Mein Code:
#define MAX 10
const int LED1 = 2;
const int LED2 = 8;
const int LED3 = 4;
const int LED4 = 5;
int val;
int array[MAX];
int counter = 0;
int i;
int old_b = 0;
int error;
void setup() {
Serial.begin(9600);
pinMode(A5, INPUT_PULLUP);
}
int readButtons(int pin) {
int b,c;
c=analogRead(pin);
Serial.print("analogRead = ");
Serial.println(c);
delay(100);
if (c>1015) b = 0;
else if (c>70 && c<76) b = 1;
else if (c<128 && c>122) b = 2;
else if (c>169 && c<175) b = 3;
else if (c>209 && c<217) b = 4;
else if (c>247 && c<256) b = 5;
else if (c>280 && c<291) b = 6;
else b = 0;
if (b == old_b) {
return 0;
old_b = b;
} else {
return b;
stari_b = b;
}
}
void loop() {
while ((val = readButtons(5)) != 5) {
if (val == 1) {
array[counter] = 1;
counter++;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println("1");
delay(500);
} else if (val == 2) {
array[counter] = 2;
counter++;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println("2");
delay(500);
} else if (val == 3) {
array[counter] = 3;
counter++;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println("3");
delay(500);
} else if (val == 4) {
array[counter] = 4;
counter++;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println("4");
delay(500);
}
if (counter == MAX) {
counter = 0;
}
}
for (i = 0; i < MAX; i++) {
if (array[i] == 1) {
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
delay(1000);
digitalWrite(LED3, LOW);
digitalWrite(LED4, LOW);
delay(1000);
Serial.print("Executing ");
Serial.print(i);
Serial.print(" ");
Serial.println(array[i]);
delay(500);
}
if (array[i] == 2) {
digitalWrite(LED1, HIGH);
digitalWrite (LED2, HIGH);
delay(1000);
digitalWrite(LED1, LOW);
digitalWrite(LED2,LOW);
delay(1000);
Serial.print("Executing ");
Serial.print(i);
Serial.print(" ");
Serial.println(array[i]);
delay(500);
}
if (array[i] == 3) {
digitalWrite(LED2, HIGH);
digitalWrite(LED4, HIGH);
delay(1000);
digitalWrite(LED2, LOW);
digitalWrite(LED4, LOW);
delay(1000);
Serial.print("Executing ");
Serial.print(i);
Serial.print(" ");
Serial.println(array[i]);
delay(500);
}
if (array[i] == 4) {
digitalWrite(LED1, HIGH);
digitalWrite(LED3, HIGH);
delay(1000);
digitalWrite(LED1, LOW);
digitalWrite(LED3, LOW);
Serial.print("Executing ");
Serial.print(i);
Serial.print(" ");
Serial.println(array[i]);
delay(500);
}
}
}
Also habe ich Tasten so verbunden , außer ich habe sie 5. Wenn eine der ersten vier gedrückt wird, speichert Sketch 1,2,3 oder 4, um anzugeben, welche Tasten gedrückt wurden, und speichert es in einem Integer-Array. Wenn die fünfte Taste (die "GO"-Taste) gedrückt wird, endet die Schleife und startet die for-Schleife, die entsprechend den gedrückten Tasten LEDs blinkt. Ich möchte das machen, während Arduino LEDs blinkt, das heißt, während die for-Schleife ausgeführt wird, wenn zu irgendeinem Zeitpunkt die fünften "GO" -Tasten gedrückt werden, sollte es aufhören, LEDs zu blinken und das Programm von Anfang an zu starten ( void loop { ... } ), das heißt wieder auf das Drücken der ersten vier Tasten warten.
Ich habe es geschafft, dies zu machen:
#define MAX 50
const int LED1 = 2;
const int LED2 = 3;
const int LED3 = 4;
const int LED4 = 5;
int array[MAX];
int old_b = 0;
int val;
int counter = 0;
int i;
int temp;
int L1;
int L2;
void setup () {
pinMode (A5, INPUT_PULLUP);
Serial.begin(9600);
}
int readButtons (int pin) {
int b, c;
c = analogRead(pin);
Serial.print("analogRead = ");
Serial.println(c);
delay(100);
if (c > 1015) b = 0;
else if (c > 70 && c < 76) b = 1;
else if (c > 122 && c < 128) b = 2;
else if (c > 169 && c < 175) b = 3;
else if (c > 209 && c < 217) b = 4;
else if (c > 247 && c < 256) b = 5;
else if (c > 280 && c < 291) b = 6;
else b = 0;
if (b == old_b) {
return 0;
old_b = b;
} else {
return b;
old_b = b;
}
}
void loop () {
while ((val = readButtons(5)) != 5) {
if ((val == 1) || (val == 2) || (val == 3) || (val == 4)) {
array[counter] = val;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println(val);
delay(200);
counter++;
if (counter == MAX) {
counter = 0;
}
}
}
temp = counter;
counter = 0;
for (i = 0; i < temp; i++) {
if (array[i] % 2 == 0) {
L1 = 2;
L2 = array[i] / 3 + 3;
} else {
L2 = 5;
L1 = array[i] % 3 + 3;
}
if (readButtons(5) != 5) {
digitalWrite (L1, HIGH);
if (readButtons(5) != 5) {
digitalWrite (L2, HIGH);
delay(1000);
digitalWrite (L1, LOW);
digitalWrite (L2, LOW);
if (readButtons(5) == 5) {
i = temp;
}
} else {
digitalWrite (L1, LOW);
i = temp;
}
}
}
}
Ich habe also noch eine Funktion, die erkennt, ob eine Taste gedrückt wurde. Zuvor habe ich ermittelt, in welchem Bereich Werte für bestimmte Schaltflächen liegen. Imwhile () {...}
Schleife, während die 5. Taste nicht gedrückt wird, "schaut" Arduino, ob eine der ersten vier Tasten gedrückt wurde. Wenn es war, speichern Sie es in einem Array und wenn nicht, "suchen Sie weiter". Wenn die 5. Taste gedrückt wird, brechen wir aus und speichern die letzte bekannte Stelle im Array, in der der Wert gespeichert wurde, und setzen den Stellenzähler auf Null, sodass Arduino beim erneuten Starten die Werte an der ersten Stelle des Arrays speichert. Dann bestimme ich basierend auf dem, was gespeichert ist, welcher Pin/LED aufleuchten wird. Wenn zu irgendeinem Zeitpunkt während der blinkenden LEDs die 5. Taste erneut gedrückt wird, stoppt Arduino das Blinken und wartet erneut auf die Betätigung der ersten vier Tasten. So soll es theoretisch funktionieren. In der Praxis kann ich es immer noch nicht dazu bringen, jedes Mal zu blinken, wenn die 5. Taste erneut gedrückt wird. Ich muss mehrmals drücken, manchmal zwei oder manchmal sogar noch mehr Male. ich nicht
Sind Sie sicher, dass Sie jederzeit beenden müssen, wo immer sich der Ausführungszeiger befindet? Normalerweise könnten Sie einfach den Tastendruck am Ende der Schleifen while
und überprüfen for
und anrufen, return
wenn er gedrückt wird.
Manchmal denken wir, unser Programm muss etwas tun und die Ausführung unterbrechen, aber nach sorgfältiger Prüfung kommen wir zu dem Schluss, dass es eine Schleifeninteraktion beenden und dann beenden kann.
Können Sie uns sagen, was innerhalb der Schleifen gemacht wird, damit wir sicherstellen können, was benötigt wird?
Bearbeiten: Wie ich vermutet habe, besteht das Problem mit Ihrem Programm darin, dass Ihre Verzögerungsintervalle zu lang sind, z. B. delay(1000)
und delay(500)
, und Sie können nicht nach Tastendrücken suchen, während das Programm wartet.
Um das zu beheben, erstellen Sie die folgende Funktion, die Ihre Aufrufe zum Verzögern ersetzt:
// waits for the specified miliseconds
// or return (almost) immediately if button is pressed
// return value indicates whether button was pressed or not
boolean waitOrButtonPressed(int miliseconds) {
for (int i = 0; i < miliseconds / 10; i++) {
if (readButtons(5)) == 5)
return true;
delay(10);
}
return false;
}
Ersetzen Sie dann innerhalb Ihrer for
Schleife Ihre Aufrufe delay(1000)
durch den folgenden Code:
if (waitOrButtonPressed(1000)) return;
Die von mir erstellte Funktion lässt Ihr Programm fast wie warten delay()
, kehrt aber zurück true
, wenn während dieser Zeit eine Taste gedrückt wurde. In diesem Fall if
wird die obige Anweisung beendet loop()
, die vom Arduino-generierten Code erneut aufgerufen wird.
Denken Sie daran, die zu wartenden Millisekunden beizubehalten, wenn Sie Ihre Aufrufe ersetzen, delay()
um das Warteverhalten Ihres Programms unverändert zu lassen.
Bearbeiten 2: Ramblings
Fälle wie dieser erinnern mich an den Film Tron , in dem die Hauptfigur in einen Computer gezogen wird, wo die Zeit viel langsamer vergeht als im wirklichen Leben. Also, wie im Film, sind 1000 Millisekunden (1s) VIEL ZEIT für die MCU. In dieser Zeit können Sie viel mehr tun, als zu warten. Versuchen Sie, die langen Wartezeiten zu unterbrechen, und machen Sie nützliche Dinge mit Ihren MCU-Zyklen.
Erfahren Sie auch, wie Sie Interrupts verwenden, wie andere in ihren Kommentaren und Antworten erwähnt haben. Es ist nur eine andere (etwas kompliziertere) Art, Dinge zu erledigen, während Sie warten. In Ihrem Fall könnten Interrupts verwendet werden, um den Tastendruck zu erkennen, ohne ihn jedes Mal überall überprüfen zu müssen. Hier ist ein Ort, an dem Sie anfangen können, etwas über Interrupts mit Arduino zu lernen .
if (digitalRead(fifthButton) == HIGH)
so ändern, wie Sie es tun, um zu überprüfen, ob Ihre Taste gedrückt wurde. Mir ist aufgefallen, dass Sie einen analogen Pin verwenden, um zu erkennen, ob diese Taste gedrückt wird, daher muss dies möglicherweise behoben werden.delay()
. Das Problem ist, dass Sie nicht überprüfen können, ob die Taste gedrückt wird, wenn sich Ihre MCU in delay () befindet. Daher wird nur sehr schnell, ein- oder zweimal pro Sekunde, nach Tastendrücken gesucht. Wenn Sie das Glück haben, den Knopf zu drücken, während er die kurze Überprüfung durchführt, dann funktioniert es. Das ist auch der Grund, warum Sie denken, dass Sie die Taste mehrmals drücken müssen, und die Anzahl der erforderlichen Betätigungen ist variabel. Ich denke, Sie sollten Ihre While-Schleife ersetzen, in der Sie definieren, wie LEDs blinken sollen, und stattdessen einen Pin-Change-Interrupt verwenden, um Tastendrücke zu erfassen. Können Sie das tun?Eine Methode, die verwendet werden kann und zum Zurücksetzen des MCU führt (ich bin mir nicht sicher, ob dies der Effekt ist, nach dem Sie suchen), besteht darin, einen externen Interrupt für die Schaltfläche zu verwenden und innerhalb des Interrupts den Watchdog mit einem kleinen Timeout zu aktivieren und lass es ablaufen und setze die mcu zurück.
Aus diesem Grund hat C die goto- Anweisung; zum Vorwärtsbewegen aus vielen verschachtelten Schleifen.
Die meisten Leute werden Ihnen sagen, dass Sie es nicht verwenden sollen, und es ist wahrscheinlich, dass Sie es umgehen können, aber es ist sicherlich eine Lösung für Ihr Problem.
goto
soll gar nicht erst erwähnt werden. Zu sagen, „es ist ein ziemlich schlechter Programmierstil“, ist immer noch eine Untertreibung. goto
ist ein Relikt von (programmierähnlichem) Assembler, wo es ein natürlicher Teil des Vokabulars ist. Das Aufteilen von langem Code in Funktionen, deren Aufruf bei Bedarf und die Verwendung von return
, break
oder continue
macht die Verwendung von goto
obsolet. Außerdem erzeugt eine tiefe Verschachtelung algorithmische Komplexität, die vermieden werden sollte. Unterm Strich ist es nicht nötig, goto
wenn Sie sich mit Programmierung auskennen. Ernsthaft.
Joe Hass
JYelton
Unsinn
loop
. Wie Sie dies tun, hängt von Ihrem Mikrocontroller und der Art und Weise ab, wie er Interrupts behandelt (Stacks / Unstacks).Matt Jung
Joe Hass
Nick
alexan_e
Nick
alexan_e
Ricardo
JYelton
Ricardo