Verzweiflung program macht was es will :((

hallo zusammen,

seit einigen tagen arbeite ich an meinem roboter projekt
momentan ist es eine laffette mit einem srf02 us sensor einem servo mit sharp gp2d12 ir-sensor

das programm soll vollgendermassen arbeiten
-Fahren
-alle 30sec den us-sensor abfragen
-wenn der wert kleiner als 30 ist
-stoppen
-servo nach links
-ir messung
-servo nach rechts
-ir messung
-messerwerte vergleichen und dementsprechen drehen

mein problem ist das das programm total dureinander läuft so scheint es zumindestens
das servo arbeitet sich immer wieder von links nach rechts obwohl der us kein wert kleiner 30 ausgi bt

bitte um hilfe

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INCLUDE

#include "Wire.h"
#include "SRF02.h"
#include <Servo.h>
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VARIABLES

SRF02 sensor(0x70, SRF02_CENTIMETERS);
unsigned long nextPrint = 0;

Servo myservo;

int irpin = 0;
// Motor Pins

int motor_RechtsPWM = 5; //PWM Motor Rechts
int motor_Rechts1 = 3;
int motor_Rechts2 = 6;

int motor_LinksPWM = 11; //PWM Motor Links
int motor_Links1 = 4;
int motor_Links2 = 7;

//Servo und IR
// Position des Servos
int rechts = 0;
int links = 120;

//Variable für Messert
int IrRechts;
int IrLinks;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SETUP
void setup()
{
Wire.begin();
Serial.begin(9600);
myservo.attach(9); //servo an pin9

pinMode(motor_RechtsPWM, OUTPUT);
pinMode(motor_Rechts1, OUTPUT);
pinMode(motor_Rechts2, OUTPUT);

pinMode(motor_LinksPWM, OUTPUT);
pinMode(motor_Links1, OUTPUT);
pinMode(motor_Links2, OUTPUT);
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LOOP
void loop() {
{
//Fahren
analogWrite(motor_RechtsPWM, 200);
digitalWrite(motor_Rechts1, HIGH);
digitalWrite(motor_Rechts2, LOW);

analogWrite(motor_LinksPWM, 200);
digitalWrite(motor_Links1, HIGH);
digitalWrite(motor_Links2, LOW);

}
{
SRF02::update();
if (millis() > nextPrint)
{
Serial.println(sensor.read());
nextPrint = millis () + 500;
}
}
if (sensor.read() < 30)
{
{
//stop
analogWrite(motor_RechtsPWM, 0);
digitalWrite(motor_Rechts1, HIGH);
digitalWrite(motor_Rechts2, LOW);

analogWrite(motor_LinksPWM, 0);
digitalWrite(motor_Links1, HIGH);
digitalWrite(motor_Links2, LOW);

}
{
myservo.write(rechts); // tell servo to go to position in variable 'pos'
delay(2000); // waits 15ms for the servo to reach the position
}
{
IrRechts=analogRead(irpin);
delay(100);
}
{
myservo.write(links); // tell servo to go to position in variable 'pos'
delay(2000); // waits 15ms for the servo to reach the position
}
{
IrLinks=analogRead(irpin);
delay(100);
}

if ((IrRechts) <(IrLinks))
{

//links drehen
analogWrite(motor_RechtsPWM, 100);
digitalWrite(motor_Rechts1, HIGH);
digitalWrite(motor_Rechts2, LOW);

analogWrite(motor_LinksPWM, 0);
digitalWrite(motor_Links1, HIGH);
digitalWrite(motor_Links2, LOW);
delay(100);
return;

}
else if ((IrRechts)> (IrLinks))
{

//rechts drehen
analogWrite(motor_RechtsPWM, 0);
digitalWrite(motor_Rechts1, HIGH);
digitalWrite(motor_Rechts2, LOW);
Serial.println("rechts");
analogWrite(motor_LinksPWM, 100);
digitalWrite(motor_Links1, HIGH);
digitalWrite(motor_Links2, LOW);
delay(100);
return;

}
}
}

Als erstes solltest Du mal die Klammern in Deinem Programm ein wenig aufräumen, die sind zwar nicht falsch, aber an einigen Stellen unnötig und damit verwirrend.
Klammern umschliessen Blöcke, wie z.B. von Schleifen, Verzweigungen (if - else) oder auch Funktionen.
Sowas wie

void loop() {
{
    //Fahren
  analogWrite(motor_RechtsPWM, 200);
  digitalWrite(motor_Rechts1, HIGH);
  digitalWrite(motor_Rechts2, LOW); 
  
  analogWrite(motor_LinksPWM, 200);
  digitalWrite(motor_Links1, HIGH);
  digitalWrite(motor_Links2, LOW); 
  
}
{
  SRF02::update();
  if (millis() > nextPrint)
  {
   Serial.println(sensor.read());
    nextPrint = millis () + 500;
  }
}

Ist identisch mit


Damit Du den Ablauf Deines Programms besser überblicken kannst, würde ich z.b. die einzelnen Teile in Funktionen packen, und die in der Loop nur noch aufrufen.
z.B.

void fahren() {
    //Fahren
  analogWrite(motor_RechtsPWM, 200);
  digitalWrite(motor_Rechts1, HIGH);
  digitalWrite(motor_Rechts2, LOW); 
  
  analogWrite(motor_LinksPWM, 200);
  digitalWrite(motor_Links1, HIGH);
  digitalWrite(motor_Links2, LOW); 

}


void loop() {

  fahren();

  SRF02::update();
  if (millis() > nextPrint)
  {
   Serial.println(sensor.read());
    nextPrint = millis () + 500;
  }
...

Das Gleiche dann für das Drehen und Messen mit dem Servo und dem Sensor. Ansonsten sehe ich in Deinem Code auch nichts, was die 30 Sekunden umsetzen würde, die Du als Zeitrahmen für das Fahren und dann Messen angegeben hast. Aktuell macht Dein Programm in der loop() folgendes:
{
Fahren

Sensor update

alle 0,5 Sekunden den gemessenenAbstand seriell ausgeben

wenn abstand < 30:

  • anhalten
  • servo nach rechts drehen (2 sek. warten)
  • IR-messen (0,1 sek. warten)
  • servo nach links drehen (2 sek. warten)
  • IR-messen (0,1 sek. warten)
  • wenn rechts < links:
  • linkskurve für 0.1 sekunde fahren
  • return (springt aus der loop / beendet loop, die dann aber gleich wieder aufgerufen wird)
  • wenn rechts > links:
  • rechtskurve für 0.1 sekunde fahren
  • return (springt aus der loop / beendet loop, die dann aber gleich wieder aufgerufen wird)
    }

danke für die schnelle antwort!

ich werde meinen code mal aufräumen :smiley:

aber das eigendliche Problem ist das wenn ich das prog starte erst das servo gedreht wird und dann manchmal aus undifinierbaren gründen der bot dreht.

dabei sagt ja das prog das gefahren werden soll

kann es sein das der srf02 am anfang noch keine "sauberen" werte liefert z.b. den wert 0 ????

daszu kommt das er anstatt 1x links und 1x rechts schaut den vorgang mehrmals wiederholt..

wo liegt das problem?

sry bin noch zimlich neu im bereich arduino und c :frowning:

schonmal vielen dank für eure hilfe

Was sein kann und was nicht hängt auch an Deiner Hardware. Die übliche Vorgehensweise ist mit print auf der seriellen Schnittstelle auszugeben was los ist.

Du kannst wie Udo vorschlägt die Sensorwerte seriell ausgeben und am Terminal des IDE anschauen.
Du kannst auch 2 LED ansteuern wenn der Abstand den der Sensor mißt kleiner als 30 cm ist; so weißt Du was der Sensor mißt und das erklährt vielleicht das Verhalten des Teils.
Grüße Uwe

danke für die tips
werde es direkt mal versuchen

werde mich dann morgen wieder mit ergebnissen melden :slight_smile:

so hab nun mal meinen code neu geordnet und überarbeitet
dazu auch mal alles über serial.print ausgeben lassen.

mein problem ist anscheinend, dass der srf02 us sensor bei den ersten 2-3 messungen einen wert von 0 ausgibt und erst danach die korekte distanz ausgibt dieses passiert sowohl beim einschalten als auch nach dem drehen.

den code fürs auslesen des srf02 und die lib habe ich 1-1 übernommen

hier erstmal mein aktueller code:

// - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - INCLUDE

#include "Wire.h"
#include "SRF02.h"
#include <Servo.h> 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  VARIABLES

SRF02 sensor(0x70, SRF02_CENTIMETERS);
unsigned long nextPrint = 0;

Servo myservo;

// Motor Pins

int motor_RechtsPWM = 5;  //PWM Motor Rechts
int motor_Rechts1 = 3;
int motor_Rechts2 = 6;

int motor_LinksPWM = 11;  //PWM Motor Links
int motor_Links1 = 4; 
int motor_Links2 = 7; 

//Servo und IR
// Position des Servos
int rechts = 0;   
int links = 120;  
int irpin=0;
//Variable für Messert
int IrRechts;     
int IrLinks;

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  SETUP
void setup()
{
  Wire.begin();
  Serial.begin(9600);
  myservo.attach(9);  // Servor myservo an Pin9
  pinMode(motor_RechtsPWM, OUTPUT);
  pinMode(motor_Rechts1, OUTPUT);
  pinMode(motor_Rechts2, OUTPUT);

  pinMode(motor_LinksPWM, OUTPUT);
  pinMode(motor_Links1, OUTPUT);
  pinMode(motor_Links2, OUTPUT);

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  LOOP
void loop() {


  SRF02::update();
  if (millis() > nextPrint)
  nextPrint = millis () + 1000; 
  Serial.println("Us-Sensor");
  Serial.println(sensor.read());
}
 
  if (sensor.read() <50)
  {

    stopp();
    delay(500);
    servo();
    
    if ((IrRechts) <(IrLinks))
    { 
      drehenL();
    }
    else if ((IrRechts)> (IrLinks))
    {
      drehenR();
    }
  }
  if (sensor.read()> 50)
  {
    fahren();
  }
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - Funktionen
void fahren()
{
  Serial.println("fahren");
  analogWrite(motor_RechtsPWM, 100);
  digitalWrite(motor_Rechts1, HIGH);
  digitalWrite(motor_Rechts2, LOW); 

  analogWrite(motor_LinksPWM, 100);
  digitalWrite(motor_Links1, HIGH);
  digitalWrite(motor_Links2, LOW); 
}

void stopp()
{
  Serial.println("stopp");
  analogWrite(motor_RechtsPWM, 0);
  digitalWrite(motor_Rechts1, HIGH);
  digitalWrite(motor_Rechts2, LOW); 

  analogWrite(motor_LinksPWM, 0);
  digitalWrite(motor_Links1, HIGH);
  digitalWrite(motor_Links2, LOW); 
}

void drehenR()
{
  Serial.println("drehen Rechts");
  analogWrite(motor_RechtsPWM, 0);
  digitalWrite(motor_Rechts1, HIGH);
  digitalWrite(motor_Rechts2, LOW); 

  analogWrite(motor_LinksPWM, 100);
  digitalWrite(motor_Links1, HIGH);
  digitalWrite(motor_Links2, LOW); 
  delay(1000);
}

void drehenL()
{
  Serial.println("drehen links");
  analogWrite(motor_RechtsPWM, 100);
  digitalWrite(motor_Rechts1, HIGH);
  digitalWrite(motor_Rechts2, LOW); 

  analogWrite(motor_LinksPWM, 0);
  digitalWrite(motor_Links1, HIGH);
  digitalWrite(motor_Links2, LOW); 
  delay(1000);
}

void servo()
{
  {
    Serial.println("servo links");
    myservo.write(links);
    delay(500);
  }
  Serial.println("messung LINKS");
  IrLinks = analogRead(irpin);
  Serial.println(IrLinks);
  delay(1000);

  {
    Serial.println("servo rechts");
    myservo.write(rechts);
    delay(500);

  }
  Serial.println("messung RECHTS");
  IrRechts = analogRead(irpin);
  Serial.println(IrRechts);
  delay(1000);
}

und hier der original code vom srf02 ich muss anmerken wenn ich nur diesen benutze bekomme ich direkt den richtigen wert ausgegeben :frowning:

/*
 * SRF02 library example code
 *
 * Reads values from a single SRF02 sensor and writes to the serial
 * interface at 9600 baud.
 *
 * The contents of this file are subject to the Apache License Version
 * 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is grappendorf.net Arduino Libraries / SRF02.
 *
 * The Initial Developer of the Original Code is
 * Dirk Grappendorf (www.grappendorf.net)
 * Portions created by the Initial Developer are Copyright (C) 2008-2011
 * the Initial Developer. All Rights Reserved.
 */


#include "Wire.h"
#include "SRF02.h"

SRF02 sensor(0x70, SRF02_CENTIMETERS);

unsigned long nextPrint = 0;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  SRF02::update();
  if (millis() > nextPrint)
  {
	Serial.println(sensor.read());
    nextPrint = millis () + 1000;
  }
}

hoffe es ist ein behebbares problem ... :((

Also mal davon abgesehen, dass Dein Code ein Race Condition enthält (die mit dem Problem nichts zu tun hat) würde ich sagen, dass Du gar kein Softwareproblem hast. Für mich hört sich das an wie ein Hardwareproblem. Genauer: ich würde vermuten, die Motoren verursachen ausreichend große Rückwirkungen um den Sensor zu stören. Ohne Schaltplan kommen wir an der Stelle aber nicht weiter. Wie sieht Deine Schaltung aus?

Geht es nur um die Ausgabe?

Probiere doch mal folgende Änderung:

void loop() {


  SRF02::update();
  if (millis() > nextPrint)
  {
    nextPrint = millis () + 1000; 
    Serial.println("Us-Sensor");
    Serial.println(sensor.read());
  }
}

Im Originalcode sind die Klammern für die if-Bedingung anders als bei dem von dir geposteten Code.

Rudi

hmm stimmt da fehlte ne klammer .. ABER trozdem bekomme ich noch bei den ersten 2-3 messungen einen wert von null ....

kann es sein das das programm an der stelle des auslesens zu schnell läuft? weil ich habe gelesen das der srf02 70milli sec brauch um eine messung abzuschlissen.

Versuch macht klug. Setz doch einfach einen Delay rein und schau was passiert.

so habe gestern abend mal versucht die sensoren ganz ohne motor zu testen selbe problem.

ich habe hier für mein motortreiber abgesteckt so das nur noch die uno mit dem servo ir und us sensor aktiv war das selbe problem. habe zudem extra die leitungen für den us seperat gelegt ...

Tja, dann ist Dein Code vermutlich nicht mehr so wie Du ihn hier gepostet hast. Da hier keiner eine Glaskugel hat musst Du den schon wieder hier reinstellen.

Davon abgesehen ist es schlau fehlerhaften Code solange einzudampfen bis man ein Minimalbeispiel hat bei dem der Fehler gerade noch auftritt. Das macht die Fehlersuche in der Regel sehr viel leichter.