Adafruit motor shield v2 line follower reagiert nicht auf linie

Hallo,
Ich baue als Schulprojekt einen Linienfolger-Roboter. Er soll einem schwarzen Klebeband entlang fahren. Dafür verwende ich zwei kleine dc motoren mit getriebe box .Ansteuerung der motoren funktioniert.
Da ich keine Infrarot sensoren zu verfügung habe, muss der Roboter mit einer Led(strahlt auf Boden) und einem ldr sensor erkennen ob Schwarz (wenig reflektion= Klebestreifen) oder Weiß(mehr reflektion=boden), bauen. Ich habe zwei ldr sensoren nebeneinander mit jeweils einer Led. Es soll so fahren werden, dass das Klebeband möglichts in der Mitte beider ldr sensoren bleibt und immer wenn ein ldr sensor auslöst gegengesteuert werden.

Damit der Roboter weiß welcher Wert für schwarz gilt und welcher für weiß wird im setup kalibriert indem man den roboter manuel jeweils auf weiß und schwarz schiebt.

Mein PROBLEM: die Motoren ändern nicht ihre Drehrichtung; wie in den If schleifen programmiert. Zudem, immer wenn schwarz an einem Sensor erkannt wird, hört der Arduino auf weitere informationen im Seriellen Moniotor auszugeben (Werte von "LdrL" und "LdrR" ). Er bleibt also irgendwo "stecken" was verhindert, dass er das void loop immer wieder von oben ausführt.

Ich habe aus Verzweiflung unterprogramme erstzellt, davor hat es aber auch nicht besser funktioniert

Ich weiß, dass ich es nicht gut erklärt habe, wenn ihr mehr infos braucht sagt bescheid.

LG

#include <Adafruit_MotorShield.h>
// Dezimalzahl um Geschwindigkeit der Motoren prozentual zu verändern
int Motorspeed = 1;
// Definition der Pins für die LDR-Sensoren
 int LDR_LEFT_PIN = A5;
 int LDR_RIGHT_PIN = A4;

// Variablen für die Kalibrierungswerte
int blackLeft, whiteLeft, blackRight, whiteRight;

// Variablen, die angeben, ob schwarz oder weiß erkannt wurde (schwarz=2; weiß=1)
int LdrL = 0;
int LdrR = 0;

// Motor Shield Objekt und Motoren initialisieren
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *MotorL = AFMS.getMotor(1);
Adafruit_DCMotor *MotorR = AFMS.getMotor(2);


void setup() {
  // Initialisiere seriellen Monitor
  Serial.begin(9600);
// Kalibrierung für den linken LDR-Sensor
  Serial.println("Bitte schwarzen Wert für linken Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Klebeband zu schieben
  blackLeft = analogRead(LDR_LEFT_PIN);
  Serial.print("Schwarz (links): ");
  Serial.println(blackLeft);

  Serial.println("Bitte weißen Wert für linken Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Holz zu schieben
  whiteLeft = analogRead(LDR_LEFT_PIN);
  Serial.print("Weiß (links): ");
  Serial.println(whiteLeft);

  // Kalibrierung für den rechten LDR-Sensor
  Serial.println("Bitte schwarzen Wert für rechten Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Klebeband zu schieben
  blackRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Schwarz (rechts): ");
  Serial.println(blackRight);

  Serial.println("Bitte weißen Wert für rechten Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Holz zu schieben
  whiteRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Weiß (rechts): ");
  Serial.println(whiteRight);
  // Initialisiere das Motor Shield
  AFMS.begin();

  //Rechne Geschwindigkeit aus
  MotorR->setSpeed(110 * Motorspeed);
  MotorL->setSpeed(107 * Motorspeed);
  //Motoren armen (entsischern)
  MotorR->run(RELEASE);
  MotorL->run(RELEASE);

  
}

void loop() {
  // Lesen der aktuellen Werte der LDR-Sensoren
  int currentLeft = analogRead(LDR_LEFT_PIN);
  int currentRight = analogRead(LDR_RIGHT_PIN);

  Serial.print("LdrL: ");// Überprüfen, ob der linke Sensor schwarz erkennt
  if (currentLeft <= (blackLeft + whiteLeft) / 2) {
    LdrL = 2;  
    Serial.print("Schwarz");
  } else {
    LdrL = 1;
    Serial.print("Weiß");
  }

  Serial.print("  -  LdrR: ");// Überprüfen, ob der rechte Sensor schwarz erkennt
  if (currentRight <= (blackRight + whiteRight) / 2) {
    LdrR = 2;
      Serial.print("Schwarz");
  } else {
    LdrR = 1;
      Serial.print("Weiß");
  }
  Serial.println();
  

  // Motorsteuerung basierend auf den Sensorwerten
  if (LdrL == 1 && LdrR == 1) {
   Serial.print("forward")
   forward();
  } 

  if (LdrL == 2 && LdrR == 1) {
   Serial.print("Right")
   driveRight();
  } 

  if (LdrL == 1 && LdrR == 2) {
   Serial.print("Left")
   driveLeft();

  } 

  delay(50); // Kurze Pause, um arduino nicht zu überlasten
}
void forward(){
  // Beide Sensoren erkennen weiß -> Beide Motoren vorwärts
    MotorR->run(FORWARD);
    MotorL->run(FORWARD);
    LdrL = 0;
    LdrR = 0;
}

void driveRight(){
   //Linker Sensor erkennt schwarz-> rechter Motor muss nachziehen
    MotorR->run(FORWARD);
    MotorL->run(RELEASE);
    LdrL = 0;
    LdrR = 0;
}

void driveLeft(){
    //Rechter Sensor erkennt schwarz-> linker Motor muss nachziehen 
    MotorR->run(RELEASE);
    MotorL->run(FORWARD);
    LdrL = 0;
    LdrR = 0;
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden.
Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Willkommen im Forum :slightly_smiling_face:
Als erstes

Es gibt keine if-Schleifen, sondern nur if-Abfragen!
LDR sin mehr als ungeeignet für dein Vorhaben.
Entsorge die delay() die LDR sind blind über 3Sek, in der zeit passiert nichts, lese mall das und anwende :

wen schon Experimentieren mit LDR dann in kurzes Rohr Setzen damit Umgebungslicht den nicht stört, und genau auslesen den Punkt zw. hell und dunkel.

die erkennung von schwarz und weiß funktioniert zuverlässig. Es ist viel einfacher mit uv sensoren etc, aber mein Problem liegt ja wo ganz anders. Wie kommst du auf 3 sekunden? das ist ja im Setup, im loop sind es ja nur 50ms und das reicht mir, auch wenn es nicht perfekt ist

Danke für dein Tipp, werde ich mir direkt anschauen

Zeige davon mal bitte die Serielle Ausgabe

#include <Adafruit_MotorShield.h>
// Dezimalzahl um Geschwindigkeit der Motoren prozentual zu verändern
int Motorspeed = 1;
// Definition der Pins für die LDR-Sensoren
byte LDR_LEFT_PIN = A5;
byte LDR_RIGHT_PIN = A4;

// Variablen für die Kalibrierungswerte
uint16_t blackLeft, whiteLeft, blackRight, whiteRight, schwelleR, schwelleL;

// Variablen, die angeben, ob schwarz oder weiß erkannt wurde (schwarz=2; weiß=1)
byte LdrL = 0;
byte LdrR = 0;

// Motor Shield Objekt und Motoren initialisieren
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *MotorL = AFMS.getMotor(1);
Adafruit_DCMotor *MotorR = AFMS.getMotor(2);

void setup() {
  // Initialisiere seriellen Monitor
  Serial.begin(9600);
  // Kalibrierung für den linken LDR-Sensor
  Serial.println("Bitte schwarzen Wert für linken Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Klebeband zu schieben
  blackLeft = analogRead(LDR_LEFT_PIN);
  Serial.print("Schwarz (links): ");
  Serial.println(blackLeft);

  Serial.println("Bitte weißen Wert für linken Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Holz zu schieben
  whiteLeft = analogRead(LDR_LEFT_PIN);
  Serial.print("Weiß (links): ");
  Serial.println(whiteLeft);

  // Kalibrierung für den rechten LDR-Sensor
  Serial.println("Bitte schwarzen Wert für rechten Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Klebeband zu schieben
  blackRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Schwarz (rechts): ");
  Serial.println(blackRight);

  Serial.println("Bitte weißen Wert für rechten Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Holz zu schieben
  whiteRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Weiß (rechts): ");
  Serial.println(whiteRight);
  
  schwelleR = ((blackRight + whiteRight) / 2);
  schwelleL = ((blackLeft + whiteLeft) / 2);
  Serial.print("Schwelle R: ");
  Serial.println(schwelleR);
  Serial.print("Schwelle L: ");
  Serial.println(schwelleL);
  // Initialisiere das Motor Shield
  AFMS.begin();

  //Rechne Geschwindigkeit aus
  MotorR->setSpeed(110 * Motorspeed);
  MotorL->setSpeed(107 * Motorspeed);
  //Motoren armen (entsischern)
  MotorR->run(RELEASE);
  MotorL->run(RELEASE);
}

void loop() {
  // Lesen der aktuellen Werte der LDR-Sensoren
  int currentLeft = analogRead(LDR_LEFT_PIN);
  int currentRight = analogRead(LDR_RIGHT_PIN);

  LdrL = 0;
  LdrR = 0;

  Serial.print("LdrL: ");// Überprüfen, ob der linke Sensor schwarz erkennt
  if (currentLeft <= schwelleL) {
    LdrL = 2;
    Serial.print("Schwarz");
  } else {
    LdrL = 1;
    Serial.print("Weiß");
  }

  Serial.print("  -  LdrR: ");// Überprüfen, ob der rechte Sensor schwarz erkennt
  if (currentRight <= schwelleR) {
    LdrR = 2;
    Serial.println("Schwarz");
  } else {
    LdrR = 1;
    Serial.println("Weiß");
  }

  if (LdrR == 2) {
    Serial.print("Left")
    driveLeft();
  } else if (LdrL == 2) {
    Serial.print("Right")
    driveRight();
  } else {
    Serial.print("forward")
    forward();
  }
  delay(50); // Kurze Pause
}

void forward() {
  // Beide Sensoren erkennen weiß -> Beide Motoren vorwärts
  MotorR->run(FORWARD);
  MotorL->run(FORWARD);
}

void driveRight() {
  //Linker Sensor erkennt schwarz-> rechter Motor muss nachziehen
  MotorR->run(FORWARD);
  MotorL->run(RELEASE);
}

void driveLeft() {
  //Rechter Sensor erkennt schwarz-> linker Motor muss nachziehen
  MotorR->run(RELEASE);
  MotorL->run(FORWARD);
}

Also wenn der Sensor schwarz sieht dann ist der gelesene Wert unter dem Grenzwert.

void loop() {
  // Lesen der aktuellen Werte der LDR-Sensoren
  int currentLeft = analogRead(LDR_LEFT_PIN);
  int currentRight = analogRead(LDR_RIGHT_PIN);

  LdrL = 0;
  LdrR = 0;

  Serial.print("LdrL: ");// Überprüfen, ob der linke Sensor schwarz erkennt
  if (currentLeft <= schwelleL) {
    LdrL = 2;
    Serial.print("Schwarz");
  } else {
    LdrL = 1;
    Serial.print("Weiß");
  }

Ich verstehe die herum speichern der Werte. zuerst 0 dann 2 oder 1 dann nur auf 2 prüfen und dann wieder von vorne. 1 und 0 oder meinetwegen 2 und 1 genügen. Da spart man sich den else Teil im Vergleich.

  if (LdrR == 2) {
    Serial.print("Left")
    driveLeft();
  } else if (LdrL == 2) {
    Serial.print("Right")
    driveRight();
  } else {
    Serial.print("forward")
    forward();
  }

Kann es nicht vorkommen daß beide Sensoren schwarz sehen?

Bist Du sicher daß der Roboter nach links fahren muß, wenn der rechte Sensor die schwarze Linie sieht? bzw umgekehrt?

Grüße Uwe

Ich habe es noch mal vereinfacht

#include <Adafruit_MotorShield.h>
// Dezimalzahl um Geschwindigkeit der Motoren prozentual zu verändern
int Motorspeed = 1;
// Definition der Pins für die LDR-Sensoren
byte LDR_LEFT_PIN = A5;
byte LDR_RIGHT_PIN = A4;

// Variablen für die Kalibrierungswerte
uint16_t blackLeft, whiteLeft, blackRight, whiteRight, schwelleR, schwelleL;

// Motor Shield Objekt und Motoren initialisieren
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *MotorL = AFMS.getMotor(1);
Adafruit_DCMotor *MotorR = AFMS.getMotor(2);

void setup() {
  // Initialisiere seriellen Monitor
  Serial.begin(9600);
  // Kalibrierung für den linken LDR-Sensor
  Serial.println("Bitte schwarzen Wert für linken Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Klebeband zu schieben
  blackLeft = analogRead(LDR_LEFT_PIN);
  Serial.print("Schwarz (links): ");
  Serial.println(blackLeft);

  Serial.println("Bitte weißen Wert für linken Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Holz zu schieben
  whiteLeft = analogRead(LDR_LEFT_PIN);
  Serial.print("Weiß (links): ");
  Serial.println(whiteLeft);

  // Kalibrierung für den rechten LDR-Sensor
  Serial.println("Bitte schwarzen Wert für rechten Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Klebeband zu schieben
  blackRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Schwarz (rechts): ");
  Serial.println(blackRight);

  Serial.println("Bitte weißen Wert für rechten Sensor messen...");
  delay(3000); // Warte 3 Sekunden, um Zeit zu geben, auf Holz zu schieben
  whiteRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Weiß (rechts): ");
  Serial.println(whiteRight);
  
  schwelleR = ((blackRight + whiteRight) / 2);
  schwelleL = ((blackLeft + whiteLeft) / 2);
  Serial.print("Schwelle R: ");
  Serial.println(schwelleR);
  Serial.print("Schwelle L: ");
  Serial.println(schwelleL);
  
  // Initialisiere das Motor Shield
  AFMS.begin();
  //Rechne Geschwindigkeit aus
  MotorR->setSpeed(110 * Motorspeed);
  MotorL->setSpeed(107 * Motorspeed);
  //Motoren armen (entsischern)
  MotorR->run(RELEASE);
  MotorL->run(RELEASE);
}

void loop() {
  // Lesen der aktuellen Werte der LDR-Sensoren
  int currentLeft = analogRead(LDR_LEFT_PIN);
  int currentRight = analogRead(LDR_RIGHT_PIN);
  Serial.print("Actual L: ");
  Serial.print(currentLeft);
  Serial.print(" - Actual R: ");
  Serial.print(currentRight);  

  if (currentRight <= schwelleR) {
    Serial.println(" --> Left")
    driveLeft();
  } else if (currentLeft <= schwelleL) {
    Serial.println(" --> Right")
    driveRight();
  } else {
    Serial.println(" --> forward")
    forward();
  }
  delay(50); // Kurze Pause
}

void forward() {
  // Beide Sensoren erkennen weiß -> Beide Motoren vorwärts
  MotorR->run(FORWARD);
  MotorL->run(FORWARD);
}

void driveRight() {
  //Linker Sensor erkennt schwarz-> rechter Motor muss nachziehen
  MotorR->run(FORWARD);
  MotorL->run(RELEASE);
}

void driveLeft() {
  //Rechter Sensor erkennt schwarz-> linker Motor muss nachziehen
  MotorR->run(RELEASE);
  MotorL->run(FORWARD);
}

so wie du es gemacht hast, macht es mehr Sinnl. (Dass der schwellwert im setup berechnet wird). Danke dir. Ich kann es erst nächste woche wieder ausprobieren, da das Zeug in der Schule liegt.
LG

da hab ich beim Ändern des codes wohl was verwechselt. wenn Rechts schwarz erkennt wird, muss der roboter natürlich nach rechts fahren.
LG

Es kann in der tat sein, dass beide sensoren schwarz melden. Ich muss in die Bedingung also doch ...&& ... reinschreiben oder?

Teste erst Mal den neuen Code

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.