Servo Sketch

Ich versuche ein Sketch zu bauen welcher ein servo antreibt, gesteuert von 2 IR-LED's.

Dies ist der Sketch, der funktioniert eigentlich. nun versuche ich aber, dass der Servo wenn keine Bewegung vor den Sensoren ist auf Mittelstellung 90 geht.
Ich dachte ich versuch das mit einer else funktion das funktioniert aber irgendwie nicht.

else {angle = 90;}

Hier ist der momentane Sketch:

// Servo-Library einbinden
#include <Servo.h>
 
// Servo-Objekt erzeugen
Servo myservo;
 
// Startwinkel für den Servo (Bereich 0-179 Grad)
int angle = 90;
 
 
void setup() {
// Serielle Schnittstelle initialisieren
Serial.begin(9600);
// Pin 3 als Ausgabe-Pin
pinMode(5, OUTPUT);
// Pin 3 ist Steuerpin für den Servo
myservo.attach(5);
}
 
 
void loop() {
 
// Helligkeit der beiden lichtempfindlichen Widerstände
int rightEye = analogRead(2);
int leftEye = analogRead(3);
 
// Differenz ausrechnen
int diff = (rightEye - leftEye);
 
// Wenn rechts deutlich heller als links -> 2 Grad nach rechts drehen
if (diff > 10) {
angle = angle+1; 
}else {angle = 90;} 

 
// Wenn links deutlich heller als rechts -> 2 Grad nach links drehen
if (diff < -10) {
angle = angle-1; 
}else {angle = 90;}



// Servo max. bis 179 Grad drehen
if (angle > 135) {
angle = 135;
}
 
// Servo min. bis 0 Grad drehen
if (angle < 45) {
angle = 45;
}
 
// Grad an den Servo schicken
myservo.write(angle);
 
// Die beiden Helligkeitswerte zu Testzwecken an den PC übertragen
Serial.println(String(rightEye)+"-"+String(leftEye));
 
// Kurze Wartezeit, dann nächste Messung.
// Sollte es beim Testen der Einstellungen zu chaotisch werden,
// diesen Wert einfach auf 50 oder 100 erhöhen und damit den Vorgang verlangsamen
delay(5);
}

Hi, gib doch den Wert von 'angle' auch im Serial-Monitor aus, dann siehst Du vlt. eher, wie sich angle verhält.

Ausserdem schreibst Du in den Kommentaren Deines Sketch verschiedene Grad-Angaben für den Servo, aber programmieren tust Du ganz andere Werte! z.B. '// 2 Grad nach links drehen' -> programmierst aber 'angle = angle -1' ???
oder '// Servo max. bis 179 Grad drehen' programmieren tust Du aber
'if (angle > 135) {
angle = 135;
}'

Du solltest Dir angewöhnen, dass , wenn Du andere Werte programmierst, als in den Kommentaren ausgewiesen, die Kommentare auch anzupassen. Sonst verwirren Kommentare mehr , als dass sie helfen.
Dies auch dann, wenn Du Fremdcode verwendest (copy & paste), sonnst kommst Du später mal, wenn Du Deinen Code anpassen willst, oder auch nur als Grundlage für was Neues nimmst völlig durcheinander, weil Du nicht mehr siehst, was jetzt richtig ist, der Kommentar, oder der Code.

Wenn Du Dir die werte von angle im Serial-Monitor angeschaut hast, ist es dir vlt. auch möglich, genauer zu beschreiben, was nicht funktioniert.
Denn so ist es sehr schwierig den Fehler zu finden.

LG Stefan

Ja, das macht natürlich Sinn. Ich versuch mal den angle wert im serial monitor auszugeben.

Ja, tue das bitte, und wenn Du dann selber den Fehler noch nicht findest, dann melde Dich doch einfach wieder hier und versuche uns , infos zu geben, wie Deine Tests verlaufen sind. Ambesten dann mit den Testergebnisen.

Ich kann es leider im Moment nicht testen, da einerseits alle meine Arduinos grad in nem Testaufbau miteinander kommunizieren und dabei ein Langzeit-Stabilitätstest läuft, den ich nicht unterbrechen möchte.
Und andererseits ich grad noch ne Platine bestücken muss. OK sind nur 440 Lötstellen.

Sorry, dass ich Dir grad nicht mehr Zeit widmen kann.
LG Stefan

Deltaflyer:
Ja, tue das bitte, und wenn Du dann selber den Fehler noch nicht findest, dann melde Dich doch einfach wieder hier und versuche uns , infos zu geben, wie Deine Tests verlaufen sind. Ambesten dann mit den Testergebnisen.

Ich kann es leider im Moment nicht testen, da einerseits alle meine Arduinos grad in nem Testaufbau miteinander kommunizieren und dabei ein Langzeit-Stabilitätstest läuft, den ich nicht unterbrechen möchte.
Und andererseits ich grad noch ne Platine bestücken muss. OK sind nur 440 Lötstellen.

Sorry, dass ich Dir grad nicht mehr Zeit widmen kann.
LG Stefan

Ok, ich meld mich dann. Gutes Löten! :wink:

So wie du die Abfragen machst ist immer eine "else" option aktiv und du wirst dich immer um 90 Grad rum bewegen.
Wenn diff > 10 dann ist diff ungleich < -10 und somit 90 Grad.
Wenn diff < -10 dann ist diff ungleich > 10 und somit auch 90 Grad.

Kadara:
So wie du die Abfragen machst ist immer eine "else" option aktiv und du wirst dich immer um 90 Grad rum bewegen.
Wenn diff > 10 dann ist diff ungleich < -10 und somit 90 Grad.
Wenn diff < -10 dann ist diff ungleich > 10 und somit auch 90 Grad.

Hmm du hast recht, ein logischer Denkfehler! Ich habs mal probiert mit einem zusätzlichen "If"

if (diff =0)
angle =90;

ist aber immer noch nicht das richtige.

Wie sieht denn der gesammte Code jetzt aus?

Die else Bedingungen musst du dann natürlich rauswerfen.
Und die dritte if würd ich nicht nur auf diff 0 setzen.
If ((diff >= -10) && (diff <= 10)) deckt dann den Bereich ab den du mit den anderen Bedingungen nicht einfängst.

Vielen Dank für den Input so funktioniert das.
Unten der Code. Einziger Schönheitsfehler ist, dass der Servo im Unterschied zu den anderen Bewegungen sehr schnell zur Position 90 zurück bewegt.

// Servo-Library einbinden
#include <Servo.h>
 
// Servo-Objekt erzeugen
Servo myservo;
 
// Startwinkel für den Servo (Bereich 0-179 Grad)
int angle = 90;
 
 
void setup() {
// Serielle Schnittstelle initialisieren
Serial.begin(9600);
// Pin 5 als Ausgabe-Pin
pinMode(5, OUTPUT);
// Pin 5 ist Steuerpin für den Servo
myservo.attach(5);
}
 
 
void loop() {
 
// Helligkeit der beiden lichtempfindlichen Widerstände
int rightEye = analogRead(2);
int leftEye = analogRead(3);
 
// Differenz ausrechnen
int diff = (rightEye - leftEye);
 
// Wenn rechts deutlich heller als links -> 2 Grad nach rechts drehen
if (diff > 20) {
angle = angle+2;
}
if ((diff >= -10) && (diff <= 10))
angle = 90;
 
// Wenn links deutlich heller als rechts -> 2 Grad nach links drehen
if (diff < -20) {
angle = angle-2;
}
if ((diff >= -10) && (diff <= 10))
angle = 90;

 
// Servo max. bis 179 Grad drehen
if (angle > 179) {
angle = 179;
}
 
// Servo min. bis 0 Grad drehen
if (angle < 0) {
angle = 0;
}
 
// Grad an den Servo schicken
myservo.write(angle);
 
// Die beiden Helligkeitswerte zu Testzwecken an den PC übertragen
Serial.println(String(rightEye)+"-"+String(leftEye)); 
 
// Kurze Wartezeit, dann nächste Messung.
// Sollte es beim Testen der Einstellungen zu chaotisch werden,
// diesen Wert einfach auf 50 oder 100 erhöhen und damit den Vorgang verlangsamen
delay(20);
}

Das du es 2x machst, bringt dir nicht viel.
Und jetzt hast du wieder 10 differenzpunkte je Richtung die nicht abgedeckt sind.
Ich würde den Bereich +-20 eben immer auf 90 Grad korrigieren, aber im selben Stil wie die anderen Korrekturen.
Dann sollte auch die Geschwindigkeit passen.

// Wenn rechts deutlich heller als links -> 2 Grad nach rechts drehen
if (diff > 20) {
angle = angle+2;
}
 
// Wenn links deutlich heller als rechts -> 2 Grad nach links drehen
if (diff < -20) {
angle = angle-2;
}

if ((diff >= -20) && (diff <= 20) && (angle >90){
angle = angle-2;
}

if ((diff >= -20) && (diff <= 20) && (angle <90){
angle = angle+2;
}

Was jetzt noch unschön ist, ist das du mit 179 die 2er Reihe brichst.
Damit pendelst du immer zwischen 89 und 91 hin und her.
Entweder 180 nehmen oder 178.
Oder den Mittenbereicht mit +-1 korrigieren.
Oder noch nen Satz einfügen mit if ((angle == 89) || (angle == 91)) angle = 90;

Heureka das funktioniert - Du bist mein Held Kadera!! :slight_smile:
Arduino wollte noch 2 Klammern je: if ((diff >= -20) && (diff <= 20) && (angle >90) die hab ich ihm gegeben.
Sio sieht der Sketch nun aus:

 // Servo-Library einbinden
#include <Servo.h>

// Servo-Objekt erzeugen
Servo myservo;

// Startwinkel für den Servo (Bereich 0-179 Grad)
int angle = 90;


void setup() {
// Serielle Schnittstelle initialisieren
Serial.begin(9600);
// Pin 5 als Ausgabe-Pin
pinMode(5, OUTPUT);
// Pin 5 ist Steuerpin für den Servo
myservo.attach(5);
}


void loop() {

// Helligkeit der beiden lichtempfindlichen Widerstände
int rightEye = analogRead(2);
int leftEye = analogRead(3);

// Differenz ausrechnen
int diff = (rightEye - leftEye);

// Wenn rechts deutlich heller als links -> 2 Grad nach rechts drehen
if (diff > 20) {
  angle = angle + 2;
}

// Wenn links deutlich heller als rechts -> 2 Grad nach links drehen
if (diff < -20) {
  angle = angle - 2;
}

if ((diff >= -20) && (diff <= 20) && (angle > 90)) {
angle = angle - 2;
}

if ((diff >= -20) && (diff <= 20) && (angle < 90)) {
angle = angle + 2;
}


// Servo max. bis 140 Grad drehen
if (angle > 140) {
angle = 140;
}

// Servo min. bis 46Grad drehen
if (angle < 46) {
angle = 46;
}

// Grad an den Servo schicken
myservo.write(angle);

// Die beiden Helligkeitswerte zu Testzwecken an den PC übertragen
Serial.println(String(rightEye) + "-" + String(leftEye));

// Kurze Wartezeit, dann nächste Messung.
// Sollte es beim Testen der Einstellungen zu chaotisch werden,
// diesen Wert einfach auf 50 oder 100 erhöhen und damit den Vorgang verlangsamen
delay(20);
}

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Außerdem entferne bitte die unnötigen Leerzeilem und formatiere den Code ordentlich (+T in der IDE hilft Dir dabei).

Gruß Tommy

Ich hab noch versucht bevor der Servo auf 90 dreht einen kleinen Delay (zB. 500) einzubauen. Das habe ich aber noch nicht geschaft. Werde es später nochmal probieren.

Tommy56:
Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Außerdem entferne bitte die unnötigen Leerzeilem und formatiere den Code ordentlich (+T in der IDE hilft Dir dabei).

Gruß Tommy

Sorry wollte ich eigentlich so machen. kann ich erst in 5 min. korrigieren :wink:

Oops, da hab ich wohl ne Klammer zu vergessen und gleich noch nen Kopierfehler hinterher gemacht.
Aber hast es ja selbst gefunden.
Schön das es klappt.
Wegen dem Delay sollte das mit einer zusätzlichen Variable machbar sein.
Wenn du das erste mal in die Schleife springst, wo du ein Delay haben willst, dann führe es aus und ändere die Variable das er es beim nächsten Zyklus nicht mehr aufruft.
In den anderen Schleifen setzt du die Variable wieder zurück das es wieder ausgeführt werden kann.
Blöd wirds halt, wenn du grade wartest, aber ne spontane Änderung kommt.
Dann wartet er nämlich erstmal bis das delay abgearbeitet ist.
Daher ist besser das delay anders auszuführen.
Such mal nach blink without delay, oder der Nachtwächter wenns mit nem normalen delay klappt.

Danke, ich probier was raus zu finden :wink:

Also ehrlich gesagt bin ich da "noch" etwas überfordert.
Ich hab nun von jemandem aus dem englischen Forum folgenden Code bekommen:

#include <Servo.h>
Servo myservo;
int angle = 90;

void setup() {
  Serial.begin(9600);
  pinMode(5, OUTPUT);
  myservo.attach(5);
}

void loop() {
  static uint32_t moment = millis();
  int rightEye = analogRead(2);
  int leftEye = analogRead(3);
  int diff = (rightEye - leftEye);
  if (diff > 10) {
    angle = angle + 1;
    moment = millis();  // reset the timer
  }
  if (diff < -10) {
    angle = angle - 1;
    moment = millis();  // reset the timer
  }
  if (abs(diff) > 20) delay(5);  // delay depending on the speed
  else if (abs(diff) > 10) delay(10);

  if (angle > 135) {
    angle = 135;
  }
  if (angle < 45) {
    angle = 45;
  }
  if (millis() - moment > 15000) { // if elapsed time exceeds 15 secs
    if (angle < 90) angle++;
    if (angle > 90) angle--;
    delay(3); // and here as well.
  }
  myservo.write(angle);
  Serial.println(String(rightEye) + "-" + String(leftEye));
  //  delay(5);  // remove it here
}