Forum: Mikrocontroller und Digitale Elektronik Gehwegbeleuchtung Fading mit Taster


von Markus R. (markus_r131)


Lesenswert?

Hallo ich habe mir einen Code "zusammengebastelt" der soweit super 
funktioniert. Ziel ist es wenn man am Gartentor einen Taster betätigt 
gehen alle Gehweglampen nacheinander im Fading an. Mein Problem ist nur, 
wie kann ich nun einen Taster einbinden der das Program startet und beim 
nächsten mal drücken wieder ausschaltet aber die Lampen wierder 
Rückwärts aus dimmt?
Mir wäre es ersteinmal wichtig das man den Tater einbinden kann,der 
Funktioniert bei mir nicht.
hier mein Code.
1
int buttonPin = 8;
2
bool lastButtonState = false;
3
int pausen = 500;
4
int vals [] = {     0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
5
                    27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255
6
              };
7
int numVal = 32; //number of values in array
8
byte schwelle = 178;  // 70% * 255; Schwelle, bei der die nächste LED einsetzt.
9
byte a,b,c,d,e,f;           // Zählervariablen für 6 LEDs
10
11
unsigned long sweepstart;  // Zeit merken, zu der der Dimmprozess gestartet wurde.
12
13
void setup() {
14
  pinMode(buttonPin, INPUT_PULLUP);              // der Taster wird mit internem Pullup verwendet, d.h. er ist mit dem GND und dem digitalen Input verbunden
15
  for (int i = 2; i < 10; i++) {
16
    pinMode(i, OUTPUT);
17
    Serial.begin(112500);
18
  }
19
}
20
21
void loop() {
22
  
23
    bool myCurrentButtonState = digitalRead(buttonPin);                           // liest den aktuellen Zustand des Tasters aus
24
  if ((lastButtonState!=myCurrentButtonState)&&(myCurrentButtonState==LOW))       // wenn dieser HIGH ist, aber beim letzten Durchlauf nicht
25
  lastButtonState=myCurrentButtonState;                                           // merke dir den aktuellen Tasterzustand für den nächsten Durchlauf
26
                                                                
27
    Serial.println("change");
28
    // Zählervariablen berechnen
29
    a = min(a++, numVal-1);  // Zähler 1. LED   wird hochgezählt bis 31
30
    if (vals[a] > schwelle){   
31
      b = min(b++, numVal-1);  // Zähler 2. LED  wird hochgezählt bis 31, wenn Wert 1. LED > Schwelle,
32
    }
33
    if (vals[b] > schwelle){   
34
      c = min(c++, numVal-1);  // Zähler 3. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
35
    }
36
    if (vals[c] > schwelle){   // Zähler 4. LED  wird hochgezählt bis 31,
37
      d = min(d++, numVal-1);
38
}
39
 if (vals[d] > schwelle){
40
      e = min(e++, numVal-1);  // Zähler 5. LED  wird hochgezählt bis 31,
41
}
42
 if (vals[e] > schwelle){
43
      f = min(f++, numVal-1);  // Zähler 6. LED  wird hochgezählt bis 31,
44
45
      
46
    }
47
    analogWrite(3, vals[a]);
48
    analogWrite(5, vals[b]);
49
    analogWrite(6, vals[c]); 
50
    analogWrite(9, vals[d]);
51
    analogWrite(10, vals[e]);
52
    analogWrite(11, vals[f]);
53
    delay(10); 
54
    
55
56
57
    // Rücksetzen alle Variablen und wiederholen nach einer Pause
58
    if(millis()-sweepstart > pausen * 128){  // Ist die Wartezeit abgelaufen? (Dauer=pausen*128)
59
      a=0;                                   // Zählervariablen rücksetzen
60
      b=0;
61
      c=0;
62
      sweepstart = millis();                  // Zeitpunkt des Neustarts merken
63
    }
64
}

: Verschoben durch Moderator
von Sebastian R. (sebastian_r569)


Lesenswert?

Ein bisschen Pseudocode:
1
void loop() {
2
  if(taster_gedrueckt){
3
    if(led == aus){
4
      led_an();
5
    }
6
    else {
7
      led_aus();
8
    }
9
    while(taster_gedrueckt);
10
  }
11
}
12
13
void led_an() {
14
  ...
15
  led = an;
16
}
17
void led_aus() {
18
  ...
19
  led = aus;
20
}

Braucht noch ein paar kleinere Funktionen und Variablen/Definitionen 
drumherum, aber so als Denkanstoß sollte es funktionieren.

Kannst ja erst einmal eine bistabile Schaltung in Code bauen. Also 
komplett ohne dimmen erstmal Tastendruck LED an, Tastendruck LED aus,... 
Dann LED an und aus durch entsprechende Dimm-Funktionen ersetzen

von Markus R. (markus_r131)


Lesenswert?

Sebastian R. schrieb:
> Kannst ja erst einmal eine bistabile Schaltung in Code bauen. Also
> komplett ohne dimmen erstmal Tastendruck LED an, Tastendruck LED aus,...

ok danke also lass ich ersteinmal den versuch mit dem bool?

: Bearbeitet durch User
von Sebastian R. (sebastian_r569)


Lesenswert?

Markus R. schrieb:
> ok danke also lass ich ersteinmal den versuch mit dem bool?

Naja. Die Entscheidung, ob die Lampen nun bei Tastendruck ein- oder 
ausgeschaltet werden müssen, hängt nicht davon ab, welchen Zustand der 
Taster vorher hatte, sondern welchen Zustand die Lampen vorher hatten.

Deshalb: Überleg dir (vielleicht auch basierend auf meinem Pseudocode), 
wie man erst einmal mit Tastendruck die Lampen (oder die LED aufm Board) 
einschaltet und mit dem nächsten Tastendruck wieder ausschaltet. Du 
musst dir merken, welchen Zustand der Ausgang hat (wieder auslesen 
und/oder xor 1 ginge, aber das führt dann später zu Problemen) und 
entscheidest dann, wenn die Taste gedrückt wurde, ob du nun ein- oder 
ausschalten musst.

von Markus R. (markus_r131)


Lesenswert?

ok danke ich tüftel heute mal noch ein paar Stunden bis ichs satt 
habe:)hier nocheinmal etwas konkreter ich möchte den Taster einmal 
drücken die Lampen gehen der Reihe nach an, bleiben 60s an und gehen 
danach wieder (Programm läuft rückwärts) aus wenn der Taster bis dahin 
nicht erneut gedrückt wurde.

Ich habe wie du schon gesagt hast mit dem Beispielcode aus der IDE jetzt 
eine Led ein und aus schalten können. Wie aber sage ich dem Program das 
es anhalten soll und erst dann weiter machen wenn die Bedingung "Taster 
ein" gegeben ist?? denn den Befehlt ledPin den ich in der IDE habe gibt 
es im obigen Programm nicht.Ich muss doch die Abfrage so gestallten das 
zuerst der Taster abgefragt wird Tru False wenn Tru dann gehe im Program 
weiter wen false dann warten bis true oder?

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Markus R. schrieb:
> wenn man am Gartentor einen Taster betätigt gehen alle Gehweglampen
> nacheinander im Fading an

Markus R. schrieb:
> wierder Rückwärts aus dimmt

Welchen Sinn hat das ? Klingt wieder wie eine Informatikerlösung, 
prsktischer Unsinn. Man steht am Gartentor und die Lichterkette geht zum 
Haus hin an.

Nun geht man doch entlang des Gartenwegs zum Haus.

Soll man danach zum Gartentor zurück laufen, um den Taster zum 
Ausschalten zu drücken, und während die Lampe am Haus zuerst aus geht 
schnell wieder zum Haus in die Dunkelheit hinein rennen?

Man braucht doch zumindest einen zweiten Taster am Haus. Und wenn man 
den drückt, hat man den Weg hinter sich, die Lampen könnten schlagartig 
aus gehen.

Und wenn man tatsächlich am Gartentor bleibt weil man es sich anders 
überlegt hat, muss man dann wirklich warten bis die ganze Lichterkette 
an ist, bevor man sie wieder ausschalten kann ?

von Sebastian R. (sebastian_r569)


Lesenswert?

Markus R. schrieb:
> Wie aber sage ich dem Program das
> es anhalten soll und erst dann weiter machen wenn die Bedingung "Taster
> ein" gegeben ist?? denn den Befehlt ledPin den ich in der IDE habe gibt
> es im obigen Programm nicht.Ich muss doch die Abfrage so gestallten das
> zuerst der Taster abgefragt wird Tru False wenn Tru dann gehe im Program
> weiter wen false dann warten bis true oder?

In meinem Pseudocode ist ein Hinweis darauf versteckt.

Nicht die eleganteste Lösung, aber es geht ja darum, was zu lernen.

solange(Taster nicht gedrückt){ tu nichts }

von Markus R. (markus_r131)


Lesenswert?

An MaWin
1. bitte richtig lesen da steht was von 60sec...

2. Sin oder Unsinn mag jeder für sich selbst entscheiden, ich finde es 
schöner wenn es sanft anläuft

: Bearbeitet durch User
von Markus R. (markus_r131)


Lesenswert?

Sorry ich habe heute den ganzen Nachmittag verbraten und mir stehts bis 
oben mit dem Prog. Ich komme immer wieder zum selben Fehler der da 
wäre,das ich nicht die Ausgänge mittels Taster abschalten will sondern 
das ich bei Taster abfrage die Stelle ausklammern mus in dem der Code 
zum Andimmen steht. mit dem Vorschlag von Sebastian geht es nicht weil 
hier ein bestimmter Ausgang definiert wird (LED) ich habe aber mehrere 
Ausgänge die ich Formelbedingt nicht ausschalten kann.Somit muss das 
Programm nach Tasterabfrage ja/nein entweder übersprungen werden oder 
durchlaufen. Ich bitte nocheinmal um Hilfe. Es soll nur per Tastendruck 
angedimmt werden 60sec. an bleiben und danach wieder ausdimmen (ende des 
Programs)bis zur nächsten betätigung des Tasters. Kann ich das durch 
eine If else funktion machen und für die 60sec.ein delay? ich befürchte 
wenn ich das delay verwende stoppt der Programmablauf für 60sec. da 
benötige ich doch auch noch einen Zähler oder??

hier nochmal mein Angefangener Code:
1
int buttonPin = 8;
2
int pausen = 500;
3
int vals [] = {     0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
4
                    27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255
5
              };
6
int vals1 [] = {     255, 215, 181, 152, 128, 108, 91, 76, 64, 54, 45, 38, 32, 27, 23,
7
                    19, 16, 13, 11, 10, 8, 7, 6, 5, 4, 3, 3, 2, 2, 2, 1, 0,
8
                   
9
              };
10
int numVal = 32; //number of values in array
11
byte schwelle = 10;  // 70% * 255; Schwelle, bei der die nächste LED einsetzt.
12
byte a,b,c,d,e,f;           // Zählervariablen für 3 LEDs
13
14
unsigned long sweepstart;  // Zeit merken, zu der der Dimmprozess gestartet wurde.
15
16
void setup() {
17
  for (int i = 2; i < 10; i++) {
18
    pinMode(i, OUTPUT);
19
      pinMode(buttonPin, INPUT_PULLUP);     // der Taster wird mit internem Pullup verwendet, d.h. er ist mit dem GND und dem digitalen Input verbunden
20
21
  }
22
}
23
24
void loop() {
25
bool myCurrentButtonState = digitalRead(buttonPin);
26
27
28
  
29
    // Zählervariablen berechnen
30
    a = min(a++, numVal-1);  // Zähler 1. LED   wird hochgezählt bis 31
31
    if (vals[a] > schwelle){   
32
      b = min(b++, numVal-1);  // Zähler 2. LED  wird hochgezählt bis 31, wenn Wert 1. LED > Schwelle,
33
    }
34
    if (vals[b] > schwelle){   
35
      c = min(c++, numVal-1);  // Zähler 3. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
36
    }
37
    if (vals[c] > schwelle){
38
      d = min(d++, numVal-1); // Zähler 4. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
39
    }
40
    if (vals[d] > schwelle){
41
      e = min(e++, numVal-1); // Zähler 5. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
42
    }
43
     if (vals[e] > schwelle){
44
      f = min(f++, numVal-1); // Zähler 6. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
45
46
      
47
    }
48
    analogWrite(3, vals[a]);
49
    analogWrite(5, vals[b]);
50
    analogWrite(6, vals[c]); 
51
    analogWrite(9, vals[d]);
52
    analogWrite(10, vals[e]);
53
    analogWrite(11, vals[f]);
54
    delay(20); 
55
    
56
57
58
    // Rücksetzen alle Variablen und wiederholen nach einer Pause
59
    if(millis()-sweepstart > pausen * 128){  // Ist die Wartezeit abgelaufen? (Dauer=pausen*128)
60
      a=0;                                   // Zählervariablen rücksetzen
61
      b=0;
62
      c=0;
63
      d=0;
64
      e=0;
65
      f=0;
66
      sweepstart = millis();                  // Zeitpunkt des Neustarts merken
67
    }
68
}

: Bearbeitet durch User
von Markus R. (markus_r131)


Lesenswert?

Keiner eine Idee wie ich den Taster einbinden kann?

von STK500-Besitzer (Gast)


Lesenswert?

Markus R. schrieb:
> Keiner eine Idee wie ich den Taster einbinden kann?

Du brauchst noch mindestens eine weitere Variable, die sich merkt, ob 
ein Fading läuft oder nicht.
Die Variable könnte sich auch gleichzeitig dir Richtung merken: +1, 0, 
-1
0: Kein Fading
+1: Einschalt-Fading
-1: Ausscahlt-Fading

von Markus R. (markus_r131)


Lesenswert?

jetzt habe ich es hinbekommen den Taster einzubinden. nun möchte ich 60 
sekunden lang die Leds eingeschaltet lassen und danach wieder ausdimmen. 
beim nächsten Tastenstart soll alles wieder von vorn beginnen.Hier 
nocheinmal der funktionierende Code. Wenn ich es mit (mills) versuche 
erwartet das Programm ja immer auch eine Aktion was es danach machen 
soll.Wie kann ich es so Schreiben das es 60sek.wartet und dann die 
nächsten Programmzeilen weiter ab arbeitet? Also das wäre dan das 
Abdimmen.Formel Kopieren und Werte negieren ??
1
int buttonPin = 8; 
2
bool lastbuttonPin = true;           // der Zustand des Buttons beim letzten Schle
3
int pausen = 5000;
4
int vals [] = {     0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
5
                    27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255 };
6
int numVal = 32; //number of values in array
7
byte schwelle = 10;  // 70% * 255; Schwelle, bei der die nächste LED einsetzt.
8
byte a,b,c,d,e,f;           // Zählervariablen für 3 LEDs
9
10
unsigned long sweepstart;  // Zeit merken, zu der der Dimmprozess gestartet wurde.
11
12
13
14
void setup() {
15
 pinMode(buttonPin, INPUT_PULLUP);
16
  
17
  }
18
19
20
void loop() {
21
bool myCurrentbuttonPin = digitalRead(buttonPin);                           // liest den aktuellen Zustand des Tasters aus
22
  if ((lastbuttonPin!=myCurrentbuttonPin)&&(myCurrentbuttonPin==LOW))    // wenn dieser HIGH ist, aber beim letzten Durchlauf nicht
23
 
24
  
25
    // Zählervariablen berechnen
26
    a = min(a++, numVal-1);  // Zähler 1. LED   wird hochgezählt bis 31
27
    if (vals[a] > schwelle){   
28
      b = min(b++, numVal-1);  // Zähler 2. LED  wird hochgezählt bis 31, wenn Wert 1. LED > Schwelle,
29
    }
30
    if (vals[b] > schwelle){   
31
      c = min(c++, numVal-1);  // Zähler 3. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
32
    }
33
    if (vals[c] > schwelle){
34
      d = min(d++, numVal-1); // Zähler 4. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
35
    }
36
    if (vals[d] > schwelle){
37
      e = min(e++, numVal-1); // Zähler 5. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
38
    }
39
     if (vals[e] > schwelle){
40
      f = min(f++, numVal-1); // Zähler 6. LED  wird hochgezählt bis 31, wenn Wert 2. LED > Schwelle,
41
42
      
43
    }
44
    analogWrite(3, vals[a]);
45
    analogWrite(5, vals[b]);
46
    analogWrite(6, vals[c]); 
47
    analogWrite(9, vals[d]);
48
    analogWrite(10, vals[e]);
49
    analogWrite(11, vals[f]);
50
    delay(20); 
51
    
52
53
54
    // Rücksetzen alle Variablen und wiederholen nach einer Pause
55
    if(millis()-sweepstart > pausen * 128){  // Ist die Wartezeit abgelaufen? (Dauer=pausen*128)
56
      a=0;                                   // Zählervariablen rücksetzen
57
      b=0;
58
      c=0;
59
      d=0;
60
      e=0;
61
      f=0;
62
      sweepstart = millis();                  // Zeitpunkt des Neustarts merken
63
    }
64
}

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Ich würds mit Statemaschine (switch/case) machen.

von Markus R. (markus_r131)


Lesenswert?

Ok leider habe ich mit switch / case keine Ahnung wie ich da anfangen 
soll um ein break von 60Sek. ausführen zu können.

: Bearbeitet durch User
von Pflasterstein (Gast)


Lesenswert?

Peter meint, dass du eine State-Maschine realisieren sollst.

Im switch/case hast du dann alle deine States und schreibst dazu den 
Code, der im jeweiligen State ausgeführt werden soll.

Ansonsten ließ mal wie du am besten einen Taster verwenden solltest:
https://www.arduino.cc/en/tutorial/debounce
(Hier gibt es von Peter D. eine wunderschöne Lib, aber die ist denke ich 
für den Anfang zu schwierig nachzuvollziehen.)

Und wie du Zeitintervalle festlegen kannst:
https://www.arduino.cc/en/tutorial/BlinkWithoutDelay

von Markus R. (markus_r131)


Lesenswert?

Ok, aber möchte das alles nicht zu komplex gestalten daher dachte ich es 
wäre einfacher wenn man nach dem hoch faden hochzählt bis 60sek. Und 
danach das abdimm Programm Schreibt was im Anschluss abläuft.

von Pflasterstein (Gast)


Lesenswert?

Markus R. schrieb:
> Ok, aber möchte das alles nicht zu komplex gestalten daher dachte
> ich es
> wäre einfacher wenn man nach dem hoch faden hochzählt bis 60sek. Und
> danach das abdimm Programm Schreibt was im Anschluss abläuft.

Das kannst du gerne so machen. Die Erfahrung zeigt, dass es immer 
weniger Komplex wird, wenn man es richtig macht.

Dein nach dem Faden hochzählen kannst du ja mit delay() erledigen, oder 
falls es retriggerbar sein soll mit Hilfe aus dem letzten Link.

von Nosnibor (Gast)


Lesenswert?

Ja, Zustandsmaschinen, für jedes Teilproblem eine:

1. Taster. Das sieht ja schon gut aus: aktuellen Eingangswert mit dem 
vorigen vergleichen, Aktivität nur bei Änderung, und nur wenn der Taster 
gedrückt wurde, wird der Sollwert für das Licht geändert: von "aus" nach 
"ein" oder umgekehrt. Entprellen ist wahrscheinlich nicht nötig, da ja 
schon 10 (oder jetzt 20) ms delay in der Hauptschleife steht.

2. Licht. Je nach Sollwert (ein oder aus) einen anderen Algorithmus 
nutzen. Den für "ein" hast du ja schon. Der sieht übrigens gut aus, 
durch das min() ist er robust gegen unsinnige Werte in den Variablen, 
wie sie vielleicht entstehen könnten, wenn jemand mitten beim Ausfaden 
wieder einschaltet.

3. Timer. Der muß gestartet werden, sobald der Sollwert auf "ein" geht, 
und wenn er abläuft, stellt er den Sollwert auf "aus". Timerstart heißt: 
aktuelle millis() merken. Solange der Sollwert "ein" ist, muß man eben 
bei jedem Schleifenduchlauf prüfen, ob der Start zu lange her ist, also 
millis() - Startzeit zu groß.

Die drei Maschinen laufen praktisch unabhängig voneinander und sind nur 
durch wenige globale Variablen (Sollwert und Timer-Startzeitpunkt) 
miteinander verbunden. Bedingung dafür ist natürlich, daß der 
Programmablauf nirgendwo durch irgendwelche delay()-Orgien oder 
sonstiges Abwarten aufgehalten wird.

von Peter D. (peda)


Lesenswert?

Markus R. schrieb:
> Ok, aber möchte das alles nicht zu komplex gestalten

Im Gegenteil, jetzt ist es komplex und völlig unerweiterbar.
Eine Statemaschine macht alles wesentlich einfacher.
Z.B. der Tastendruck wechselt von STOP zu FADE_A. Ist FADE_A fertig 
wechselst Du zu FADE_B usw.
Du mußt also nicht ständig alles machen, sondern nur das für die Aktion 
nötige.
1
switch (state)
2
{
3
case STOP:   if (get_key())
4
               state = FADE_A;
5
             break;
6
case FADE_A: if (++a >= FADE_MAX)
7
               state = FADE_B;
8
             break;
9
case FADE_B: if (++b >= FADE_MAX)
10
               state = FADE_C;
11
             break;
12
// ...
13
case DIMM_F: if (--f == 0 )
14
               state = DIMM_E;
15
             break;
16
// usw.
17
}
Dann fällt es auch leicht, weitere States hinzuzufügen.
Die States definiert man vorzugweise mit einem enum.

von Markus R. (markus_r131)


Lesenswert?

Danke aber bei deinem Vorschlag Faden die LEDs nacheinander bei mir 
gehen die ineinander über  ab 20% geht die nächste los unsw. Ich kann da 
auch nicht sehen das es eine Minute wartet?

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

man kann es auch in 4 States aufteilen: stateIDLE (wartend), 
stateFadeUp, stateDelay, stateFadeDown. Die malt man sich als 4 Kreise 
auf ein Blatt und dann Pfeile vom einen Zustand zum anderen. An die 
Pfeile schreibt man wann diese Zustandsänderung passiert.
Das ist für diese Sequenz noch sehr einfach, aber so bekommt man auch 
Erweiterungen übersichtlich hin. Z.B. einen Bewegungsmelder der nur 
einschaltet, oder Taste lang drücken um Helligkeit fest dauerhauft 
einzuschalten, Doppelklick zum Ausschalten.
Und FadeUp/Down in ein Unterprogramm packen, dann bleibt switch/case 
übersichtlicher.
Was man versthen muss ist das kein Teil lange blockieren darf. Die loop 
mit Eingänge auswerten und switch/case rennt immer schnell im Kreis. Nur 
bei Zustandsänderung wird über die switch Variable auf eine andere 
Funktion umgeschaltet.

von Markus R. (markus_r131)


Lesenswert?

Danke und wie sieht es dann mit dem Code aus ich habe echt keinen Ansatz 
mehr wie es aussehen muss damit es funktioniert.

von STK500-Besitzer (Gast)


Lesenswert?

Peter D. schrieb:
> Ich würds mit Statemaschine (switch/case) machen.

Die Verwendung weiterer Arrays würde die Übersicht und 
Modularisierbarkeit erhöhnen.

von Johannes S. (Gast)


Angehängte Dateien:

Lesenswert?

so als Vorlage:
- button an Pin2 startet state machine
- Meldungen über serielle werden ausgegeben, eine LED dimmt rauf/runter

Das fade() muss dann noch die Logik für die vielen LED bekommen.
Für sowas einfaches mit Kanonen mit auf Spatzen, aber dafür 
Erweiterbar...
Das delay ist global, daher ist ein stateDelay hier nicht drin.

von Markus R. (markus_r131)


Lesenswert?

Vielen Dank für deine Mühe aber ich sehe da nicht mehr durch, ich muss 
da noch sehr viel lernen. Ich versuch mich heute Abend nach der Arbeit 
mal daran.

von Johannes S. (Gast)


Lesenswert?

dafür sind die Ausgaben auf die serielle Schnittstelle drin, 
Werkzeuge/Serieller Monitor ist hoffentlich bekannt?

Der Ablauf in loop() ist:
1
checkInputs()
2
  Entprellzeit 20 ms abwarten
3
  Taster einlesen
4
  bei Änderung über startSequence() die Schrittkette anstossen
5
6
processDelay()
7
  wenn die (globale) Verzögerungszeit >0 ist,
8
  dann warten, sonst Wartezeit löschen
9
10
processStateMachine()
11
  wenn wartezeit aktiv, dann nix machen
12
  Meldung ausgeben wenn state sich geändert hat
13
  Aktion abhängig vom State ausführen

state ist zunächst nix tun, bis der über die Taste auf FadeUp gesetzt 
wird. Dann landet processStateMachine immer wieder in fade(). Bis es 
fertig meldet, dann wird eine Pause gesetzt (als Demo 3s) und der 
nächste Schritt auf fadeDown gesetzt. Weil die Verzögerung jetzt >0 ist, 
wird fadeDown aber erst nach Ablauf der Verzögerungszeit erreicht. Wenn 
fade() jetzt fertig meldet wird wieder auf warten geschaltet.
fade() kann machen was es will, es darf nur nicht blockieren. Das loop() 
führt dann immer wieder die 3 Funktionen aus und kann damit jederzeit 
auf die Taste (oder auch andere Eingänge) reagieren. Wenn man in einem 
stat ungleich idle ist, könnte man mit der Taste auch ein stop auslösen 
(LED aus, state auf idle setzen).

Hoffe es war einigermassen verständlich.

von Markus R. (markus_r131)


Lesenswert?

Super ! das funktioniert Danke bis dahin ist auch super erklärt! aber in 
welchen Teil deines Sketches kann ich jetzt meine Routine einbinden? in 
der "VOID Loop" wie vorher geht das jetzt bestimmt nicht mehr so einfach 
oder? Ich muss jetzt meine Variablen ändern da er ja nicht mehr über 
vals hoch zählt (0-255) sondern über deine Formel trotzdem muss ich 
jetzt sagen das er die erste LED bis 20% andimmen soll und weiter bis 
255 aber gleichzeitig bei ereichen von 21% die zweite Led anfangen soll 
unsw. damit es einen weichen Übergang untereinander gibt.

[c]
 // Zählervariablen berechnen
    a = min(a++, numVal-1);  // Zähler 1. LED   wird hochgezählt bis 31
    if (vals[a] > schwelle){
      b = min(b++, numVal-1);  // Zähler 2. LED  wird hochgezählt bis 
31, wenn Wert 1. LED > Schwelle,
    }
    if (vals[b] > schwelle){
      c = min(c++, numVal-1);  // Zähler 3. LED  wird hochgezählt bis 
31, wenn Wert 2. LED > Schwelle,
    }
    if (vals[c] > schwelle){
      d = min(d++, numVal-1); // Zähler 4. LED  wird hochgezählt bis 31, 
wenn Wert 2. LED > Schwelle,
    }
    if (vals[d] > schwelle){
      e = min(e++, numVal-1); // Zähler 5. LED  wird hochgezählt bis 31, 
wenn Wert 2. LED > Schwelle,
    }
     if (vals[e] > schwelle){
      f = min(f++, numVal-1); // Zähler 6. LED  wird hochgezählt bis 31, 
wenn Wert 2. LED > Schwelle,


    }
    analogWrite(3, vals[a]);
    analogWrite(5, vals[b]);
    analogWrite(6, vals[c]);
    analogWrite(9, vals[d]);
    analogWrite(10, vals[e]);
    analogWrite(11, vals[f]);
    delay(20);
[c/]

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

Das gehört in die fade() Funktion, das jetzige LED rauf/runter war nur 
ein Beispiel für den Test. Ein Argument für die Richtung ist ja schon 
drin, damit kann beides in eine Funktion. Fade() wird auch zyklisch 
aufgerufen, wie vorher in loop(). Mit dem Unterschied das es jetzt nur 
gestartet wird wenn es im Ablauf dran ist.
Und das delay(20) wird jetzt praktisch am Anfang gemacht und muss weg, 
sonst würde es ja die ganze Ausführung für 20 ms blockieren.

von Peter D. (peda)


Lesenswert?

Johannes S. schrieb:
> Das gehört in die fade() Funktion

Man kann dafür auch eine 2. Statemaschine implementieren.
Je feiner man Code unterteilt, umso übersichtlicher wird er.

von Johannes S. (Gast)


Lesenswert?

ja, richtig. Nur sind in vielen Arduino Programmen schon Unterprogramme 
Luxus und für einen Anfänger vielleicht eher unübersichtlich :)
Nur wenn Code wächst und dann in eine 1 m lange loop ausartet ist es 
meist zu spät. Wenn die eine Schrittkette verstanden wurde kommt der TO 
hoffentlich auch weiter.

Die fade() Funktion kann man auch mit einem Schieberegister bauen: ein 
Array mit Wert für jede Led, nach jedem 200 ms Schritt alle Werte um 
eine Position weiterschieben und den nächsten Helligkeitswert aus der 
Tabelle an Anfang (oder Ende für runterdimmen) setzen.
Aber dann wäre ja garnix mehr vom original Code übrig.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.