PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einschalt-Sequenzer mir Arduino-UNO



Andi#87
15.05.2022, 18:16
Hallo,

ich möchte mir eine Einschalt-Verzögerung mit dem Arduino-UNO bauen. Möchte eine Taste (Taster momentary) kurz drücken, dann sollen in einer gewissen Reihenfolge am Arduino 5 LEDs angehen. Nach nochmaligem Drücken des Tasters sollen die LEDs dann wieder ausgehen. Anhand diverser Beschreibungen/Beispiele zu Button/LED und Verzögerungen usw., die ich gefunden habe, habe ich diesen Sketch zusammengesetzt. Er funktioniert, aber ich möchte da einiges noch ändern. Jedoch weiß ich nicht wie.

Im Moment schalten die LED nach dem Tastendruck in der Reihenfolge 1-2-3-4-5 im Intervall von je 1000 msek ein und bleiben dann angeschaltet. Drücke ich den Taster nochmals, dann schalten sich die LED wieder in derselben Reihenfolge aus wie beim anschalten (also 1-2-3-4-5 und wieder mit Intervall 1000 msek). Nun möchte ich beim Ausschalten aber eine andere Reihenfolge festlegen (aber mit jeweils anderer Zeitverzögerung als die bisherigen 1000 msek), z.B. 5-3-4-1-2. Hier weiss ich nicht, wie das gemacht wird. Es muss die Ausschalt-Reihenfolge nun ja entsprechend anders nochmals eingetragen werden. Kann mir jemand helfen?

Andi







int button = 2;

int led1 = 3;
int led2 = 4;
int led3 = 5;
int led4 = 6;
int led5 = 7;

int status = false;

void setup()
{
pinMode(button, INPUT_PULLUP);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
}

void loop()
{
if (digitalRead(button) == true)
{
status = !status;
delay(1000);
digitalWrite(led1, status);
delay(1000);
digitalWrite(led2, status);
delay(1000);
digitalWrite(led3, status);
delay(1000);
digitalWrite(led4, status);
delay(1000);
digitalWrite(led5, status);
}
while(digitalRead(button) == true);
delay(50);
}

Gnom67
15.05.2022, 23:17
Probier mal:


status = !status;
if status == true {
digitalWrite(led1, status);
delay(1000);
digitalWrite(led2, status);
delay(1000);
digitalWrite(led3, status);
delay(1000);
digitalWrite(led4, status);
delay(1000);
digitalWrite(led5, status);
}
else {
digitalWrite(led5, status);
delay(1000);
digitalWrite(led3, status);
delay(1000);
digitalWrite(led4, status);
delay(1000);
digitalWrite(led2, status);
delay(1000);
digitalWrite(led1, status);
}

Andi#87
17.05.2022, 10:15
Hallo,

es funktioniert. Musste nur noch die beiden runden Klammern nach dem "if" einfügen. Hab vielen Dank für Deine Hilfe :-)

Andi

Andi#87
26.05.2022, 10:52
Hallo,
möchte hier nochmal nachhaken. Der Sketch funktioniert, dass hatte ich schon geschrieben. Nochmals danke für die Hilfe.
Im Moment arbeitet das so, dass die Einschaltsequenz dann startet, wenn ich den Button drücke. Wenn ich denselben Button dann nochmals drücke, schaltet sich das wieder entsprechend der vorgemerkten Einstellungen aus (Ausschaltsequenz).
Was muss ich ändern im Sketch, wenn ich folgende Funktion möchte:
Die Einschaltsequenz soll starten, sobald der Arduino mit Strom versorgt wird, bzw. 5 Sekunden, nachdem der Arduino mit dem Strom verbunden wurde, soll die Einschaltsequenz automatisch starten, ohne dass ich also den "Start"-Button drücken muss. Das Ausschalten soll dann jedoch wieder geregelt als Ausschaltsequenz über den Button erfolgen.
Geht das?

Andi

Hubert.G
26.05.2022, 20:10
Die Einschaltsequenz und Verzögerung vor dem loop einfügen.

021aet04
26.05.2022, 20:32
Ich würde es etwas anders machen. Auch wenn es so funktioniert.

Ich würde es mit Switch Case machen. Es ist so leichter wartbar bzw änderbar.

Mfg Hannes

Andi#87
28.05.2022, 13:55
Danke für die Antworten. Ich hab es vor dem Loop eingesetzt (Switch/Case... soweit bin ich noch nicht). Das sieht dann so aus:

__________________________________________________ ____


int button = 2;

int led1 = 3;
int led2 = 4;
int led3 = 5;
int led4 = 6;
int led5 = 7;

int status = false;

void setup()
{
pinMode(button, INPUT_PULLUP);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);

delay(5000);
digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led2, HIGH);
delay(1000);
digitalWrite(led3, HIGH);
delay(1000);
digitalWrite(led4, HIGH);
delay(1000);
digitalWrite(led5, HIGH);
}

void loop()
{
if (digitalRead(button) == true)
{
status = !status;
if (status == true)
{
delay(1000);
digitalWrite(led1, status);
delay(1000);
digitalWrite(led2, status);
delay(1000);
digitalWrite(led3, status);
delay(1000);
digitalWrite(led4, status);
delay(1000);
digitalWrite(led5, status);
}
else
{
delay(1000);
digitalWrite(led5, LOW);
delay(500);
digitalWrite(led3, LOW);
delay(500);
digitalWrite(led4, LOW);
delay(500);
digitalWrite(led2, LOW);
delay(500);
digitalWrite(led1, LOW);
}
}
while(digitalRead(button) == true);
delay(50);

}


__________________________________________________ ____


(sorry, ich finde wieder mal nicht das Symbol für "Code-Einfügen", deshalb nur per Linie optisch abgegrenzt)


Nun schaltet das zwar an wie gewünscht (5 Sek nach Stromzufuhr), aber ich kann es nicht mehr ausschalten. Wo muss ich da ansetzen?

Andi

021aet04
28.05.2022, 16:48
Wenn du einen Code einfügen willst, schreibst du vor dem Code einfach [ c o d e ] und nach dem Code [ / c o d e ] (Leerzeichen entfernen).

Dann sieh es so aus.

Hier steht dein Code

Der Switch Befehl ist relativ einfach.
Du benötigst eine Zählvariable (Integer), mehr nicht.
Ich habe in der Arduino Referenz geschaut wie es funktioniert (Verwende das Atmel Studio und nicht die Arduino IDE).

https://www.arduino.cc/reference/de/language/structure/control-structure/switchcase/

Aber im Prinzip schaut die Schleife so aus:


switch (Zählvariable)
{
case 0:
// Statement(s)
digitalWrite(led1, HIGH);
delay(1000);

// Wichtig: Die Zählvariable muss auf den nächsten Wert geschalten werden
Zählvariable = 1;
break;
case 1:
// Statement(s)
digitalWrite(led2, HIGH);
delay(1000);


// Wichtig: Die Zählvariable muss auf den nächsten Wert geschalten werden
Zählvariable = 2;
break;

.................
.................
.................

default: // Statement(s) break; // Wird nicht benötigt, wenn Statement(s) vorhanden sind
}

Der Default Zweig sollte immer eingefügt werden. Der Default Zweig wird immer verwendet, wenn es für den aktuellen Wert der Zählvariable keinen Case gibt.
Also wenn du im oberen Beispiel z.B. "3" schreibst.

Ich habe oben nur 2 Cases geschrieben, du musst es noch erweitern.

Wenn der Ein- Ausschaltvorgang unterschiedlich sein soll, benötigst du 2 Switch Case Strukturen.
Was du bei der Switch Case Anweisung wissen musst ist, das immer der Case bearbeitet wird und danach unter dem Case weiterläuft. Das steht aber in dem Link.

Die Zählvariable zählst du einfach hoch oder runter. Je nachdem ob du Ein- oder Aus schaltest.

Wenn du Hilfe benötigst helfe ich gerne weiter.

Warum dein Programm nicht funktioniert weiß ich nicht.
Du könntest aber versuchen statt
"status = !status" in
"status = ~status" zu ändern.

Edit: Was ich an der Arduino IDE richtig sch..... finde ist, das es nicht einmal einen Simulator gibt. Bei dem Atmel Studio ist das schon eine richtig gute Funktion. Wenn man einen Debugger hat, ist das natürlich viel besser, den gibt es aber in der Arduino IDE ebenfalls nicht.

MfG Hannes

Andi#87
28.05.2022, 17:35
Danke :-)
Diesen Artikel zu Switch/Case hatte ich mir schon angeschaut nach Deiner ersten Antwort. Dazu gibt es auch Videos in YT, eines fand ich ganz aufschlussreich. Ich melde mich wieder, sobald ich damit weitergekommen bin.
Nochmals Danke.
Andi

Andi#87
29.05.2022, 13:00
Hallo,

ich hab es zunächst nun doch erstmal nach der "einfachen" Methode probiert (Switch Case muss ich mir in Ruhe anschauen). Und bin ganz glücklich, es hinbekommen zu haben, zumindest hoffe ich das. Denn es funktioniert so, wie ich es wünschte. Darf ich Euch trotzdem bitten, mal drüber zu schauen, ob das auch wirklich korrekt ist, was ich da gemacht habe?

Funktion soll ja sein, dass die LEDs 2 Sek nach Arduino-Stromzufuhr automatisch ganz ohne zusätzlichen Tastendruck angehen (jeweils mit Verzögerung, hier im Bsp dann je 200 mSek). Nur zum ausschalten möchte ich den Taster verwenden.




int button = 2;

int led1 = 3;
int led2 = 4;
int led3 = 5;
int led4 = 6;
int led5 = 7;

void setup()

{
pinMode(button, INPUT_PULLUP);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);

delay(2000);
digitalWrite(led1, HIGH);
delay(200);
digitalWrite(led2, HIGH);
delay(200);
digitalWrite(led3, HIGH);
delay(200);
digitalWrite(led4, HIGH);
delay(200);
digitalWrite(led5, HIGH);
}

void loop()
{
if (digitalRead(button) == LOW)
{
delay(2000);
digitalWrite(led5, LOW);
delay(200);
digitalWrite(led3, LOW);
delay(200);
digitalWrite(led4, LOW);
delay(200);
digitalWrite(led2, LOW);
delay(200);
digitalWrite(led1, LOW);
}
{
while(digitalRead(button) == true);
delay(50);
}
}



Ist das so richtig? Oder gibt es da noch Stellen, die anders bzw. besser gemacht werden können?

Andi

Rabenauge
01.06.2022, 08:11
Da kann man eine ganze Menge verbessern- muss man aber nicht.
Wenn du tiefer einsteigen, und später auch grössere Programme schreiben willst, wärs eine gute Übung, sämtliche delay() aus dem Programm zu verbannen.
delay() hat nämlich einen Nachteil: der Controller tut...nichts, ausser ab und zu auf die Uhr zu schauen.
In komplexeren Programmen ist das oft doof, weil in der Wartezeit andere Dinge erledigt werden könnten.

Wenn du wissen willst, wie man die delay() los wird, schau dir mal das Beispielprogramm blinkWithoutDelay an, was du unter Beispiele in der Arduino-IDE findest. Das ist ein Grundgerüst für nen Timer, den man für alles Mögliche benutzen kann.
Beispielsweise das Entprellen des Tasters (ich nehme an, das soll dieses delay(50) bewirken), kann man damit eleganter lösen.

Auch könntest du den Button über nen Interrupt anbinden, so stört der den normalen Programmablauf nur dann, wenn es unbedingt nötig ist.
Da du ihn an Pin2 hast, sollte das bei den meisten Arduinos klappen.

Wo ich grade nicht sicher bin (könnte sein, das optimiert der Compiler selber): int ist ne recht grosse Zahl.
So viel Speicher brauchst du für die Pin-Definitionen gar nicht, das kann man alles mit byte machen.
Gelegentlich landet man beim Speicherverbrauch an der oberen Grenze, da ist man froh über jedes Byte, was man irgendwo eingespart hat.

Das alles ist aber nicht nötig, wenn dein Programm tut, was es soll...sind eher empfehlenswerte Übungen für später.

Andi#87
01.06.2022, 16:43
Vielen Dank für Deine Antwort. "Programm tut, was es soll", aber natürlich möchte ich auch weitere Dinge lernen, von daher ist das eine gute Gelegenheit, an diesem übersichtlichen und an sich unkomplizierten Programm solche Dinge zu lernen, ohne den Durchblick zu verlieren. Das schaue ich mir an, danke für Deine vielen Hinweise dazu.

Andi