Hallo,
ich habe ein kleines Problem bei einem Schulprojekt. Wir machen gerade einen Arduino Minibot

der automatisch Hindernisse erkennen soll und diese Umfahren. Dies hat auch schon geklappt. Nun wollten ich eine weitere Funktion hinzufügen, das Starten und des automatischen Fahrens durch ein drücken einer Taste auf der IR-Fernbedienung. Da das Programm gerne mal 10s braucht, habe ich alle Delays mit der BlinkWithoutDelay-Technik ausgetauscht. Hierbei arbeite ich mit der IRremote Bibliothek und ich habe diese Anleitung befolgt. Obwohl der Arduino immer wieder die void loop durchläuft (habe ich mit einer Serial-Monitor Nachricht herausgefunden), stoppt er einfach nicht das Unterprogramm fahren.
Wir arbeiten mit einem L293D Motortreiber, in meinem Programm starte ich die Motoren über z.B. motor11 hierbei meine ich den ersten Steuerungspin des ersten Motors (motor12 würde den 2. Steuerungspin meinen).
Unsere Komponenten sind so verbunden (kann nur 1 Bild hochladen).
Und das hier ist mein Code:
/*
Version: 3.0
Aktueller Stand: 18.01.2022
*/
//----- Festlegen -----
//Motoren
#define enable1 9 //Enableport des 1. Motors
#define enable2 10 //Enableport des 2. Motors
#define motor11 6 //1. Steuerungspin vom 1. Motor
#define motor12 5 //2. Steuerungspin vom 1. Motor
#define motor21 4 //1. Steuerungspin vom 2. Motor
#define motor22 3 //2. Steuerungspin vom 2. Motor
//Zeiten, Geschwindigkeiten
#define kurvezeit 1500 //Zeit in ms, die der Minibot braucht um eine Kurve zu fahren
#define enablewert1 250 //Geschwindigkeitsfeinjustierung vom 1. Motor
#define enablewert2 185 //Geschwindigkeitsfeinjustierung vom 2. Motor
//Ultraschall
#define trigger 8 //Trigger/Auslöser vom Ultraschallsensors
#define echo 12 //Echo/Empfägner vom Ultraschallsensors
long dauer=0; //Variable zum Speichern der Dauer (von Auslößen bis zum Empfangen einer Ultraschallwelle)
long entfernung=0; //Variable zum Speichern der Entfernung (nach vorne gerichtet)
long entfernungl=0; //Variable zum Speichern der linken Entfernung
long entfernungr=0; //Variable zum Speichern der rechten Entfernung
//IR-Remote
#include <IRremote.h> //Library zur IR-Steuerung wird eingebunden
#define RECEIVER_PIN 11 //Pin des Ultraschallsensors
IRrecv receiver(RECEIVER_PIN); //Objekt zum Empfangen wird erstellt
decode_results results; //Objekt zum Speichern der Ergebnisse wird erstellt
#define Vor 0xFF629D //IR-Empfangs-Hex-Zahl der Vor-Taste
#define Zurueck 0xFFA857 //IR-Empfangs-Hex-Zahl der Zurück-Taste
#define Rechts 0xFFC23D //IR-Empfangs-Hex-Zahl der Rechts-Taste
#define Links 0xFF22DD //IR-Empfangs-Hex-Zahl der Links-Taste
#define Power 0xFD00FF //IR-Empfangs-Hex-Zahl der Power-Taste
#define Stop 0xFD40BF //IR-Empfangs-Hex-Zahl der Stop-Taste
//Flags
int steuerflag = 0; //Flag um Befehl/e nur 1 mal auszuführen
int linksflag = 0; //Flag um Befehl/e nur 1 mal auszuführen
int rechtsflag = 0; //Flag um Befehl/e nur 1 mal auszuführen
int fahrenflag = 0; //Flag um Befehl/e nur 1 mal auszuführen
int entscheidungflag = 0; //Flag um Befehl/e nur 1 mal auszuführen
int linksfertig = 0; //Flag um Befehl/e nur 1 mal auszuführen
int rechtsfertig = 0; //Flag um Befehl/e nur 1 mal auszuführen
int rechtsbereit = 0; //Flag um Befehl/e nur 1 mal auszuführen
int entscheidungsbereit = 0; //Flag um Befehl/e nur 1 mal auszuführen
//Millis
unsigned long linkskurvemillis; //Variable zum abspeichern der Millis am Anfang des Linkskurvenunterprogramms
unsigned long rechtskurvemillis; //Variable zum abspeichern der Millis am Anfang des Rechtskurveunterprogramms
unsigned long entscheidungmillis; //Variable zum abspeichern der Millis am Anfang des Entscheidungunterprogramms
unsigned long fahrenmillis; //Variable zum abspeichern der Millis am Anfang des Fahrenunterprogramms
void setup() {
//----- Definieren -----
//Motoren
pinMode(enable1, OUTPUT);
pinMode(enable2, OUTPUT);
pinMode(motor11, OUTPUT);
pinMode(motor12, OUTPUT);
pinMode(motor21, OUTPUT);
pinMode(motor22, OUTPUT);
//Ultraschall
pinMode(trigger, OUTPUT);
pinMode(echo, INPUT);
//IR-Remote
receiver.blink13(true); //Blinklicht des IR-Empfängers wird aktiviert
receiver.enableIRIn(); //IR-Empfänger wird als Eingang gekennzeichnet
//Serieller Monitor
Serial.begin(9600); //Serieller Monitor wird gestartet
}
void loop() {
if (receiver.decode(&results)) { //dekodiert das empfangene IR-Signal und speichert es in dem "Results"-Objekt
Serial.println(results.value, HEX); //schreibt den Hex-Code aus dem "Results"-Objekt in den seriellen Monitor
receiver.resume(); //IR-Empfänger-Objekt wird zurückgesetzt
}
if(results.value == Power){ //Wenn die IR-Empfangs-Hex-Zahl der Power-Taste dem "Results"-Objekt
fahren(); //entspricht wird das Unterprogramm "fahren" ausgeführt
}
if(results.value == Stop){ //Wenn die IR-Empfangs-Hex-Zahl der Stop-Taste dem "Results"-Objekt
resetallflag(); //entspricht wird das Unterprogramm "resetallflag" ausgeführt
}
}
void fahren(){ //Unterprogramm "fahren"
digitalWrite(trigger, HIGH); //Ultraschallsensor wird angeschaltet, 10ms gewartet und dann wieder ausgeschaltet
delay(10);
digitalWrite(trigger, LOW);
dauer = pulseIn(echo, HIGH); //Der Zeitabstand zwischen dem Ausschalten bis der Empfänger eine Welle empfängt, wird gemessen und auf die Variable "dauer" gespeichert
entfernung = (dauer / 2) * 0.0343; //Die Zeit wird durch 2 geteilt (wegen Hin- und Rückweg) und mit der Schallgeschwindigkeit multiplizieren, so dass man ein Maßstab hat
if(fahrenflag == 0){ //Die Variable "fahrenmillis" wird auf die aktuellen "millis" gesetzt, mithilfe einer Flag wird sichergestellt
fahrenmillis = millis(); //das dies nur 1 mal passiert, bis die Flag wieder zurückgesetzt wird.
}
fahrenflag = 1;
if(millis() - fahrenmillis >= 500){ //500ms werden durch Millis abgewartet
if (entfernung >= 35){
analogWrite(enable1, enablewert1); //Wenn die ausgerechnete Entfernung weniger (oder gleich) 35 ist, fährt er 1s nach vorne (Code von 131 - 141)
analogWrite(enable2, enablewert2);
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW);
digitalWrite(motor21, HIGH);
digitalWrite(motor22, LOW);
if(millis() - fahrenmillis >= 1000 + 500){ //1s wird durch Millis abgewartet
digitalWrite(enable1, LOW);
digitalWrite(enable2, LOW);
fahrenflag = 0; //Der Flag "fahrenflag" wird zurückgesetzt, sodass beim nächsten die Millis wieder neu gesetzt werden
}
}
else{
if(linksfertig == 0){ //Unterprogramm "linkskurve" wird solange ausgeführt, bis "linksfertig" nicht mehr 0 ist
linkskurve();
}
if(rechtsbereit == 1 && rechtsfertig == 0){ //Unterprogramm "rechtskurve" wird ausgeführt wenn "rechtsbereit" 1 ist und endet wenn rechtsfertig nicht mehr 0 ist
rechtskurve();
}
if(entscheidungsbereit == 1){
entscheidung(); //Unterprogramm "entscheidung" wird ausgeführt wenn "entscheidungsbereit" 1 ist
}
}
}
}
void linkskurve() { //Unterprogramm "linkskurve"
if(linksflag == 0){ //Die Variable "linkskurvemillis" wird auf die aktuellen "millis" gesetzt, mithilfe einer Flag wird sichergestellt
linkskurvemillis = millis(); //das dies nur 1 mal passiert, bis die Flag wieder zurückgesetzt wird.
}
linksflag = 1;
analogWrite(enable1, enablewert1);
digitalWrite(enable2, LOW);
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW); //Rechter Motor gibt Gas
if(millis() - linkskurvemillis >= kurvezeit){ //"kurvenzeit" wird durch Millis abgewartet
digitalWrite(enable1, LOW); //Rechter Motor hält an
digitalWrite(trigger, HIGH);
if(millis() - linkskurvemillis >= kurvezeit + 10){ //10ms wird durch Millis abgewartet
digitalWrite(trigger, LOW); //Ultraschallwellen werden für 10ms über den Sender/Trigger ausgestrahlt
dauer = pulseIn(echo, HIGH); //Der Zeitabstand zwischen dem Ausschalten bis der Empfänger eine Welle empfängt, wird gemessen und auf die Variable "dauer" gespeichert
entfernungl = (dauer / 2) * 0.0343; //Die Zeit wird durch 2 geteilt (wegen Hin- und Rückweg) und mit der Schallgeschwindigkeit multiplizieren, so dass man ein Maßstab hat. Dieser
//wird auf der Variable "entfernungl" gespeichert.
if(millis() - linkskurvemillis >= kurvezeit + 10 + 500){ //500ms (Rechenzeit) wird durch Millis abgewartet
analogWrite(enable1, enablewert1);
digitalWrite(motor11, LOW);
digitalWrite(motor12, HIGH);
if(millis() - linkskurvemillis >= kurvezeit + 10 + kurvezeit + 500){ //"kurvenzeit" wird durch Millis abgewartet
digitalWrite(enable1, LOW); //Rechter Motor fährt für "kurvenzeit" rückwärts, um sich wieder in Normalposition zu begeben
linksfertig = 1; //Flag "linksfertig" wird auf 1 gesetzt, so dass das Unterprogramm "linkskurve" nicht mehr ausgeführt wird, bis die Flag zurückgesetzt wird
rechtsbereit = 1; //Flag "rechtsbereit" wird auf 1 gesetzt, so dass jetzt das Unterprogramm "rechtskurve" ausgeführt werden kann
}
}
}
}
}
void rechtskurve() { //Unterprogramm "rechtskurve"
if(rechtsflag == 0){ //Die Variable "rechtskurvemillis" wird auf die aktuellen "millis" gesetzt, mithilfe einer Flag wird sichergestellt
rechtskurvemillis = millis(); //das dies nur 1 mal passiert, bis die Flag wieder zurückgesetzt wird.
}
rechtsflag = 1;
analogWrite(enable2, enablewert2);
digitalWrite(enable1, LOW);
digitalWrite(motor21, HIGH);
digitalWrite(motor22, LOW); //Linker Motor gibt Gas
if(millis() - rechtskurvemillis >= kurvezeit){ //"kurvenzeit" wird durch Millis abgewartet
digitalWrite(enable2,LOW);
digitalWrite(trigger, HIGH);
if(millis() - rechtskurvemillis >= kurvezeit + 10){ //10ms wird durch Millis abgewartet
digitalWrite(trigger, LOW); //Ultraschallwellen werden für 10ms über den Sender/Trigger ausgestrahlt
dauer = pulseIn(echo, HIGH); //Der Zeitabstand zwischen dem Ausschalten bis der Empfänger eine Welle empfängt, wird gemessen und auf die Variable "dauer" gespeichert
entfernungr = (dauer / 2) * 0.0343; //Die Zeit wird durch 2 geteilt (wegen Hin- und Rückweg) und mit der Schallgeschwindigkeit multiplizieren, so dass man ein Maßstab hat. Dieser
//wird auf der Variable "entfernungr" gespeichert.
if(millis() - rechtskurvemillis >= kurvezeit + 10 + 500){ //500ms (Rechenzeit) wird durch Millis abgewartet
analogWrite(enable2, enablewert2);
digitalWrite(motor21, LOW);
digitalWrite(motor22, HIGH);
if(millis() - rechtskurvemillis >= kurvezeit + 10 + kurvezeit + 500){ //"kurvenzeit" wird durch Millis abgewartet
digitalWrite(enable2, LOW); //Linker Motor fährt für "kurvenzeit" rückwärts, um sich wieder in Normalposition zu begeben
rechtsfertig = 1; //Flag "rechtsfertig" wird auf 1 gesetzt, so dass das Unterprogramm "rechtskurve" nicht mehr ausgeführt wird, bis die Flag zurückgesetzt wird
entscheidungsbereit = 1; //Flag "entscheidungsbereit" wird auf 1 gesetzt, so dass jetzt das Unterprogramm "entscheidung" ausgeführt werden kann
}
}
}
}
}
void entscheidung() { //Unterprogramm "rechtskurve"
if(entscheidungflag == 0){ //Die Variable "rechtskurvemillis" wird auf die aktuellen "millis" gesetzt, mithilfe einer Flag wird sichergestellt
entscheidungmillis = millis(); //das dies nur 1 mal passiert, bis die Flag wieder zurückgesetzt wird.
}
entscheidungflag = 1;
if(entfernungl>entfernungr){ //Wenn die vorhin errechnete Entfernung "entfernungl" größer als die Entfernung "entfernungr" ist,
analogWrite(enable1, enablewert1); //dann gibt der rechte Motor gas
digitalWrite(enable2, LOW);
digitalWrite(motor11, HIGH);
digitalWrite(motor12, LOW);
if(millis() - entscheidungmillis >= kurvezeit){ //"kurvenzeit" wird durch Millis abgewartet
digitalWrite(enable1, LOW); //rechter Motor wird wieder abgeschaltet
resetallflag(); //Unterprogramm "resetallflag" wird ausgeführt, da dass das Ende des "fahren" Unterprogramms ist
}
}
else{
analogWrite(enable2, enablewert2); //Wenn die vorhin errechnete Entfernung "entfernungl" nicht größer als die Entfernung "entfernungr" ist,
digitalWrite(enable1, LOW); //dann gibt der linke Motor gas
digitalWrite(motor21, HIGH);
digitalWrite(motor22, LOW);
if(millis() - entscheidungmillis >= kurvezeit){ //"kurvenzeit" wird durch Millis abgewartet
digitalWrite(enable2, LOW); //linker Motor wird wieder abgeschaltet
resetallflag(); //Unterprogramm "resetallflag" wird ausgeführt, da dass das Ende des "fahren" Unterprogramms ist
}
}
}
void resetallflag(){ //Unterprogramm "resetallflag"
steuerflag = 0;
linksflag = 0;
rechtsflag = 0;
fahrenflag = 0;
entscheidungflag = 0;
linksfertig = 0;
rechtsfertig = 0;
rechtsbereit = 0;
entscheidungsbereit = 0; //alle Flags werden zurückgesetzt (auf 0 gesetzt)
}
In meinem Code wird das Unterprogramm fahren ausgeführt, wenn man die Taste POWER drückt. Dann misst er erstmal mit einem Ultraschallsensor die Entfernung, wenns sie weniger als 35 ist fährt er für 500ms geradeaus. Sonst macht er eine linkskurve und misst dort, dreht sich zurück, macht eine rechtskurve und misst dort, dreht sich zurück. Dann führt er entscheidung aus. Und dreht sich in die Richtung, wo die Entfernung höher ist.
Ich hoffe irgendjemand hat hier vielleicht eine Idee, was ich ändern muss damit das Unterprogramm fahren gestoppt werden kann.