#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <RotaryEncoder.h> // Von https://github.com/mathertel/RotaryEncoder
//////////////////////////////////////////////////
// Funktions Vorwärtsdeklaration(en)
//////////////////////////////////////////////////
void setup(void);
void loop(void);
void start(void);
void berechne(int index);
void menue(void);
//////////////////////////////////////////////////
// Definitionen
//////////////////////////////////////////////////
#define DEBUG 1 // 0 = Serial.print aus 1 = Serial.print an
//////////////////////////////////////////////////
// Globale Konstanten und Variablen
//////////////////////////////////////////////////
// Erläuterungen:
// https://wiki.funkfreun.de/wissen/arduino_konstanten
constexpr uint8_t ENCODER_A = 3;
constexpr uint8_t ENCODER_B = 2;
constexpr uint8_t ENCODER_T = 4;
constexpr uint8_t LEDPIN = 13;
constexpr uint8_t TASTERSTART = 5;
constexpr char TEXT[][16] = {"Tausenderstelle","Hunderterstelle","Zehnerstelle","Einerstelle"};
constexpr uint16_t POTENZ[] = {1000,100,10,1}; //Bei Vergrößerung/Verkleinerung sprintf-Parameter "%04d" beachten!!
constexpr uint8_t STELLENANZAHL = (sizeof(POTENZ)/2);
// Datenstruktur für Pausenberechnug und Wertanzeige
struct Pause {
uint16_t pause;
uint16_t max = POTENZ[0] * 10;
char strBuffer[STELLENANZAHL+1];
};
Pause dataPause;
LiquidCrystal_I2C lcd(0x27, 20, 4);
//LiquidCrystal_I2C lcd(0x3F, 20, 4);
RotaryEncoder encoder(ENCODER_B, ENCODER_A, RotaryEncoder::LatchMode::FOUR3);
// Einen Anzeigepfeil für das Display definieren
byte pfeil[8] = {B00000,
B00000,
B00100,
B00100,
B10101,
B01110,
B00100};
//////////////////////////////////////////////////
// Hauptprogramm
//////////////////////////////////////////////////
void setup() {
#if DEBUG==1
Serial.begin(9600);
#endif
pinMode(ENCODER_T, INPUT_PULLUP);
pinMode(TASTERSTART, INPUT_PULLUP);
pinMode(LEDPIN, OUTPUT);
lcd.init();
lcd.createChar(0, pfeil);
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Zeiteinstellung");
lcd.setCursor(0,1);
lcd.print("mittels Encoder");
lcd.setCursor(0,2);
lcd.print("und Encoder Taster");
sprintf(dataPause.strBuffer,"%04d",dataPause.pause);
}
void loop() {
encoder.tick();
menue();
start();
}
void start() {
static boolean ledAn = false; // Wenn LED an, dann "true" (wahr)
static unsigned long lastTime;
static uint8_t tasterStartStatus;
// IF Statement verhindert, dass ein Tastendruck während die LED leuchtet, ihre Leuchtdauer beeinflusst
// bzw. dass sich die Tastendruckzeit zur Auslösezeit hinzuaddiert.
if (!ledAn) {
tasterStartStatus = digitalRead(TASTERSTART);
}
if (!ledAn && tasterStartStatus == LOW){
lastTime = millis();
ledAn = true;
digitalWrite(LEDPIN, HIGH);
#if DEBUG==1
Serial.print("Display ON ");
Serial.println(millis());
Serial.print("Wartezeit beträgt: ");
Serial.print(dataPause.strBuffer);
Serial.println(" Millisekunden");
#endif
}
if (ledAn && millis() - lastTime >= (unsigned int)dataPause.pause){ // Wenn an und Leuchtzeit vorbei
ledAn = false;
digitalWrite(LEDPIN, LOW);
#if DEBUG==1
Serial.print("Display OFF ");
Serial.println(millis());
#endif
delay(1000); // Eine Sekunde Zwangspause bevor erneut ausgelöst werden kann.
}
}
void berechne(int index) {
static uint16_t lastEncoderPos = 0;
uint16_t encoderPos=encoder.getPosition();
// Berechnung.
// Maximaler Wert = 9999
// Minimaler Wert = 0
//
if (encoderPos != lastEncoderPos) {
if (encoderPos > lastEncoderPos) {
if (dataPause.pause + POTENZ[index] < dataPause.max) {
dataPause.pause += POTENZ[index];
}
} else if (POTENZ[index] <= dataPause.pause) {
dataPause.pause -= POTENZ[index];
}
lastEncoderPos = encoderPos;
sprintf(dataPause.strBuffer,"%04d", dataPause.pause);
#if DEBUG==1
Serial.print("Encoder Position ist: ");
Serial.println(encoderPos);
Serial.print("Pause ist: ");
Serial.println(dataPause.pause);
#endif
lcd.setCursor(16,3);
lcd.print(" ");
lcd.setCursor(16,3);
lcd.print(dataPause.strBuffer);
}
}
void menue() {
static uint8_t menuePunkt=-1;
if(!digitalRead(ENCODER_T)) {
menuePunkt = (menuePunkt+1) % 4;
lcd.clear();
lcd.setCursor(16+menuePunkt,2);
lcd.write(byte(0));
lcd.setCursor(0,1);
#if DEBUG==1
Serial.println(TEXT[menuePunkt]);
#endif
lcd.print(TEXT[menuePunkt]);
lcd.setCursor(0,3);
lcd.print("FallZeit ist:");
lcd.setCursor(16,3);
lcd.print(dataPause.strBuffer);
delay(400);
}
berechne(menuePunkt);
}