ESP8266 Servo mit Taster auf / zu fahren Saugroboter

Ich wüsste nichts von einem yield() bei der Servo-Lib. Auf dem Wemos dürfte die Servo-Lib schlicht die PWM-Funktionen des Core nutzen. Der hat ja nur einen Timer, mit dem die Core-Funktionen ( tone/pwm) arbeiten.

Dann muss ich das anders bauen... :cry:

Dann sind die MobaTools ja vielleicht doch einfacher :wink:

Ich kenn ja deine Planungen nicht, aber für die langsame Bewegung brauchst Du doch eh eine Zeitverzögerung von Schritt zu Schritt. Und wenn Du am Ende noch ein paar Schritte ohne Winkeländerung machst, ist das Servo auch auf jeden Fall am Ziel.

P.S. Vielleicht meldet sich @ron85 ja auch mal, wie jetzt bei ihm der Stand der DInge ist ...

Das hatte ich gerade vor... :wink:
Na mal sehen, ob und was ich in meiner Logik unterbringe. :slight_smile:

Da musst dann aber aufpassen, dass der Servo im ausgeschalteten Zustand nicht versucht, sich über die Signal-Leitung zu ernähren.

Ich hab auch keine Ahnung, was ich da eigentlich mache... :slight_smile:
... wüsste aber gerne ob meine Überlegungen richtig sind.
(Achtung die Zeiten sind überdimensioniert)

#include <Servo.h>

Servo myservo;
const byte servoPin = 5;
const byte anschlag = 4;
const byte endPos[] = {14, 90};  // Ziel wenn Taster zu / Taster auf
bool lastPos;

void setup()
{
  pinMode(anschlag, INPUT_PULLUP);
  lastPos = digitalRead(anschlag);       // Feststellen wo der Robot ist
  myservo.write(endPos[lastPos]);        // setzt die Ausgangsposition
  myservo.attach(servoPin);              // Servo machen lassen...
  delay(1000);                           // kurze Wartezeit
  myservo.detach();                      // Ausgangsstellung erreicht
}

void loop()
{
  aufZu(digitalRead(anschlag));
}

void aufZu(bool richtung)
{
  const unsigned long laufZeit = 10000;    // Zeit die der Servo aktiv bleibt
  const unsigned long nextStep = 50;       // Wartezeit für nächsten Step
  static unsigned long lastMillis = 0;     // Zeitmerker
  static unsigned long startZeit = millis();
  static bool lastRichtung = !richtung;
  static byte startPos = endPos[lastRichtung];
  if (lastRichtung != richtung)            // Anfang Init
  {
    startZeit = millis();                  // Jetzt
    startPos = endPos[lastRichtung];       // wo war ich
    myservo.write(startPos);               // setzt die Ausgangsposition
    myservo.attach(servoPin);              // Servo machen lassen...
    lastRichtung = richtung;               // Ende Init
  }
  if (millis() - startZeit < laufZeit)     // aktive Zeit
  {
    if (millis() - lastMillis > nextStep)  // Zeit ist um
    {
      lastMillis = millis();               // Zeit merken
      if (startPos > endPos[richtung])
      {
        myservo.write(--startPos);         // setzt neue Position
      }
      else if (startPos < endPos[richtung])
      {
        myservo.write(++startPos);         // setzt neue Position
      }
    }
  }
  else                                     // Laufzeit ist um
  {
    if (startPos == endPos[richtung])      // Position ist erreicht?
    { myservo.detach();}
    else
    { startZeit = millis(); }               // Wenn nicht, noch mehr Zeit
  }
}

Ich hoffe das genügend kommentiert zu haben.

Das hier:

  lastPos = digitalRead(anschlag);       // Feststellen wo der Robot ist
  myservo.write(endPos[lastPos]);        // setzt die Ausgangsposition

Zusammen mit dem:

  static bool lastRichtung = !richtung;

funktioniert nicht. Beim Starten meint er so immer er steht falsch. Im setup wird auf die richtige Startposition gestellt, und in aufZu fährt er dann mit maximal Speed in die andere Position und dann wieder langsam in die Startposition.
lastRichtung muss global sein, und dann im setup schon richtig gestellt werden:

...
byte lastRichtung;
void setup()
{ Serial.begin( 74880 );
  pinMode(anschlag, INPUT_PULLUP);
  lastRichtung = digitalRead(anschlag);       // Feststellen wo der Robot ist
  myservo.write(endPos[lastRichtung]);        // setzt die Ausgangsposition
...

Ein bool als Index in ein Array ... :roll_eyes:

Aah.. Das war der Bruch von gestern...
Es muss oben lastPos in lastRichtung geändert werden und die lokale Variable raus.
oben:

bool lastRichtung;

void setup()
{
  pinMode(anschlag, INPUT_PULLUP);
  lastRichtung = digitalRead(anschlag);       // Feststellen wo der Robot ist
  myservo.write(endPos[lastRichtung]);        // setzt die Ausgangsposition
  myservo.attach(servoPin);              // Servo machen lassen...
  delay(1000);                           // kurze Wartezeit
  myservo.detach();                      // Ausgangsstellung erreicht
}

und in aufZu fange ich an mit:

void aufZu(bool richtung)
{
  const unsigned long laufZeit = 10000;    // Zeit die der Servo aktiv bleibt
  const unsigned long nextStep = 50;       // Wartezeit für nächsten Step
  static unsigned long lastMillis = 0;     // Zeitmerker
  static unsigned long startZeit = millis();
  static byte startPos = endPos[lastRichtung];
  if (lastRichtung != richtung)            // Anfang Init
  {
    startZeit = millis();                  // Jetzt
    startPos = endPos[lastRichtung];       // wo war ich
    myservo.write(startPos);               // setzt die Ausgangsposition
    myservo.attach(servoPin);              // Servo machen lassen...
    lastRichtung = richtung;               // Ende Init
  }

Danke fürs drauf schaun.

Och naja...

Hallo bin heute leider nicht dazu gekommen weiter drüber zu schauen.

Mal zu meinem Aufbau… habe mir eine Klappe in die Sockelblende vom Küchenschrank gebaut, an dieser Blende ist der Servo mit einem Gestänge befestigt um seinen Dienst zu verrichten.

Wenn nun der Saugroboter startet, dann fährt er ja zurück, dabei wird der Taster geöffnet. Dieser Impuls soll nun die Klappe öffnen. Da der Servo in dieser Stellung brummt dachte ich mir das man ihn abschalten kann, also die Datenleitung abschalten. Wenn dann der Saugroboter fertig ist dann fährt er wieder zu der Ladestation, wo wieder der Taster betätigt wird und so die Klappe wieder geschlossen werden soll (auch hier brummt der Servo). So meine Vorstellung. Für mich reicht es wenn die sich öffnet und wieder schließt. Wenn sie sich langsamer schließt das wäre das nur ein Zusatz für mich.

auf der Suche um mein Vorhaben um zu setzen bin ich dann auf irgendwann darauf gestoßen.

if (digitalRead(button) == HIGH) {
        if ( pos > POS_A)  {
          // in steps of  1°
          myservo.write(--pos);      // tell servo to go stepwise down to POS_A
          delay(20);

wo ich denke das das „delay(20)“ die Geschwindigkeit regelt, was ich gut fand. Trotzdem, muss das nicht langsamer zu gehen. Es reicht wenn es normal öffnet und schließt

Gestern bin ich dann hier hängen geblieben.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo 
int pos ;    // variable to store the current servo position


const byte button = D1;  // The button will be on Pin 
const byte POS_A = 14;   // Ziel wenn Taster offen
const byte POS_B = 90; // Ziel wenn Taster zu

void setup()
{
  myservo.attach(D4);  // attaches the servo on pin 5 to the servo
  pinMode(button, INPUT_PULLUP);  // button connects to GND ( LOW when pressed )
  myServo.attach( int D4 );
}

void loop()
{
 
   if (digitalRead(button) == HIGH) {
        if ( pos > POS_A)  {
          // in steps of  1°
          myservo.write(--pos);      // tell servo to go stepwise down to POS_A
          myServo.attach( int D4, bool autoOff);
          delay(20);
      }
  }

  if (digitalRead(button) == LOW) {
       if ( pos < POS_B)  {
          // in steps of  1°
          myservo.write(++pos);      // tell servo to go stepwise up to POS_B
          myServo.attach( int D4, bool autoOff);
          delay(5); // langsame Bewegung : 20 ° / Sekunde
      }
  }
  
}

und bekomme diese Fehlermeldung

Arduino: 1.8.13 (Windows 10), Board: "LOLIN(WEMOS) D1 R2 & mini, 80 MHz, Flash, Legacy (new can return nullptr), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600"

C:\Users\Ronny\Desktop\robi_beta_v0.1\robi_beta_v0.1.ino: In function 'void setup()':

robi_beta_v0.1:15:3: error: 'myServo' was not declared in this scope

   myServo.attach( int D4 );

   ^

robi_beta_v0.1:15:19: error: expected primary-expression before 'int'

   myServo.attach( int D4 );

                   ^

C:\Users\Ronny\Desktop\robi_beta_v0.1\robi_beta_v0.1.ino: In function 'void loop()':

robi_beta_v0.1:25:11: error: 'myServo' was not declared in this scope

           myServo.attach( int D4, bool autoOff);

           ^

robi_beta_v0.1:25:27: error: expected primary-expression before 'int'

           myServo.attach( int D4, bool autoOff);

                           ^

In file included from C:\Users\Ronny\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\cores\esp8266/Arduino.h:29:0,

                 from sketch\robi_beta_v0.1.ino.cpp:1:

robi_beta_v0.1:25:35: error: expected primary-expression before 'bool'

           myServo.attach( int D4, bool autoOff);

                                   ^

robi_beta_v0.1:34:11: error: 'myServo' was not declared in this scope

           myServo.attach( int D4, bool autoOff);

           ^

robi_beta_v0.1:34:27: error: expected primary-expression before 'int'

           myServo.attach( int D4, bool autoOff);

                           ^

In file included from C:\Users\Ronny\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\cores\esp8266/Arduino.h:29:0,

                 from sketch\robi_beta_v0.1.ino.cpp:1:

robi_beta_v0.1:34:35: error: expected primary-expression before 'bool'

           myServo.attach( int D4, bool autoOff);

                                   ^

Mehrere Bibliotheken wurden für "Servo.h" gefunden

 Benutzt: C:\Users\Ronny\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\libraries\Servo

 Nicht benutzt: C:\Program Files (x86)\Arduino\libraries\Servo

 Nicht benutzt: C:\Users\Ronny\Documents\Arduino\libraries\Servo

exit status 1

'myServo' was not declared in this scope

Ich musste nun feststellen das mir das doch viel schwerer fällt als ich dachte, muss mich damit nun noch viel mehr beschäftigen, da ich feststellen musste das ich auch Probleme habe noch dinge ein zu fügen. Vielleicht gibt es info's wo ich einen guten einstieg bekommen kann, um das besser zu verstehen.

ach und mein Problem war ja auch noch, das beim versorgen mit Strom die Klappe immer auf ging und ich immer erst den taster betätigen musste um die richtige Stellung zu erreicht. Dabei war es egal ob der taster geöffnet oder geschlossen war, wenn ich alles mit Strom verbunden habe.

Du würdest überrascht sein :wink:

Es ist kein Impuls. Es ist ein Zustand. Bitte nicht durcheinanderwerfen - das macht rein logisches Denken kaputt ...

Ok. dann den Code von mir mal als Gesamt.
Vorher zu Deiner Fehlermeldung:

 const byte button = D1;  // The button will be on Pin

Da wird eine Pin-Nummer erwartet.
ebenso hier:

myservo.attach(D4);  // attaches the servo on pin 5 to the servo

Ich würd mal meinen, das Du ein falsches Board ausgewählt hast. Siehe hier: Pin numbering for WeMos D1 Mini (ESP8266) – The Chewett blog

Mein Code für einen Arduino wäre:

#include <Servo.h>

Servo myservo;
const byte servoPin = 5;
const byte anschlag = 4;
const byte endPos[] = {14, 90};  // Ziel wenn Taster zu / Taster auf
bool lastRichtung;

void setup()
{
  pinMode(anschlag, INPUT_PULLUP);
  lastRichtung = digitalRead(anschlag);  // Feststellen wo der Robot ist
  myservo.write(endPos[lastRichtung]);   // setzt die Ausgangsposition
  myservo.attach(servoPin);              // Servo machen lassen...
  delay(1000);                           // kurze Wartezeit
  myservo.detach();                      // Ausgangsstellung erreicht
}

void loop()
{
  aufZu(digitalRead(anschlag));
}

void aufZu(bool richtung)
{
  const unsigned long laufZeit = 10000;    // Zeit die der Servo aktiv bleibt
  const unsigned long nextStep = 50;       // Wartezeit für nächsten Step
  static unsigned long lastMillis = 0;     // Zeitmerker
  static unsigned long startZeit = millis();
  static byte startPos = endPos[lastRichtung];
  if (lastRichtung != richtung)            // Anfang Init
  {
    startZeit = millis();                  // Jetzt
    startPos = endPos[lastRichtung];       // wo war ich
    myservo.write(startPos);               // setzt die Ausgangsposition
    myservo.attach(servoPin);              // Servo machen lassen...
    lastRichtung = richtung;               // Ende Init
  }
  if (millis() - startZeit < laufZeit)     // aktive Zeit
  {
    if (millis() - lastMillis > nextStep)  // Zeit ist um
    {
      lastMillis = millis();               // Zeit merken
      if (startPos > endPos[richtung])
      {
        myservo.write(--startPos);         // setzt neue Position
      }
      else if (startPos < endPos[richtung])
      {
        myservo.write(++startPos);         // setzt neue Position
      }
    }
  }
  else                                     // Laufzeit ist um
  {
    if (startPos == endPos[richtung])      // Position ist erreicht?
    { myservo.detach();}
    else
    { startZeit = millis(); }              // Wenn nicht, noch mehr Zeit
  }
}

Die Pins für Servo und den Taster musst Du für Dich anpassen.

Okay danke für den Hinweis, ich muss das mehr verinnerlichen :grinning:
Nur so kann ich dazu lernen

Danke für den Code, habe ich natürlich gleich probiert. Leider ist es nun so...
Wenn der Taster geschlossen wird, bewegt sich der Servo in seine neue Position, dann aber gleich wieder zurück in langsamer Geschwindigkeit.

Habe ich vielleicht einen Problem im Anschluss?
Nutze einen Wemos D1 mini, der Servo ist an D4 und an Plus 5V/ GND
Der Taster ist an D2 / GND

Ich muss bestimmt noch einen Widerstand zu GND-->D2 machen. Diesen habe ich gerade nicht verbaut, da ich gerade keinen habe. Habe es auf gerade auf einer Zeichnung gesehen.

Ja alles gut - ich lerne ja auch.

GRR...

Das war so nicht vorgesehen ;(
Nu hab ich a keinen ESP/Wemos und b auch eine andere Baustelle...
Ich bau das ggfls. später mal mit dem Seriellen Monitor.
Aber da sehe ich gerade wieder hell ... - das übernimmt jemand für mich :wink:

Hast Du mal die MobaTools Variante in #11 versucht? Einfacher geht es eigentlich nicht mehr.

Wozu? Du benutzt den internen Pullup, und die Verbindung nach Gnd macht doch der Taster - oder wie hast Du das angeschlossen?

P.S. Du solltest dich auf eine Pinbezeichnung einigen. Entweder die Dx, oder die GPIO-Nummern. Sonst kommt man immer wieder durcheinander.

Das wäre mein Anschluss, nicht schön, denke man sieht wie ich es angeschlossen habe.

Muss jetzt gestehen das es mit den MobaTools funktioniert :grinning:
Habe noch die "myservo.setSpeed ()" erhöht und nun läuft es wie ich mir das gewünscht habe.

Habt ihr noch info's und Tipps wo ich noch mehr lernen kann.

Danke für eure Hilfe

Ja
Das Servo aus einer externen Spannungsquelle die mindestens 2A liefern kann versorgen.
Wenn das Servo unter Last ist dann zieht das auch mal 1,5A und dann macht ein Standard-USB-Anschluss an einem Computer schlapp. Der kann nur 0,5A liefern für Wemos und Servo zusammen.

Das ist ein sehr ausführlicher Kurs der in die Arduino-Programmierung einführt
https://www.hobbyelektroniker.ch/roboter/arduinoprogrammierung/

vgs

Was ist da zu gestehen? :joy: Ist doch super, wenn's jetzt gunktioniert, Freut mich :sunglasses:
Ein bisschen wundert mich dein Anschlußbild, weil das passt eigentlich weder zu den Pinnummern in deinem Sketch, noch zu deiner verbalen Beschreibung oben.

Ja ich bin immer am Probieren und um Stecken oder eben am Pinnummern ändern :see_no_evil:
Musste schon lernen das das nicht gut ist. Habe da auch schon einen Wemos D1 kurzgeschlossen.

Nochmals Danke an alle die mir geholfen haben :grinning: