Ultraschall Sensor steuert Servo an - oder eben nicht!

Hallo zusammen!
Da ich bei meinem Projekt nicht mehr weiter komme (blutiger Anfänger) dachte ich mir - postest hier mal im Forum und schaust ob Dir jemand weiter helfen kann. ...tja... und nun bin ich hier gelandet! Worum geht es? Ich habe hier diesen PING Ultraschall-Sensor und einen Servo, welche ich miteinander interagieren lassen möchte. D.h. sinkt die gemessene Entfernung z.B. unter 30 cm ab, möchte ich das Servo von der Nullstellung in die 180 Grad Stellung bringen. Misst der Ultraschall-Sensor dann wieder eine Entfernung über 30 cm, soll der Servo wieder zurück in Ausgangsstellung fahren.
Das habe ich schon geschafft --> Die Abtastung und die Schleife habe ich so weit hin bekommen, dass der Sensor wie oben beschrieben ein Relais schalten kann. Das Relais schaltet dann momentan einen Servosteller (externe Baugruppe), welcher wiederum das Servo ansteuert. Jetzt dachte ich mir, baust einfach den "Servo-Code" an die Stelle wo Du das Relais auf High oder Low schaltest und schon kannst Dir den Servosteller sparen! Doch leider bekomme ich eben das nicht hin - bastel nun schon gute zwei Abende an einer direkten Steuerung herum, doch leider funktioniert das nicht so, wie ich es mir vorstelle - entweder das Relais zuckt nur komisch rum oder es fährt planlos durch die Gegend - egal welcher Abstand vom Sensor gemessen wird. ...und ich habe ehrlich gesagt keine Idee mehr, wo ich suchen kann um der Lösung näher zu kommen! Wenn ich den einfachen Beginner-Code teste ...bei dem das Relais einfach in 180 Grad Stellung fährt und danach wieder zurück, funktioniert die Ansteuerung ohne Probleme! Vielleicht hat ja hier jemand einen Tipp, bzw. den richtigen Code für mich! (PING = 4-polig) (der Sensor befindet sich nicht auf dem Servo, sondern arbeitet getrennt davon!
Vielen Dank!
Martin

EPICENTER:
Vielleicht hat ja hier jemand einen Tipp, bzw. den richtigen Code für mich!
Vielen Dank!

Was ist das für ein Sensor und wo ist der nicht funktionierende Code?

Am einfachsten für Anfänger anzusteuern sind die Ultraschallmodule, fertig bestückt mit Ultraschallsender und Ultraschallempfänger, sowie Trigger- und Echo-Logik, Bezeichnung z.B.: HC-SR04.

Hallo Jurs,
genau diesen habe ich im Einsatz! :wink:
Auf die Code-Varianten die ich alle schon getestet habe, hab ich momentan keinen Zugriff, aber ich glaube die Basis bekomme ich auch so aus dem Gedächtnis hin:

#define trigPin 12
#define echoPin 13
#include <Servo.h> 
long duration, cm;
Servo myservo;

void setup() 
{
Serial.begin(9600);
myservo.attach(9);
}
void loop()
{ 

pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(5);
digitalWrite(trigPin, LOW);


pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);

cm = duration / 29 / 2; 

Serial.print(cm);

if(cm < 30){

 myservo.write(0);
delay(15);

}
else{

 myservo.write(180);
delay(15);

}
delay(100);
}

So hätte ich mir das vorgestellt!
Aber hier macht das Ding so weit ich mich erinnern kann nicht wirklich was! :wink:
Tausch ich die "IF" "ELSE" Bedingungen mit einer Relais-Ansteuerung aus ...schaltet das Relais ohne Probleme!
Erweitere ich den "Servo-Code" in der Bedingung z.B. mit der Angabe der Schritte - so bewegt sich zwar was ..aber nicht so wie ich mir das vorstelle! :wink:

Hallo EPICENTER,

der Code macht genau, was du willst. Einzig unschön ist, dass das Servo bei 30 cm hin- und herflattert, hier solltest du eine Hysterese einbauen.
Funktioniert der Servo denn, wenn du ihn ansteuerst? Bau mal in die setup routine einen Servotest eine, zB:

...
myservo.write(0);
delay(100);
myservo.write(180);
delay(100);

Gruß
Reinhard

Hallo erni-berni,
ja, der Code sollte auch meiner Meinung nach funktionieren ...macht er aber nicht!
Wenn ich mich noch richtig an gestern Nacht erinnere ...funktioniert ...der einfache Code ...so wie Du diesen hier schreibst ..oder ich integriert habe eben nicht! Nehm ich dagegen so ein "Testprogramm" ala .....

#include <Servo.h>
// Erzeugen eines Servo Objekts zur Servo Steuerung
Servo myservo;

// Variable zum Speichern der Position
int pos = 0;

// Initialisierung der Pins
void setup(){
   myservo.attach(9);
}
// Hauptprogramm
void loop(){
   for(pos = 0; pos < 180; pos++){
     myservo.write(pos);
     delay(15);
   }
}

...fährt der Servo sauber in seine Position ...oder halt auch wieder zurück! Gibt ja da noch andere Code-Stückchen, mit denen man den Servo spazieren fahren lassen kann. Aber die funken nur ...wenn ich das so mit dem "for" schreibe. Versuche ich jedoch das in den Code zu integrieren ...zuckt der Servo nur wild herum.

Miss doch erst mal, was Dein Code für den Ultraschallsensor an Entfernungen zurückgibt. Vielleicht liegt da der Hund begragen. Also Servo und Co raus und die berechnete Entfernung ab in den seriellen Monitor.

EPICENTER:
Versuche ich jedoch das in den Code zu integrieren ...zuckt der Servo nur wild herum.

Poste genau den Code, mit dem der Servo wild zuckt und beschreibe dazu, was der Code tatsächlich machen soll!

Dass die Positionen 0 und 180 vom Servo vom Prinzip her sauber angefahren werden können, das hast Du geprüft?
Ansonsten müßtest Du den Servo auf andere Impulslängen für die 0° und 180° Position initialisieren!

Im übrigen brauchst Du, wie von Reinhard geschrieben, bei Deinem oben geposteten Code nur eine Hysterese: Wenn die Messwerte des Sensors nämlich schnell zwischen 29 und 30 hin- und herspringen, würde Dein Servo genau an der Grenze zwischen 29 und 30 ebenfalls hin und herspringen.

Das verhinderst Du mit einem Bereich, in dem der Servo die letzte Position beibehält:

if(cm < 30){
 myservo.write(0);
}
else if (cm>30){
 myservo.write(180);
}

Der Servo würde nun nur bei Werten unter 30, also bis einschließlich 29 auf die 0° Position gedreht werden und erst bei Werten über 30, also ab 31 auf die 180° Position. Bei exakt 30 cm behält der Servo die Position, die er vorher hatte.

D.h. springt der Messwert vom Sensor ständig zwischen 29 und 30, bleibt der Sensor auf 0°.
Und springt der Messwert ständig zwischen 30 und 31, bleibt der Sensor auf 180°.

Falls die Messwerte um mehr als eine Stelle springen können, muss die Hysterese am Umschaltpunkt noch größer gewählt werden. Z.B. wenn die Sensorwerte zwischen 3 verschiedenen cm-Werten hin- und herpendeln:

if(cm < 29){
 myservo.write(0);
}
else if (cm>31){
 myservo.write(180);
}

Dann würde der Servo sogar bei den Messwerten 29, 30 und 31 immer die zuletzt angefahrene Position beibehalten, auch wenn der Messwert etwas zittert.

..jetzt wird es langsam kompliziert! :wink:
Aber der Code für die Entfernungsmessung funktioniert! Vielleicht nicht zu 100 Prozent genau ...aber zumindest so ca. Wenn ich den Servo mit einem Relais vertausche, wird das Relais sauber geschalten und auch ca. bei dem Abstand, welchen ich im Code gesetzt habe.
Daher sollte der Sensor und die Messung richtig sein.

Irgendwie scheint es so als würde der Code zur direkten Ansteuerung nicht funktionieren.
Wobei das Relais mit dem anderen Code ja sauber arbeitet.

@jurs

Mit dem Zucken habe ich mich vielleicht etwas falsch ausgedrückt! Ich schalte ein und der Servo steht wie unter Strom! Es ist jetzt nicht so, dass der Servo in eine Stellung fährt und danach zuckt ...sondern er beginnt gleicht nach dem Einschalten leicht zu zittern. Egal ob ich bei 5 cm eine Abdeckung vornehme, bei genau 30 cm ...oder den Sensor einfach ins Weltall scannen lasse! :wink:

zum Code:

Wenn ich den einfachen Code (myservo.write(x)) mit diesem hier ...

  for(pos = 0; pos < 180; pos++){
     myservo.write(pos);
     delay(15);

ersetze - fährt der Servo irgendwie hin und her ...bzw. interessant daran ist ...es gibt nicht so wirklich einen 100 prozentigen gleichen Ablauf.

Servos haben gerne mal Probleme im stabilen Zustand, besonders die preiswerten zucken/zittern/rattern da mal vor sich hin. Fällt beim Hin- und Herfahren natürlich nicht auf, nur im statischen Zustand.

Vielleicht isses das?

EPICENTER:
Mit dem Zucken habe ich mich vielleicht etwas falsch ausgedrückt! Ich schalte ein und der Servo steht wie unter Strom! Es ist jetzt nicht so, dass der Servo in eine Stellung fährt und danach zuckt ...sondern er beginnt gleicht nach dem Einschalten leicht zu zittern. Egal ob ich bei 5 cm eine Abdeckung vornehme, bei genau 30 cm ...oder den Sensor einfach ins Weltall scannen lasse! :wink:

Schaltung?
Hat der Servo eine eigene Stromversorgung?

Wenn ja, dann müssen GND vom Arduino und GND von der Servostromversorgung miteinander verbunden sein zwecks Potentialausgleich!

Wenn nein: Nur für sehr kleine Servos darfst Du Strom am 5V Anschluss des Arduino-Boards abzapfen. Mittlere und große Servos brauchen mehr Strom als Du am 5V Pin des Boards entnehmen darfst, dann wird die Stromversorgung des Boards instabil.

@Klaus
Wenn es nur zu einer Bewegung käme. :wink:
Der Servo ist übrigens ...aus meinem Modellbau-Zubehör und ist an sich ein gutes und zuverlässiges Gerät. Dat Ding kostet mehr wie das Arduino Board und die Technik drum herum! :wink: Wenn ich diesen über die oben genannte Baugruppe ansteuere läuft der Servo wie auf Schienen.

@Jurs
Ganz ehrlich - daran hatte ich auch schon gedacht.
Was mich davon etwas abgebracht hat, war die Tatsache, dass der Servo arbeitet, wenn ich das Testscript verwende. Einzige Erklärung wäre nun vielleicht, dass der Anzugsstrom beim anderen Befehl zu hoch wird und das Board irgendwie zum Absturz bringt. Aber dann müsste meiner Meinung nach eine längere Pause entstehen, wenn das Board sich wieder startet.
Aber das könnte ich natürlich mal testen ...wenn ihr sagt, der Code sollte ok sein - dann teste ich das mal mit einer getrennten Spannungsversorgung.

EPICENTER:
...wenn ihr sagt, der Code sollte ok sein - dann teste ich das mal mit einer getrennten Spannungsversorgung.

Nein, der von Dir gepostete Code ist mehr eine Wirr-Steuerung als eine Schön-Steuerung:

// Hauptprogramm
void loop(){
   for(pos = 0; pos < 180; pos++){
     myservo.write(pos);
     delay(15);
   }
}

Der Code macht folgendes: Es soll 180 mal mit einem zeitlichen Abstand von 15 Millisekunden eine um 1° andere Winkelposition angefahren werden. Das ist noch der "schönere" Teil des Ablaufs. Zwar kann ein Servo nicht in 15 tausendstel Sekunden reagieren, wenn die Servo-Refresh-Impulse nur alle 20 Millisekunden eintreffen. Das führt eher zu einem Lauf, der von der internen Steuerung mehr so aussieht:
0ms = 0°
20ms = 1° (1x 15 ms vergangen)
40ms =2° (2x 15 ms vergangen)
60ms = 4° (4x15 ms vergangen)
80ms = 5° (515ms vergangen)
100ms = 6° (6
15ms vergangen)
120ms = 8° (8*15ms vergabgen)
Das ergibt einen fast normalen Servolauf, von 0 auf 180 Grad drehend mit einer Geschwindigkeit deutlich unterhalb der Servo-Höchstgeschwindigkeit.

Wenn diese For-Schleife einmal abgearbeitet ist, wird allerdings der Servo innerhalb von 20ms auf einen Soll-Winkel von 0° umgesteuert, d.h. der Servo fängt an, mit Höchstgeschwindigkeit die andere Endposition zu erreichen.

Der Servo steuert also immer mit niedriger Geschwindigkeit von 0 auf 180° und danach extrem schnell in die Gegenrichtung. Die 0° Position wird allerdings nie erreicht, weil der Servo wohl ca. 0,2 Sekunden benötigen würde, um die Position zu erreichen, tatsächlich wird er zu dem Zeitpunkt aber schon wieder auf höhere Drehwinkel gesteuert.

Mit dem Code dreht sich also der Servo immer langsam (gute 1,5s lang( in die eine Richtung und schnell (Höchstgeschwindigkeit, ca. 0,2s lang) in die andere Richtung, und das wiederholt sich ständig.

Wenn Du das meinst: Das ist kein Fehler, sondern nur das, was Du programmiert hast.

@Jurs
Naja, das erklärt das wilde hin und her fahren, welches ich als unkontrolliert beschrieben hatte.

Der ursprüngliche Code ist ja im Beitrag 3 zu sehen - doch da macht das System ja gar nichts, wenn ich dem Servo sage ...fahr einfach zu der gewünschten Gradzahl.

Hallo,

ich hatte exakt das selbe Problem, da ich ebenfalls einen Servo (bzw. 2 Servos) über ein HC-SR04 ansteuern wollte. Das Problem ist die Spannungsversorgung. Ich tippe auch mal das dies bei dir ebenfalls der Fall ist. Bei mir war es so das sich Servo sowie den Sensor in einem Stromkreis hatte und den Arduino in einem anderen, denn den Servo und das HC-SR04 über den Arduino zu versorgen geht schonmal nicht. Die massen waren miteinander verbunden sodass alles wunderbar funktionierte. Jedenfalls einzeln, zusammen fuhr mein Servo unkontrolliert hin und her. Jedoch sollte meiner nicht nur 180° sondern eine "Kanone" in der höhe steuern um die Flugbahn in Abhängigkeit zur Entfernung zu regulieren. Das Problem ist folgendes, wie ich bei mir herausfand. Das HC-SR04 ist für Entfernungen bis 4m ausgelegt, jedoch braucht es dafür ordentlich Strom und konstante Spannung. Zieht der Servo jetzt an (setzt sich in Bewegung oder bewegt sich) bricht die Spannung am Sensor zusammen und die gemessene Entfernung stimmt nicht. Bei mir ging es plötzlich runter auf 20cm, obwohl das ziel 1,5m entfernt war. Der Ardunio interpretiert diese Entfernung und stellt den Servo anders, dies führt wiederum dazu das die Spannung am Sensor wieder zusammenbrach......... den Rest kannst du dir ausmalen.
ich konnte das Problem auf sehr einfache Weiße lösen, indem ich dem Servo so wie dem HC-SR04 jeweils einen 100µF Elko Parallel zur Spannungsversorgung spendierte. Seitdem läuft alles wie geschmiert. Ich kann nur tippen, aber wenn ich tippen müsste würde ich bei dir auf das selbe Problem tippen. Versuch einfach mal wie es ausschaut wenn du deinem Servo und dem Sensor die Abblockkondensatoren spendierst.

MFG

His