ardubu:
Zustand und Zeit bei Pegeländerung merken, bei kurzer Zeit Zeit Zustand ändern bei langer Zeit Dimmwert hoch oder runterlaufen lassen.
#define EIN 2
#define DIM 9
#define DRUECKZEIT 300
uint32_t aktMillis, prellMillis, tasterMillis, dimMillis, intervall;
int dimWert, dimDelta = 5;
bool aktTaster, altTaster, pruef, dimmen = true;
void setup() {
Serial.begin(9600);
Serial.println("Start");
pinMode(EIN, INPUT_PULLUP); // gedrückt ist LOW
}
void dim() {
dimWert += dimDelta;
if (dimWert > 255) {
dimWert = 255;
dimDelta = -dimDelta;
}
if (dimWert < 0) {
dimWert = 0;
dimDelta = -dimDelta;
}
analogWrite(DIM, dimWert);
}
void loop() {
aktMillis = millis();
altTaster = aktTaster;
if (aktMillis - prellMillis >= 30) {
prellMillis = aktMillis;
aktTaster = digitalRead(EIN);
}
if (!aktTaster && altTaster) {
tasterMillis = aktMillis;
pruef = true;
}
if (pruef && aktMillis - tasterMillis >= DRUECKZEIT) {
pruef = false;
if (aktTaster) {
if (dimWert < 11) {
dimWert = 255;
} else {
dimWert = 0;
}
analogWrite(DIM, dimWert);
dimmen = false;
} else {
dimmen = true;
}
}
if (dimmen && aktTaster && !altTaster) {
dimmen = false;
}
if (dimmen && aktMillis - dimMillis >= 30) {
dimMillis = aktMillis;
dim();
}
}
combie:
Das ist die erste Grundlage für deinen endlichen Automaten.
#define EIN 2 // Tasterpin
#define DIM 9 // LED-Pin
#define ENTPRELLZEIT 30
#define DRUECKZEIT 300
#define DIMVERZOEGERUNG 100
const byte pwmtable[] PROGMEM = {0, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 90, 128, 181, 255};
const byte dimElemente = sizeof(pwmtable); // Anzahl Elemente der Tabelle
enum {WARTEN, ZEIT, DIMMEN}; // mögliche Zustände des endlichen Automaten
byte zustand = WARTEN;
uint32_t aktMillis, // Zeit seit Reset in ms
prellMillis, // relative Entprellzeit in ms
tasterMillis, // relative Zeit für Tastendruck in ms
dimMillis; // relative Zeit zum Dimmen in ms
int dimWert, // Wert für die LED; mit Vorzeichen, damit auch -1 möglich ist
dimIndex; // Feldindex
bool rauf = true, // Dimmrichtung
aktTaster, // aktueller Zustand Taster
altTaster; // alter Zustand Taster
void setup() {
pinMode(EIN, INPUT_PULLUP); // gedrückt ist LOW
}
void dim() {
if (rauf) {
dimIndex++;
} else {
dimIndex--;
}
if (dimIndex >= dimElemente) {
dimIndex = dimElemente - 2;
rauf = false; // Richtung ändern
}
if (dimIndex < 0) {
dimIndex = 1;
rauf = true; // Richtung ändern
}
dimWert = pgm_read_byte(&pwmtable[dimIndex]); // Wert aus der Tabelle ausgeben
analogWrite(DIM, dimWert);
}
void loop() {
aktMillis = millis(); // eindeutig für diese Schleife
altTaster = aktTaster;
if (aktMillis - prellMillis >= ENTPRELLZEIT) { // Taster nur gelegentlich lesen, dadurch entprellen
prellMillis = aktMillis;
aktTaster = digitalRead(EIN);
}
switch (zustand) { // endlicher Automat
case WARTEN:
if (!aktTaster && altTaster) { // wenn Taster gedrückt (Flanke)
tasterMillis = aktMillis; // Stoppuhr starten
zustand = ZEIT;
}
break;
case ZEIT:
if (aktMillis - tasterMillis >= DRUECKZEIT) {
zustand = DIMMEN; // nach der DRUECKZEIT, also langer Druck
}
if (aktTaster) { // vor der DRUECKZEIT, also kurzer Druck
if (dimWert < 127) {
dimWert = 255; // AN
} else {
dimWert = 0; // AUS
}
analogWrite(DIM, dimWert);
zustand = WARTEN;
}
break;
case DIMMEN:
if (aktTaster) { // wenn Taster Losgelassen, dann Dimmwert beibehalten
zustand = WARTEN;
}
if (aktMillis - dimMillis >= DIMVERZOEGERUNG) { // nächster Dimmschritt
dimMillis = aktMillis;
dim();
}
}
}
Endliche Automaten gefallen mir 