Das Problem mit der Ecke

Auf einem RP5 Raupenfahrgestell ist ein Seeeduino Mega montiert.
Sensoriken sind ein paar LDR’s, Accelerometer, elektrisches Mikro, Sharp Ir-Detektoren und Sharp Ir-Sensoren.
Die Motoren des Fahrgestelles werden mit einer H-brücke gesteuert.

Bin gerade am werkeln mit meinem Autonomen Modus. Funktioniert alles soweit ganz gut. Der Bot sieht ob ein hindernis mehr rechts oder mehr links zu ihm steht und weicht dann dem entsprechend aus.

Wenn ich nun aber in eine Ecke fahre oder Hindernisse eng aneinander stehen kommt er in Entscheidungsnot. Er weicht zuerst links aus dann sieht er es wieder rechts und dreht sich wieder in die andere Richtig und pendelt in diesem Falle hin und her bis er ein Schlupfloch gefunden hat.

Habe nun schon mit verschiedenen Ansätzen versucht, dass er sich seine vergangenen Entscheidungen merkt und nach mehrmaligen gleichen Zyklen z. B. eine 180 ° drehung macht oder Ähnliches.

Komme aber irgendwie nicht weiter.
Hoffe ihr könnt mir einen Denkanstoß geben, der mich in die richtige Richtung lenkt.

Hier noch meine missglückten Ansätze:

void FWD() 
{
  x++;
  digitalWrite(enablePin, HIGH);
  digitalWrite(motorAPin1, LOW);
  digitalWrite(motorAPin2, HIGH);
  analogWrite(PWMA, 150);
  digitalWrite(motorBPin1, LOW);
  digitalWrite(motorBPin2, HIGH);
  analogWrite(PWMB, 150);
}

void DrehLi() 
{
  if (x < 1 &&  rechts > 0) {
    rechts = 0;
    x = 0;
    BWD();
    delay(1000);
    DrehRe();
    delay(3200);
    FWD();
  }
  
  else {
  digitalWrite(enablePin, HIGH);
  digitalWrite(motorAPin1, HIGH);
  digitalWrite(motorAPin2, LOW);
  analogWrite(PWMA, 150);
  digitalWrite(motorBPin1, LOW);
  digitalWrite(motorBPin2, HIGH);
  analogWrite(PWMB, 150);
  links++;
  }
}


void DrehRe() 
{
  if (x < 1 &&  links > 0) {
    links = 0;
    x = 0;
    BWD();
    delay(1000);
    DrehLi();
    delay(3200);
    FWD();
  }
  
  else {
  digitalWrite(enablePin, HIGH);
  digitalWrite(motorAPin1, LOW);
  digitalWrite(motorAPin2, HIGH);
  analogWrite(PWMA, 150);
  digitalWrite(motorBPin1, HIGH);
  digitalWrite(motorBPin2, LOW);
  analogWrite(PWMB, 150);
  rechts++;
  }
}

Habe versucht mit der variable x Zeit zu messen die der Bot vörwärts fährt. Jedesmal wenn er Rechts oder Links ausweicht erhöht sich die jeweilige Variable links++ oder rechts++.

Das habe ich dann versucht zu kombinieren. Wenn er nicht lange Vorwärts gefahren ist und schon rechts ausgeweicht ist, soll er nicht links ausweichen sondern eine 180 ° Drehung machen und anders genauso. Ist bis jetzt nicht sehr erfolgreich.

Gruß Chris

Das Problem liegt nicht notwendig in dem Schnipsel den Du in Deiner Nachricht drin hast. Wie sieht der Rest des Codes aus?

Gruß, Udo

....
void loop() {
  n = digitalRead(encoder0PinA);
  Enter = digitalRead(17);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } 
    else {
      encoder0Pos++;
    }

  } 
  encoder0PinALast = n;

  if (encoder0Pos < 2) {
    lcd.clear();
    lcd.print("Bitte Encoder");
    lcd.setCursor(0, 1);
    lcd.print("drehen"); 
    delay(50);
  } 
  if (encoder0Pos == 2 && wii == false && Auto == false && pressed1 == false) {
    lcd.clear();
    lcd.print("<Lichtsucher>");
    lcd.setCursor(0, 1);
    lcd.print(" WII-Mode");
    delay(50);
    ldr = true;

  }
  if (ldr == true && Enter == HIGH) {
    pressed1 = true;
  }
  if (ldr == true && pressed1 == true) {
    LDR();
  }
  if (encoder0Pos == 3) {
    ldr = false;
    pressed1 = false;
  }  
  if (encoder0Pos == 3 && ldr == false && Auto == false && pressed2 == false) {
    lcd.clear();
    lcd.print("<WII-Mode>");
    lcd.setCursor(0, 1);
    lcd.print(" Autonom");
    delay(50);

    wii = true; 
    lcd.clear(); 
  } 
  if (wii == true && Enter == HIGH) {
    pressed2 = true;
  }
  if (wii == true && pressed2 == true) {
    nunchuck();
  } 
  if (encoder0Pos > 3) {
    wii = false;
    pressed2 = false;
  }
  if (encoder0Pos > 3 && ldr == false && wii == false && pressed3 == false) {
    lcd.clear();
    lcd.print("<Autonom>");
    lcd.setCursor(0, 1);
    lcd.print("......");
    delay(50);
    Auto = true; 
    lcd.clear(); 
  } 
  if (Auto == true && Enter == HIGH) {
    pressed3 = true;
  }
  if (Auto == true && pressed3 == true) {
    autonomous();
  } 

}
void autonomous() {
  lcd.print("Autonom aktiv                 ");
  FWD();
  SharpLFT = analogRead(Sharp1);
  delay(10);
  SharpRHT = analogRead(Sharp2);
  delay(10);
  IRLFT = digitalRead(BMP1);
  delay(10);
  IRRHT = digitalRead(BMP2);
  delay(10);
  if ((SharpLFT > 280 && SharpRHT < 280) && (!(SharpLFT > 380 && SharpRHT > 380)))  {
    DrehRe();
    delay(1000);
    FWD();
  }

  if ((SharpLFT < 280 && SharpRHT > 280)  && (!(SharpLFT > 380 && SharpRHT > 380))) {
    DrehLi();
    delay(1000);
    FWD();
  }
  
   if (IRLFT ==LOW) {
    DrehRe();
    delay(400);
    FWD();
   }
   
   if (IRRHT ==LOW) {
    DrehLi();
    delay(400);
    FWD();
    
   }
  if (SharpLFT > 380 && SharpRHT > 380) {
    BWD();
    delay(1000);
    DrehRe();
    delay(3000);
    FWD();
  }
  lcd.clear(); 
}
void FWD()
{
  x++;
  digitalWrite(enablePin, HIGH);
  digitalWrite(motorAPin1, LOW);
  digitalWrite(motorAPin2, HIGH);
  analogWrite(PWMA, 150);
  digitalWrite(motorBPin1, LOW);
  digitalWrite(motorBPin2, HIGH);
  analogWrite(PWMB, 150);
}

void DrehLi()
{
  if (x < 1 &&  rechts > 0) {
    rechts = 0;
    x = 0;
    BWD();
    delay(1000);
    DrehRe();
    delay(3200);
    FWD();
  }
  
  else {
  digitalWrite(enablePin, HIGH);
  digitalWrite(motorAPin1, HIGH);
  digitalWrite(motorAPin2, LOW);
  analogWrite(PWMA, 150);
  digitalWrite(motorBPin1, LOW);
  digitalWrite(motorBPin2, HIGH);
  analogWrite(PWMB, 150);
  links++;
  }
}


void DrehRe()
{
  if (x < 1 &&  links > 0) {
    links = 0;
    x = 0;
    BWD();
    delay(1000);
    DrehLi();
    delay(3200);
    FWD();
  }
  
  else {
  digitalWrite(enablePin, HIGH);
  digitalWrite(motorAPin1, LOW);
  digitalWrite(motorAPin2, HIGH);
  analogWrite(PWMA, 150);
  digitalWrite(motorBPin1, HIGH);
  digitalWrite(motorBPin2, LOW);
  analogWrite(PWMB, 150);
  rechts++;
  }
} 

....

Das ist der Rest des Sketches, zumindest der Teil der den Autonomen Modus bestimmt.

Eigentlich erst ab void autonomous() interessant für das hier beschriebende Problem.

Danke Chris

Der Code ist immer noch schwierig zu durchschauen. Es steht ja nirgends ein Kommentar was die Sensoren eigentlich unter welchen Bedigungen liefern und/oder wie sie montiert sind.

Hast Du Dir schon mal überlegt die kritischen Stellen mit Serial.print zuzupflastern und auf der seriellen Schnittstelle mitzulesen wieso Dein Roboter anfängt zu zicken?

Gruß, Udo

Mein Code war prinzipiell richtig. Hatte für die Variable x welche sich beim Vorwärtsfahren hochrechnet (x++) einen viel zu kleinen Wert abgefragt. In 1-2 Sekunden ist x =>10. Da ich aber

if (x < 1) {}

abfragte, trat diese Bedingung nie ein. Trotzdem danke für die Anteilnahme. Das mit dem Serial.print hat mich erst darauf gebracht.
Manchmal sind die einfachsten Sachen die erfolgreichsten.
Danke hierfür.

Gruß Chris

Auf alle Fälle solltest Du die Sensoren vertikal montieren... das aber nur zur optimierung...

Weiterhin läßt man die Sensoren oft schielen... dann kann man den relativen abstand besser interpolieren...

Lieber Gruß ChrisS

@ChrisS

Vertikal..hab das auch schon öfters gesehen. Warum ist das denn besser? Kannst du mir das mit dem Schielen und den relativen Messwerten mal genauer erklären?

Danke Chris

Die Sensoren haben eine (aus meiner Sicht sehr blöde) Eigenart.

Du misst ein Objekt welches gerade so horizontal im Messbereich steht... er gibt Dir den Abstand aus... soweit so schön...

Nun schiebst Du ein Objekt dahinter... was ebenfalls in den Messbereich ragt...

Nun springt der Abstandswert auf das Objekt welches hinter dem Vorderen steht.... und so bleibts....

Blöde... weil ja etwas näher ist.... Bumms... haste eine kollision mit dem vorderen Objekt.... weil er als letztes auf dem Messwert des hinteren Objekts hängen bleibt....

Naja, das ganze passiert aber nur wenn sich objekte in horizontal-Achse zum Sensor befinden...

Montierst du den Sensor vertikal, müßte ein Objekt in vertikaler Richtung in den aktuellen messbereich wandern... das passiert aber nicht, solange du deinen Bot nicht "wippen" läßt....

deshalb werden diese Sensoren vertikal montiert....

Was das schielen angeht... der linke Sensor wird ein paar Grad nach rechts geschwenkt, der rechte Sensor nach links...

Was passiert... du hast quasi ein doppeltes Messfeld direkt vor deinem Bot, aber leuchtest je Sensor quasi noch die Gegenüberliegende Ecke aus....

Der Vorteil ist, eine bessere genauigkeit vor dem Bot... und beide Sensoren nehmen auch beide Eck-Bereiche wahr...

Die Sensoren haben ja ein Messfeld was quasi (von oben gesehen) wie ein Fächer aussieht. Wenn Du also den linken Sensor soweit nach rechts drehst, daß der rand des Fächers die rechte Botseite mit misst, und umgekehrt hast du hier auchnochmal eine verbesserung... bist also für die "blöden Messeigenarten" nicht so anfällig.

Beim schielen mußt du allerdings darauf achten daß die Sensoren sich nicht gegenseitig durch das ausgesendete Licht beeinflussen....

http://www.nightwulf.org/bot_scheuklappen.jpg

Sicher ein bisschen übertrieben.... es sollte nur so sein, daß das ausgesendete licht des einen Sensors nicht auf den anderen Sensor treffen kann... aber dafür haben die Sensoren ja schon entsprechende Blenden...

Die Schemazeichnung vom Schielen kann ich gerade nicht finden... war ich nur mal drüber gestolpert... war von irgendeiner Uni....

kannst dazu auchnochmal im RN fragen... das ist ja deren Fachgebiet....

Das Problem mit dem Entscheiden liegt aber in der Software....

Hoffe ich konnte Dir ein bisschen helfen...

Lieber Gruß ChrisS