RC Auto mit Hinderniserkennung

Moin,

in meinem Projekt möchte ich ein RC Auto mit einer Hinderniserkennung ausstatten. Über den Ultraschallsensor HC-SR04 soll ab einer vorgegebenen Entfernung zu einem Hindernis das Auto stoppen. Die Vorwärtsbewegung soll blockiert werden und das Auto nur noch rückwärts fahren können, bis ein ausreichender Abstand zum Hindernis vorliegt bzw kein Hindernis mehr erkannt wird.

Mein bisheriges Programm sieht wie folgt aus:

//-------------------------------------------------------------------------------------------------------------------
//Stufenlose Geschwindigkeits- und Lenkregelung

#include <Servo.h>

Servo Lenkservo;

#define ENA 6
#define IN1 5
#define IN2 7

int g = 0;

char cmd[100];
int cmdIndex;
//-------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------
//Bluetooth-Verbindung

#define bluetooth Serial
//-------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------
//Display

#include <Wire.h> // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h> // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden

LiquidCrystal_I2C lcd(0x27, 16, 2); //VCC=5V , SDA = A4 , SCL = A5
//-------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------
//RFID-Erkennung

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN); //SDA=10, SCK=13, MOSI=11, MISO=12, RST=5 (nicht benötigt)

long ids[] = {1857660, 1857660};
boolean e = false;
//-------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------
//Temperaturmessung

#define TMP A0

int sensorwert;
int temperatur = 0;
unsigned long temperatur_trigger = 4000;
//-------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------
//Hinderniserkennung

#include <NewPing.h>

#define PING_PIN  A3
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE); // NewPing setup of pin and maximum distance.

long entfernung = 0;
//-------------------------------------------------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------------------
unsigned long zeit = 0;
unsigned long startMillis;
const unsigned long period = 1000;
//-------------------------------------------------------------------------------------------------------------------

//__________________________________________________________________________________________________________________________


//RFID-Erkennung

void rfid() {
  long code = 0;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    code = ((code + mfrc522.uid.uidByte[i]) * 10);
  }

  Serial.print("Die Kartennummer lautet:");
  Serial.println(code);

  int counter = 0;
  for (counter = 0; counter < sizeof(ids) - 1; counter++) {
    if (code == ids[counter]) {
      e = !e;
      break;
    }
    else if (code != ids[counter]) {
      break;
    }
  }
  delay (100);
}



//Hinderniserkennung: Stoppen, wenn Hindernis (Abstand = 5cm) erkant wurde, und blockieren der //Vorwärtstbewegung. Nur Rückwärtsbewegung erlauben.

void hindernis () {
  //  sendewechsel = zeit;

  unsigned int uS = sonar.ping();
  entfernung = (uS / US_ROUNDTRIP_CM);

  if (entfernung > 1 && entfernung < 5) {

  }
}

//Stufenlose Geschwindigkeits- und Lenkregelung --> done

void exeCmd() {
  if (cmd[0] == 's' && cmd[1] == ' ') {
    int g = atoi(cmd + 2);

    Serial.print("geschwindigkeit=");
    Serial.println(g);

    if (g >= 0) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      analogWrite(ENA, g);
    } else {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      analogWrite(ENA, -g);
    }
  }

  if (cmd[0] == 'y' && cmd[1] == ' ') {

    //float val = atof(cmd + 2);

    //val = val / 9.8; //nur mit Beschleunigungssensor notwendig
    //val = val * 500;

    int servoMicroseconds =  atof(cmd + 2); //1500 ist die Mittelposition des Servos

    Lenkservo.writeMicroseconds(servoMicroseconds);

    Serial.print("Servo=");
    Serial.println(servoMicroseconds);
  }
}

//Temperaturmessung
void tempmessung () {
  sensorwert = analogRead(TMP);
  temperatur = map(sensorwert, 0, 410, -50, 150);
  Serial.println(temperatur);
}

void setup() {
  //delay(500);

  Serial.begin(9600);

  pinMode(ENA , OUTPUT);
  pinMode(IN1 , OUTPUT);
  pinMode(IN2 , OUTPUT);

  Lenkservo.attach(9);
  Lenkservo.writeMicroseconds(1500);

  SPI.begin();
  mfrc522.PCD_Init();
  lcd.init();

  cmdIndex = 0;
  startMillis = millis();
}


void loop() {
  zeit = millis();
  
  if (zeit - startMillis >= period) {
    startMillis = zeit; //Alle 4 Sekunden wird die Temperatur gemessen
    tempmessung ();
  }
  
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
    rfid();
  }

  while (bluetooth.available() && e == true) {

    char c = (char)bluetooth.read();

    if (c == '\n') {
      cmd[cmdIndex] = 0;
      exeCmd();  // Befehl ausführen
      cmdIndex = 0; // reset the cmdIndex
    } else {
      cmd[cmdIndex] = c;
      if (cmdIndex < 99) cmdIndex++;
    }
  }


}

Leider habe ich keine Idee, wie ich ab einer bestimmten Entfernung die Vorwärtsbewegung blockieren und nur die Rückwärtsbewegung aus der Funktion void exeCmd freigeben kann. Diese Funktion erlaubt das stufenlose Regeln der Geschwindigkeit mittels Schieberegler, der von -255 bis 255 geht und somit über ein PWM Signal den Motortreiber ansteuert.

Zunächst muss ich sicherstellen, dass durchgehend die Entfernung gemessen wird ==> dies muss daher im Loop passieren. Richtig? Allerdings ist hier das Problem, dass das Programm so lange in der While-Schleife loopt, wie ich das Auto übers Handy steuere. ==> Bedeutet, die Entfernungsmessung müsste sich in dieser While-Schleife befinden. Richtig?

Wenn jetzt eine Entfernung kleiner als eine vorgegebene Entfernung gemessen wird, könnte evtl eine Funktion ähnlich der Funktion void exeCmd ausgeführt werden, die nur eine Rückwärtsbewegung erlaubt.

Hört sich das soweit richtig an oder bin ich auf dem Holzweg? Vielleicht habt ihr eine Idee. Ich würde mich riesig freuen.

Grüße.

TheDoDo:
Allerdings ist hier das Problem, dass das Programm so lange in der While-Schleife loopt, wie ich das Auto übers Handy steuere. ==> Bedeutet, die Entfernungsmessung müsste sich in dieser While-Schleife befinden. Richtig?

Nein, nicht richtig. Die while-Schleife muss raus. Mit loop hast Du bereits eine Schleife. Du brauchst keine 2. Schleife innerhalb der Schleife. Du blockierst sonst alle anderen Aktivitäten.

P.S. wobei die while-Schleife vermutlich eh nicht 'loopt'. Bei 9600 Baud tröpfelt jede ms ein Zeichen rein, da ist der Arduino längst schon wieder aus der while-Scheife raus.

Eine Variante ist am Ende der Funktion exeCmd sowas zu machen:

if(entfernung < entfernung_krit) {
   if(g > 0){
       g =0;
   }
}

Halt eben mit deinen Variablennamen und du musst irgendwo, z. B. global, entfernung_krit definieren.

MicroBahner:
Die while-Schleife muss raus.

Der Grund für die While-Schleife ist, dass das Programm nur in diese springen soll wenn:

  • über ein Handy ein Bluetooth-Signal gesendet und empfangen wird
  • die boolean variable e nach einer richtigen RFID-Erkennung im Sinne eines Schlüssels auf true geschaltet ist

MicroBahner:
P.S. wobei die while-Schleife vermutlich eh nicht 'loopt'. Bei 9600 Baud tröpfelt jede ms ein Zeichen rein, da ist der Arduino längst schon wieder aus der while-Scheife raus.

Also hier evtl auch nochmal was an der Baudrate ändern?

Mahimus:
Eine Variante ist am Ende der Funktion exeCmd sowas zu machen:

if(entfernung < entfernung_krit) {

if(g > 0){
      g =0;
  }
}





Halt eben mit deinen Variablennamen und du musst irgendwo, z. B. global, entfernung_krit definieren.

Vielen dank, das werde ich mal in meine Überlegungen mit einfließen lassen.

Grüße.

TheDoDo:
Der Grund für die While-Schleife ist, dass das Programm nur in diese springen soll wenn:

  • über ein Handy ein Bluetooth-Signal gesendet und empfangen wird
  • die boolean variable e nach einer richtigen RFID-Erkennung im Sinne eines Schlüssels auf true geschaltet ist

Ich denke, hier liegt noch ein prinzipielles Verständnisproblem für den Programmablauf vor.
Loop ist ja bereits eine Schleife, und wenn ein Bluetooth-Signal empfangen wird, soll er natürlich hier reinspringen, und das/die empfangenen Zeichen lesen. Er bleibt aber da nicht bis ein komplettes Kommando empfangen wird, denn das dauert viel zu lange. Er liest das Kommando 'häppchenweise' so wie die Zeichen reintröpfeln, und dazwischen kann er immer wieder andere Dinge im loop machen ( z.B. auch die Entfernung messen). Erst wenn das Kommando vollständig empfangen ist ( bei dir nach dem '\n') wird es ausgewertet und ausgeführt.
Du könntest insofern eigentlich das 'while' durch ein 'if' ersetzen, und es würde genauso funktionieren.
Nur wenn Du im loop andere Dinge erledigst, die länger als der Empfang eines Zeichens dauert, kann es dann sein, dass er durch das 'while' mehr als ein Zeichen aus dem Puffer liest. Edit: was ja nicht schlecht ist, weshalb Du das while schon drinlassen kannst. Du musst dir nur den tatsächlichen Ablauf klarmachen: er bleibt eben nicht in der Whileschleife bis das komplette Kommando empfangen wurde - und das ist auch gut so.

Es ist auch nicht gut, das Auslesen aus dem Puffer vom Flag 'e' ( ein aussagekräftiger Name wäre da hilfreich) abhängig zu machen. Das Empfangen der Zeichen durch das Bluetoothmodul kannst Du ja damit nicht verhindern, sondern der ballert dir nur deinen Empfangspuffer voll, ohne dass Du ihn ausliest. Wird nun später 'e' auf 'true' gesetzt, liest Du u.U. alte Kommandos, die Du eigentlich garnicht mehr haben willst.
Du solltest also die empfangenen Kommandos immer auslesen. Nur ob Du sie ausführst machst Du vom Flag 'e' abhängig.

TheDoDo:
Also hier evtl auch nochmal was an der Baudrate ändern?

Das ändert nichts am Prinzip, denn die serielle Schnittstelle ist immer langsam im Verhältnis zur Prozessorgeschwindigkeit. Am oben beschrieben Ablauf ändert das nichts. Höchstens, dass er weniger loop-Durchläufe macht bis er überhaupt mal wieder in die Bluetoothauswertung springt.

MicroBahner:
Ich denke, hier liegt noch ein prinzipielles Verständnisproblem für den Programmablauf vor.

Das stimmt wohl leider, bin noch nicht ganz mit der Materie vertraut.

MicroBahner:
Es ist auch nicht gut, das Auslesen aus dem Puffer vom Flag 'e' ( ein aussagekräftiger Name wäre da hilfreich) abhängig zu machen. Das Empfangen der Zeichen durch das Bluetoothmodul kannst Du ja damit nicht verhindern, sondern der ballert dir nur deinen Empfangspuffer voll, ohne dass Du ihn ausliest. Wird nun später 'e' auf 'true' gesetzt, liest Du u.U. alte Kommandos, die Du eigentlich garnicht mehr haben willst.
Du solltest also die empfangenen Kommandos immer auslesen. Nur ob Du sie ausführst machst Du vom Flag 'e' abhängig.

Das erklärt schonmal, warum das Auto teilweise einfach losfährt, wenn der RFID-Chip 'e' auf True schaltet. Also führt er hier scheinbar noch alte übermittelte Bluetooth-Werte aus, richtig?
Dann stehe ich jetzt aber auf dem Schlauch, wie ich es umsetze, dass die Werte immer ausgelesen, aber nur bei eingeschalteter 'e(ngine)' ausgeführt werden....

Ich habe den Loop-Teil wie folgt abgeändert:

void loop() {
  zeit = millis();

  while (engine == false) {
    Serial.println("Closed");
    rfid();
  }

  if (zeit - rfid_startMillis >= rfid_period) {
    rfid_startMillis = zeit;
    Serial.println("RFID-Check");
    rfid();
  }


  if (bluetooth.available()) {

    char c = (char)bluetooth.read();

    if (c == '\n') {
      cmd[cmdIndex] = 0;
      exeCmd();  // Befehl ausführen
      cmdIndex = 0; // reset the cmdIndex
    } else {
      cmd[cmdIndex] = c;
      if (cmdIndex < 99) cmdIndex++;
    }
  }

  if (zeit - tmp_startMillis >= tmp_period) {
    tmp_startMillis = zeit;
    tempmessung ();
  }

So lange kein hinterlegter RFID-Chip erkannt wurde, bleibt kommt das Programm maximal zur While-Schleife - der Rest des Codes ist "gesperrt".

Wenn nun der RFID-Chip erkannt wurde, wird boolean engine auf true gesetzt und das Programm loopt durch den gesamten Loop.

Die alte While-Schleife habe ich nun doch in ein if umgeschrieben.

Mit diesem Programm stelle ich doch nun sicher, dass alle Bluetooth-Werte ausgelesen aber nur ausgeführt werden, wenn 'engine' auf true ist, oder?

Oder sollte ich die ausführende Funktion void exeCmd auch noch im eine Abfrage ergänzen, ob 'engine == true' ist? Siehe:

void exeCmd() {
  if(engine == true) {

  if (cmd[0] == 's' && cmd[1] == ' ') {
    int g = atoi(cmd + 2);

    Serial.print("geschwindigkeit=");
    Serial.println(g);

    if (g >= 0) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      analogWrite(ENA, g);
    } else if (g <= 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      analogWrite(ENA, -g);
    } else if (g = 0) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
    }
  }

  if (cmd[0] == 'y' && cmd[1] == ' ') {


    int servoMicroseconds =  atof(cmd + 2); //1500 ist die Mittelposition des Servos

    Lenkservo.writeMicroseconds(servoMicroseconds);

    Serial.print("Servo=");
    Serial.println(servoMicroseconds);
  }
}
}

Du solltest evtl. zeigen (im Code), wo und wie du die ominöse Variable engine definierst, veränderst und verwendest.
Dein loop Schnipsel hilft nicht viel und sieht -ohne den Rest- erstmal nur falsch aus.

So lange kein hinterlegter RFID-Chip erkannt wurde, bleibt kommt das Programm maximal zur While-Schleife - der Rest des Codes ist "gesperrt".

Das hätte ich als

void loop() {
  if ( ! rfid() ) return;
  ...
}

ohne while Schleife geschrieben. Dass eine Funktion keinen Rückgabewert hat (void) sollte eher die Ausnahme sein, finde ich.

Ist übrigens gewollt, dass dann --ohne erkannten gültigen RFID Chip-- die Serial-Schnittstelle bluetooth ignoriert wird? ( Und ohne Pause mit "Closed" vollgeballert wird? Das wirkt bei 9600 ungefähr wie ein delay(7); ) Wie groß ist übrigens die später verwendete rfid_period ?

Okay, entschuldige. Folgend nochmal das gesamte Programm:

//--------------------------------------------------------------------------------------------------------------------------
//Stufenlose Geschwindigkeits- und Lenkregelung
#include <Servo.h>

Servo Lenkservo;

#define ENA 6
#define IN1 5
#define IN2 7

int g = 0;

char cmd[100];
int cmdIndex;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Bluetooth-Verbindung
#define bluetooth Serial
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Display
#include <Wire.h> // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h> // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden

LiquidCrystal_I2C lcd(0x27, 16, 2); //VCC=5V , SDA = A4 , SCL = A5
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//RFID-Erkennung
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN); //SDA=10, SCK=13, MOSI=11, MISO=12, RST=5 (nicht benötigt)

long ids[] = {1857660, 1857660};
boolean engine = false;
const unsigned long rfid_period = 500;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Temperaturmessung
int TMP = A0; //Flache Seite: 5V , A0 , GND

int sensorwert;
int temperatur = 0;
const unsigned long tmp_period = 4000;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Hinderniserkennung
#include <NewPing.h>

#define PING_PIN  A3
#define MAX_DISTANCE 200 .

NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE);
long entfernung;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
unsigned long zeit;
unsigned long rfid_startMillis;
unsigned long tmp_startMillis;
//--------------------------------------------------------------------------------------------------------------------------

//__________________________________________________________________________________________________________________________


//RFID-Erkennung --> ToDo?
void rfid() {
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  long code = 0;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    code = ((code + mfrc522.uid.uidByte[i]) * 10);
  }

  Serial.print("Die Kartennummer lautet:");
  Serial.println(code);

  int counter = 0;
  for (counter = 0; counter < sizeof(ids) - 1; counter++) {
    if (code == ids[counter]) {
      engine = !engine;
      break;
    }
    else if (code != ids[counter]) {
      break;
    }
  }
  delay (1000);
}


//Hinderniserkennung: Stoppen, wenn Hindernis (Abstand = 5cm) erkant wurde, und blockieren der Vorwärtstbewegung. Nur Rückwärtsbewegung erlauben. --> ToDo
void hindernis () {
  //  sendewechsel = zeit;

  unsigned int uS = sonar.ping();
  entfernung = (uS / US_ROUNDTRIP_CM);

  if (entfernung > 1 && entfernung < 5) {

  }
}

//Stufenlose Geschwindigkeits- und Lenkregelung --> done

void exeCmd() {
  if (cmd[0] == 's' && cmd[1] == ' ') {
    int g = atoi(cmd + 2);

    Serial.print("geschwindigkeit=");
    Serial.println(g);

    if (g > 0) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      analogWrite(ENA, g);
    } else if (g < 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      analogWrite(ENA, -g);
    } else if (g == 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, HIGH);
    }
  }

  if (cmd[0] == 'y' && cmd[1] == ' ') {

    int servoMicroseconds =  atof(cmd + 2); //1500 ist die Mittelposition des Servos

    Lenkservo.writeMicroseconds(servoMicroseconds);

    Serial.print("Servo=");
    Serial.println(servoMicroseconds);
  }
}

//Temperaturmessung
void tempmessung () {
  sensorwert = analogRead(TMP);
  temperatur = map(sensorwert, 0, 410, -50, 150);
  Serial.println(temperatur);
}

void setup() {
  //delay(500);

  Serial.begin(9600);

  pinMode(ENA , OUTPUT);
  pinMode(IN1 , OUTPUT);
  pinMode(IN2 , OUTPUT);

  Lenkservo.attach(9);
  Lenkservo.writeMicroseconds(1500);

  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, HIGH);

  SPI.begin();
  mfrc522.PCD_Init();
  lcd.init();

  cmdIndex = 0;
  zeit = 0;
  entfernung = 0;
  tmp_startMillis = millis();
  rfid_startMillis = millis();
}


void loop() {
  zeit = millis();

  while (engine == false) {
    Serial.println("Closed");
    rfid();
  }

  if (zeit - rfid_startMillis >= rfid_period) {
    rfid_startMillis = zeit;
    Serial.println("RFID-Check");
    rfid();
  }


  if (bluetooth.available()) {

    char c = (char)bluetooth.read();

    if (c == '\n') {
      cmd[cmdIndex] = 0;
      exeCmd();  // Befehl ausführen
      cmdIndex = 0; // reset the cmdIndex
    } else {
      cmd[cmdIndex] = c;
      if (cmdIndex < 99) cmdIndex++;
    }
  }

  if (zeit - tmp_startMillis >= tmp_period) {
    tmp_startMillis = zeit;
    tempmessung ();
  }

}

michael_x:
Ist übrigens gewollt, dass dann --ohne erkannten gültigen RFID Chip-- die Serial-Schnittstelle bluetooth ignoriert wird? ( Und ohne Pause mit "Closed" vollgeballert wird? Das wirkt bei 9600 ungefähr wie ein delay(7); )

Das war nur für mich, um im Monitor zu sehen, dass sich das Programm dort befindet und das Auto sozusagen "abgeschlossen" ist. Dementsprechend, ja, ohne gültigen RFID-Chip soll Bluetooth ignoriert werden.

michael_x:
Wie groß ist übrigens die später verwendete rfid_period ?

Die ist zur Zeit auf 500ms eingestellt.

michael_x:
Das hätte ich als

void loop() {

if ( ! rfid() ) return;
}


ohne while Schleife geschrieben. Dass eine Funktion keinen Rückgabewert hat (void) sollte eher die Ausnahme sein, finde ich.

Den Punkt verstehe ich nicht ganz.
rfid() müsste hier doch ein boolean sein, damit das klappt, oder nicht?

rfid() müsste hier doch ein boolean sein, damit das klappt, oder nicht?

Ja sicher.

bool rfid () {
    if ( ! mfrc522.PICC_IsNewCardPresent())    return false;
    ...
    bool engine; // hier lokal definiert, falls eine lokale Variable reicht
    ...
    return engine;
}

TheDoDo:
So lange kein hinterlegter RFID-Chip erkannt wurde, bleibt kommt das Programm maximal zur While-Schleife - der Rest des Codes ist "gesperrt"
...
Mit diesem Programm stelle ich doch nun sicher, dass alle Bluetooth-Werte ausgelesen aber nur ausgeführt werden, wenn 'engine' auf true ist, oder?

Nein, das tust Du nicht. Da er nicht mehr zum

  if (bluetooth.available()) { 
    ...

kommt, wird auch nichts vom Bluetooth ausgelesen. Das ist fast noch schlechter als vorher

TheDoDo:
Oder sollte ich die ausführende Funktion void exeCmd auch noch im eine Abfrage ergänzen, ob 'engine == true' ist?

Nur das ist der richtige Weg. Den Aufruf dieser Funktion musst Du von deinem 'engine' Wert abhängig machen. Dann werden die Bluetooth-Kommandos zwar gelesen, aber nicht ausgeführt.
Alles andere bleibt im loop wie es war.

Hi

Ob man loop() per return; 'abbrechen' will, könnte Glaubenskriege auslösen.
Meiner Meinung nach sollte loop() IMMER durchlaufen.
Alles, was irgendwie dort gemacht werden soll, wird 'angetestet' und wenn die Bedingungen erfüllt sind, ausgeführt.
Im Grunde eine State-Maschine.

Bei Dir IMMER BT einlesen - eventuell möchtest Du ja später auch was machen, wenn das Fahrzeug sich nicht mit Schallgeschwindigkeit irgendwelchen Hindernissen nähert.
Je nach Status werden diese Informationen verarbeitet - z.B., um den Status anzupassen.
... oder die Geschwindigkeit von Schnecke auf Schnecke 2.0 umzustellen ...
... den Akku-Status zurück zu melden ...
... egal, Hauptsache, loop() läuft (möglichst schnell) durch, damit Du IMMER auf ALLES reagieren kannst.

Vll. möchtest Du im laufendem Betrieb auch die Möglichkeit haben, weitere RFID-Chips einzulernen oder Vorhandene zu entfernen ... Möglichkeiten Es Da viele gibt.

MfG

Ob man loop() per return; 'abbrechen' will, könnte Glaubenskriege auslösen.

Da stimme ich dir zu, solange du beim Konjunktiv "könnte" bleibst.

Da der TO ja seine Grundannahme ( "ohne rfid() läuft gar nichts" ) schon revidiert hat, ist hier das Ganze auch schon obsolet.

Zum Glaubenskrieg-Thema generell gebe ich zu bedenken, dass manchmal eine if-Schachtelungstiefe weniger die Übersichtlichkeit erhöhen kann. Und Übersichtlichkeit ist sehr erstrebenswert, oder?

Wenn das ganze loop() locker auf einen Bildschirm oder gar in ein kleines scroll-Fenster passt, kann man sowohl vorzeitige return; wie die gesamte Programmlogik ziemlich gut überblicken, und auch erkennen, dass das Mantra
void Funktionen immer ohne return;
Funktionen dürfen nur ein return (am Ende) haben
nicht ganz so wichtig ist.

Hi

Sobald Du aber ein return; irgendwo versteckst, brauchst Du Dich über Fehlfunktionen nicht wundern, wenn Du in loop() Funktionalitäten hinzufügen möchtest.
Die kommen dann - warum auch immer - nur alle Jubeljahr Mal dran (klar: wegen des return, daß irgendwo - vll. sogar mehrfach - in irgendwelchen IF-Konstrukten dafür sorgt, daß 'da hinten' rein gar Nichts mehr geht).
Ob Das dann der Übersicht dienlich ist - habe da so meine Zweifel.

Soll Jeder machen, wie Er will - ich befürchte aber, daß die darauf auftauchenden Probleme weder vorher gesehen, noch verstanden werden.

MfG

Moin,

ich wollte mich nochmal kurz zu Worte melden. Vielen Dank für die Hilfe, ich bin noch dabei eure Ratschläge einfließen zu lassen und probiere einiges rum. Bisher leider ohne Erfolg.

Folgendes Problem besteht weiterhin, obwohl ich versucht habe, die ausführende Funktion exeCmd mit einer Abfrage, ob engine == true ergänzt habe: Bluetooth Modul mit Handy-App verbunden, Auto ansonsten noch gesperrt (RFID-Chip noch nicht vorgehalten). Auf der App bediene ich den Geschwindigkeitsregler, Auto fährt logischerweise durch die Sperrung nicht los. Halte ich jetzt den RFID-Chip vor, wertet das Programm scheinbar die im gesperrten Modus übermittelten Werte aus und das Auto fährt los.
Dieses Problem ist bestimmt immer noch auf die bereits erwähnte Problematik zurückzuführen:

MicroBahner:
Das Empfangen der Zeichen durch das Bluetoothmodul kannst Du ja damit nicht verhindern, sondern der ballert dir nur deinen Empfangspuffer voll, ohne dass Du ihn ausliest. Wird nun später 'e' auf 'true' gesetzt, liest Du u.U. alte Kommandos, die Du eigentlich garnicht mehr haben willst.

Ich versuche mich nochmal ein bisschen und poste ansonsten am Besten nochmal mein Programm.

Danke und Grüße.

TheDoDo:
und poste ansonsten am Besten nochmal mein Programm.

Ja, das wäre sicher hilfreich.

Man kann auch alles was man liest, ignorieren. Ein großer Unterschied zu gar nicht lesen.

Also ähnlich wie

   if ( ! engine ) while (bluetooth.available()) bluetooth.read();

michael_x:
Man kann auch alles was man liest, ignorieren. Ein großer Unterschied zu gar nicht lesen.

Also ähnlich wie

   if ( ! engine ) while (bluetooth.available()) bluetooth.read();

Ich habe es "ignoriert" bzw erstmal hinten angestellt, weil ich um ehrlich zu sein, diese Zeile überhaupt nicht verstehe. !engine bedeutet doch eigentlich, dass der vorherige bool Wert von false auf true bzw von true auf false gesetzt wird oder nicht? Und wie würde ich dann meine ausführende Funktion exeCmd dort einbinden? Nach der If und While Abfrage kommen ja keine {}.
Wie gesagt, ich bin ganz neu in der Materie.

Ich habe es versucht wie folgt einzubinden. Wobei ich denke, dass du dir die Hände vor den Kopf schlagen wirst.

//--------------------------------------------------------------------------------------------------------------------------
//Stufenlose Geschwindigkeits- und Lenkregelung
#include <Servo.h>

Servo Lenkservo;

#define ENA 6
#define IN1 5
#define IN2 7

int g = 0;

char cmd[100];
int cmdIndex;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Bluetooth-Verbindung
#define bluetooth Serial
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Display
#include <Wire.h> // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h> // Vorher hinzugefügte LiquidCrystal_I2C Bibliothek einbinden

LiquidCrystal_I2C lcd(0x27, 16, 2); //VCC=5V , SDA = A4 , SCL = A5
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//RFID-Erkennung
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN); //SDA=10, SCK=13, MOSI=11, MISO=12, RST=5 (nicht benötigt)

long ids[] = {1857660, 1857660};
boolean engine = false;
const unsigned long rfid_period = 500;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Temperaturmessung
int TMP = A0; //Flache Seite: 5V , A0 , GND

int sensorwert;
int temperatur = 0;
const unsigned long tmp_period = 4000;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Hinderniserkennung
#include <NewPing.h>

#define PING_PIN  A1
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE); // NewPing setup of pin and maximum distance.

long entfernung;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Blinker
int rechterblinker = 3;
int linkerblinker = 2;

boolean blinken_links_state = LOW;
boolean linker_blinker_state = false;
boolean blinken_rechts_state = LOW;
boolean rechter_blinker_state = false;
boolean warnblinken_state = LOW;
boolean warnblinker_state = false;
unsigned long blinken_links_startMillis;
unsigned long blinken_rechts_startMillis;
unsigned long warnblinklicht_startMillis;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
unsigned long zeit;
unsigned long rfid_startMillis;
unsigned long tmp_startMillis;
//--------------------------------------------------------------------------------------------------------------------------



//RFID-Erkennung
void rfid() {
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  long code = 0;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    code = ((code + mfrc522.uid.uidByte[i]) * 10);
  }

  Serial.print("Die Kartennummer lautet:");
  Serial.println(code);

  int counter = 0;
  for (counter = 0; counter < sizeof(ids) - 1; counter++) {
    if (code == ids[counter]) {
      engine = !engine;
      cmd [100] = {0};
      break;
    }
    else if (code != ids[counter]) {
      break;
    }
  }
  delay (1000);
}


//Hinderniserkennung
void hindernis () {
  //  sendewechsel = zeit;

  unsigned int uS = sonar.ping();
  entfernung = (uS / US_ROUNDTRIP_CM);

  if (entfernung > 1 && entfernung < 5) {

  }
}

//Stufenlose Geschwindigkeits- und Lenkregelung

void exeCmd() {
  if (cmd[0] == 's' && cmd[1] == ' ') {
    int g = atoi(cmd + 2);

    Serial.print("geschwindigkeit=");
    Serial.println(g);

    if (g > 0) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      analogWrite(ENA, g);
    } else if (g < 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      analogWrite(ENA, -g);
    } else if (g == 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, HIGH);
    }
  }

  if (cmd[0] == 'y' && cmd[1] == ' ') {

    float val = atof(cmd + 2);

    int servoMicroseconds =  val;

    Lenkservo.writeMicroseconds(servoMicroseconds);

    Serial.print("Servo=");
    Serial.println(servoMicroseconds);

    if (servoMicroseconds == 1450) {
      linker_blinker_state = false;
      rechter_blinker_state = false;
    }
  }
}

//Blinken
void blinken_links () {
  if (zeit - blinken_links_startMillis > 250) {
    blinken_links_startMillis = zeit ;

    if (blinken_links_state == LOW) {
      blinken_links_state = HIGH;
    } else {
      blinken_links_state = LOW;
    }
    digitalWrite(linkerblinker, blinken_links_state);
    digitalWrite(rechterblinker, LOW);
  }
}

void blinken_rechts () {
  if (zeit - blinken_rechts_startMillis > 250) {
    blinken_rechts_startMillis = zeit ;

    if (blinken_rechts_state == LOW) {
      blinken_rechts_state = HIGH;
    } else {
      blinken_rechts_state = LOW;
    }
    digitalWrite(rechterblinker, blinken_rechts_state);
    digitalWrite(linkerblinker, LOW);
  }
}

void warnblinklicht () {
  if (zeit - warnblinklicht_startMillis > 250) {
    warnblinklicht_startMillis = zeit ;

    if (warnblinken_state == LOW) {
      warnblinken_state = HIGH;
    } else {
      warnblinken_state = LOW;
    }
    digitalWrite(rechterblinker, warnblinken_state);
    digitalWrite(linkerblinker, warnblinken_state);
  }
}

//Temperaturmessung
void tempmessung () {
  sensorwert = analogRead(TMP);
  temperatur = map(sensorwert, 0, 410, -50, 150);
  Serial.println(temperatur);
}

void setup() {

  Serial.begin(9600);

  pinMode(ENA , OUTPUT);
  pinMode(IN1 , OUTPUT);
  pinMode(IN2 , OUTPUT);

  pinMode(linkerblinker, OUTPUT);
  pinMode(rechterblinker, OUTPUT);

  Lenkservo.attach(9);
  Lenkservo.writeMicroseconds(1500);

  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, HIGH);

  SPI.begin();
  mfrc522.PCD_Init();
  lcd.init();

  cmdIndex = 0;
  zeit = 0;
  entfernung = 0;
  tmp_startMillis = millis();
  rfid_startMillis = millis();
}


void loop() {
  zeit = millis();

  if ( ! engine) while (bluetooth.available()) {

      char c = (char)bluetooth.read();

      if (c == '\n') {
        cmd[cmdIndex] = 0;
        exeCmd();
        cmdIndex = 0;
      } else {
        cmd[cmdIndex] = c;
        if (cmdIndex < 99) cmdIndex++;
      }
    }

  while (engine == false) {
    Serial.println("Closed");
    rfid();
  }

  if (zeit - rfid_startMillis >= rfid_period) {
    rfid_startMillis = zeit;
    Serial.println("RFID-Check");
    rfid();
  }

}

MicroBahner:
Ja, das wäre sicher hilfreich.

Mein eigentlicher Code, der bis auf das genannte Problem mit den alten Werten soweit funktioniert, sieht wie folgt aus:

//--------------------------------------------------------------------------------------------------------------------------
//Stufenlose Geschwindigkeits- und Lenkregelung
#include <Servo.h>

Servo Lenkservo;

#define ENA 6
#define IN1 5
#define IN2 7

int g = 0;

char cmd[100];
int cmdIndex;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Bluetooth-Verbindung
#define bluetooth Serial
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Display
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //VCC=5V , SDA = A4 , SCL = A5
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//RFID-Erkennung
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN); //SDA=10, SCK=13, MOSI=11, MISO=12, RST=5 (nicht benötigt)

long ids[] = {1857660, 1857660};
boolean engine = false;
const unsigned long rfid_period = 500;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Temperaturmessung
int TMP = A0; //Flache Seite: 5V , A0 , GND

int sensorwert;
int temperatur = 0;
const unsigned long tmp_period = 4000;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Hinderniserkennung
#include <NewPing.h>

#define PING_PIN  A1
#define MAX_DISTANCE 200 

NewPing sonar(PING_PIN, PING_PIN, MAX_DISTANCE); 
long entfernung;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
//Blinker
int rechterblinker = 3;
int linkerblinker = 2;

boolean blinken_links_state = LOW;
boolean linker_blinker_state = false;
boolean blinken_rechts_state = LOW;
boolean rechter_blinker_state = false;
boolean warnblinken_state = LOW;
boolean warnblinker_state = false;
unsigned long blinken_links_startMillis;
unsigned long blinken_rechts_startMillis;
unsigned long warnblinklicht_startMillis;
//--------------------------------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------------------------------
unsigned long zeit;
unsigned long rfid_startMillis;
unsigned long tmp_startMillis;
//--------------------------------------------------------------------------------------------------------------------------

//__________________________________________________________________________________________________________________________


//RFID-Erkennung --> Done
void rfid() {
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  long code = 0;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    code = ((code + mfrc522.uid.uidByte[i]) * 10);
  }

  Serial.print("Die Kartennummer lautet:");
  Serial.println(code);

  int counter = 0;
  for (counter = 0; counter < sizeof(ids) - 1; counter++) {
    if (code == ids[counter]) {
      engine = !engine;
      cmd [100] = {0};
      break;
    }
    else if (code != ids[counter]) {
      break;
    }
  }
  delay (1000);
}

//Stufenlose Geschwindigkeits- und Lenkregelung

void exeCmd() {
  if (cmd[0] == 's' && cmd[1] == ' ') {
    int g = atoi(cmd + 2);

    Serial.print("geschwindigkeit=");
    Serial.println(g);

    if (g > 0) {
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      analogWrite(ENA, g);
    } else if (g < 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      analogWrite(ENA, -g);
    } else if (g == 0) {
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, HIGH);
    }
  }

  if (cmd[0] == 'y' && cmd[1] == ' ') {

    float val = atof(cmd + 2);

    int servoMicroseconds =  val;

    Lenkservo.writeMicroseconds(servoMicroseconds);

    Serial.print("Servo=");
    Serial.println(servoMicroseconds);

    if (servoMicroseconds == 1450) {
      linker_blinker_state = false;
      rechter_blinker_state = false;
    }
  }
}

//Blinken
void blinken_links () {
  if (zeit - blinken_links_startMillis > 250) {
    blinken_links_startMillis = zeit ;

    if (blinken_links_state == LOW) {
      blinken_links_state = HIGH;
    } else {
      blinken_links_state = LOW;
    }
    digitalWrite(linkerblinker, blinken_links_state);
    digitalWrite(rechterblinker, LOW);
  }
}

void blinken_rechts () {
  if (zeit - blinken_rechts_startMillis > 250) {
    blinken_rechts_startMillis = zeit ;

    if (blinken_rechts_state == LOW) {
      blinken_rechts_state = HIGH;
    } else {
      blinken_rechts_state = LOW;
    }
    digitalWrite(rechterblinker, blinken_rechts_state);
    digitalWrite(linkerblinker, LOW);
  }
}

void warnblinklicht () {
  if (zeit - warnblinklicht_startMillis > 250) {
    warnblinklicht_startMillis = zeit ;

    if (warnblinken_state == LOW) {
      warnblinken_state = HIGH;
    } else {
      warnblinken_state = LOW;
    }
    digitalWrite(rechterblinker, warnblinken_state);
    digitalWrite(linkerblinker, warnblinken_state);
  }
}

//Temperaturmessung
void tempmessung () {
  sensorwert = analogRead(TMP);
  temperatur = map(sensorwert, 0, 410, -50, 150);
  Serial.println(temperatur);
}

void setup() {
  //delay(500);

  Serial.begin(9600);

  pinMode(ENA , OUTPUT);
  pinMode(IN1 , OUTPUT);
  pinMode(IN2 , OUTPUT);

  pinMode(linkerblinker, OUTPUT);
  pinMode(rechterblinker, OUTPUT);

  Lenkservo.attach(9);
  Lenkservo.writeMicroseconds(1500);

  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, HIGH);

  SPI.begin();
  mfrc522.PCD_Init();
  lcd.init();

  cmdIndex = 0;
  zeit = 0;
  entfernung = 0;
  tmp_startMillis = millis();
  rfid_startMillis = millis();
}


void loop() {
  zeit = millis();

  if (bluetooth.available()) {

    char c = (char)bluetooth.read();

    if (c == '\n') {
      cmd[cmdIndex] = 0;
      if (engine == true) {
        exeCmd();  // Befehl ausführen
      }
      cmdIndex = 0; // reset the cmdIndex
    } else {
      cmd[cmdIndex] = c;
      if (cmdIndex < 99) cmdIndex++;
    }
  }

  while (engine == false) {
    Serial.println("Closed");
    rfid();
  }

  if (zeit - rfid_startMillis >= rfid_period) {
    rfid_startMillis = zeit;
    Serial.println("RFID-Check");
    rfid();
  }

//Temperaturmessung
  if (zeit - tmp_startMillis >= tmp_period) {
    tmp_startMillis = zeit;
    tempmessung ();
  }

}

MicroBahner:
Nein, das tust Du nicht. Da er nicht mehr zum

  if (bluetooth.available()) { 

...



kommt, wird auch nichts vom Bluetooth ausgelesen. Das ist fast noch schlechter als vorher

Das habe ich versucht zu vermeiden, indem ich die if-Abfrage vor die while-Abfrage gestellt habe. Richtig? Falsch? Anderer Weg?

Danke

!engine bedeutet doch eigentlich, dass der vorherige bool Wert von false auf true bzw von true auf false gesetzt wird

Nein.

Bedeutet if (engine == false) was aber in meinen Augen deutlich schlechter lesbar ist.
Die Variable engine wird in beiden Fällen jedenfalls nicht verändert. (Wenn man nicht versehentlich eins der Gleichheitszeichen verliert)