ESP8266 Servo Bewegunssequenz via html button

Hallo zusammen,

Ich habe diesen Sketch hier mit identischen Teilen nachgebaut (Code siehe unten): Wemos D1 Mini Web Server based Servo Motor Control. Abweichung: Servo und ESP8266 werden parallel von einem 5V, 1,5A DC Netzteil versorgt (GND von Servostromkreis und ESP8266 Stromkreis verbunden).

Nach Neuzuweisung des Servo Pins (siehe kommentiert im Code) klappt das auch soweit einwandfrei und ich kann die Servoposition über den Schieberegler auf der html Seite zwischen 0-180 kontrollieren. Allerdings habe ich einige Fragen, die ich nicht so ganz verstehe:

  • Der Servo fährt nicht den gesamten 180° Winkel ab – warum? Zwischen 0-180 auf dem Schiebregler liegen in Wahrheit nur ca. 90° Winkel.
  • Warum kann ich die html page zur Kontrolle der Servoposition von meinem Handy (via WIFi im gleichen Netzwerk verbunden) aufrufen, nicht aber von meinem Rechner (via LAN verbunden). Am Rechner kommt immer ein Fehler: Verbindung unterbrochen.
  • Warum fährt der Servo beim Resetten des boards/sketch unabhängig von seiner aktuellen Position immer zuerst auf 0 und dann auf 90 (das sind Schieberegler-Zahlen, nicht der tatsächliche Winkel; in Winkelangabe wären es ca. 45°)? Ich kann diese Befehle im code nicht finden.

Der oben nachgebaute sketch soll nur als Ausgangsbasis dienen. Eigentlich möchte ich statt des Schiebreglers einen digitalen Button auf meiner html Seite haben. Durch klicken auf diesen Button soll eine Bewegungssequenz am Servo initiiert werden: Er soll so schnell wie möglich eine bestimmte Position anfahren und danach so schnell wie möglich wieder auf seinen Ausgangspunkt zurückfahren. Parallel dazu soll ein Text durch Klicken auf den digitalen button alternierend wechseln zwischen: An-Aus-An-Aus usw.

  • Weiss jemand wie sich so etwas realisieren lässt?
  • Welchen Teil meines Beispielsketches muss ich ändern? Der sketch funktioniert super und ich würde gerne so viel wie möglich wiederverwenden.
  • Hat jemand vielleicht ein Codebeispiel oder eine Anleitung wie so ein digitaler Button hinter dem sich eine fest vorprogrammierte Servobewegungsfrequenz verbirgt, aussehen könnte?

Vielen Dank schon einmal!


#include <ESP8266WiFi.h>
#include <Servo.h>

Servo ObjServo;
static const int ServoGPIO = 2; // meine einzige Modifikation; Im Original steht hier "D4"

const char* ssid = "Your WiFi SSID";
const char* password = "Your WiFi Password";

WiFiServer server(80);
String header;
String valueString = String(0);
int positon1 = 0;
int positon2 = 0;

void setup()
{
  Serial.begin(115200);
  ObjServo.attach(ServoGPIO);
  Serial.print("Making connection to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop() {
  WiFiClient client = server.available();
  if (client)
  {

    String header = client.readStringUntil('\r');
    client.println("HTTP/1.1 200 OK");
    client.println("Content-type:text/html");
    client.println("Connection: close");
    client.println();

    client.println("<!DOCTYPE html><html>");
    client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
    client.println("<title>Servo Angle Controller</title>");
    client.println("<link rel=\"icon\" href=\"data:,\">");
    client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");
    client.println(".headertext{ font-weight:bold; font-family:Arial ; text-align: center; color: brown ;}");
    client.println(".slider { width: 500px; }</style>");
    client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");

    client.println("</head><body><h1><u><div class = \"headertext\"> Web Server based Servo Angle Controller</u></h1>");
    client.println("<p><h3>Angle</h3><span id=\"servoPos\"></span></p>");
    client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\"" + valueString + "\"/>");

    client.println("<script>var slider = document.getElementById(\"servoSlider\");");
    client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
    client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
    client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");
    client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}</script>");
    client.println("</body></html>");

    if (header.indexOf("GET /?value=") >= 0)
    {
      positon1 = header.indexOf('=');
      positon2 = header.indexOf('&');
      valueString = header.substring(positon1 + 1, positon2);

      ObjServo.write(valueString.toInt());
      Serial.println(valueString);
    }

    header = "";
    client.stop();
    Serial.println("");
  }
}

Was hast Du für einen Servo?
Link? Typenschild?

Wenn Du die unnötigen Leerzeilen aus Deinem Code entfernen würdest, könnte man versuchen, ihn zu lesen. Auch eine ordentliche Einrückung (Strg+T in der IDE hilft Dir dabei) erhöht die Lesbarkeit unheimlich.

Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Was hast Du für einen Servo?
Link? Typenschild?

einen Servo Motor SG-90. Also auch dieses Teil ist identisch zum Beispiel. Mein board ist ein ESP8266MOD 12-F.

Wenn Du die unnötigen Leerzeilen aus Deinem Code entfernen würdest, könnte man versuchen, ihn zu lesen. Auch eine ordentliche Einrückung (Strg+T in der IDE hilft Dir dabei) erhöht die Lesbarkeit unheimlich.

Erledigt! Ich hoffe es ist nun besser lesbar.

GRR.
Also nehmen wir mal an, es wäre, was Du hast...
Dann heisst es nicht 0...180
sondern -90...0....90
Du weisst, was jetzt zu tun ist?

Hm naja, ichbin mir nicht sicher - diese Zeile hier wie folgt ändern ist es jedenfalls nicht:

Alt:

 client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\"" + valueString + "\"/>");

Neu:

 client.println("<input type=\"range\" min=\"-90\" max=\"90\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\"" + valueString + "\"/>");

Vielleicht hat es hiermit etwas zu tun?

WiFiServer server(80);
String header;
String valueString = String(0);
int positon1 = 0;
int positon2 = 0;

Ich auch nicht.
Aber hier:

muss wohl vermutlich -90 bis 90 ankommen.
Das ginge jetzt zum Beispiel mit:

      ObjServo.write(valueString.toInt()-90);

wenn das valueString 0-180 ist...
Hinweis: Nur aus der Logik heraus und einen Versuch wert - ich habe keinen ESP... :wink:

:smiley: Auf jeden Fall immer einen Versuch wert!

In diesem Fall leider nicht erfolgreich: Der tatsächliche Bewegungsradius beim sliden zwischen 0 und 180 hat sich verringert.

Mich würde ja mal interessieren, wann die erste Bewegung einsetzt und die letzte Bewegung erfolgt.

Nach dem, was ich jetzt habe, bewegt sich der Servo jetzt nur noch 45°....
Richtig?

Nach dem, was ich jetzt habe, bewegt sich der Servo jetzt nur noch 45°....
Richtig?

siehe Korrektur unten

Mich würde ja mal interessieren, wann die erste Bewegung einsetzt und die letzte Bewegung erfolgt.

Die Bewegung der Servos erfolgt linear und komplett zwischen slider=0 und slider=180.

Übrigens:
Beim Hochladen des sketches auf das Board fährt der Servo komplette 360° Bewegungen.
Nach board reset im setup des sketches fährt der servo unabhängig von aktueller position immer auf 45° und direkt danach auf Grundposition. :thinking:

Korrektur: Sorry ich habe das falsch beobachtet: Dein Änderungsvorschlag ändert nichts an der Servobewegung. In beiden Varianten des Codes fährt der Servo, ausgehend von der Grundposition jeweils 45° in (slider=0) bzw gegen (slider=180) den Uhrzeigersinn.

Ich kann mich dran erinnern, das wir das schon mal hatten und uns dämlich gesucht haben...
Bau Dir einen MinimalSketch, der dir ohne zutun den Servo bewegt und auf dem SerMon ausgibt, was für eine Position er hat.
Schön mit einem delay...

Hallo nochmal

ich habe es jetzt soweit hinbekommen, dass der Servo eine Bewegungssequenz, wie oben beschrieben erforderlich, ausführt, sobald ich den digitalen Button auf der html page klicke. Den Code habe ich mir bei unten angegebener Quelle gemopst und die für meine Verwendung nicht relevanten Parts gelöscht bzw. modifiziert. Ausserdem habe ich eine Statusanzeige hinzugefügt, (sobald die Sequenz ausgelöst wurde wechselt der Status auf "AN"). Wie das ganze auf der Webpage aussieht zeige ich unten per screenshot - damit bin ich relativ zufrieden.

Nach wie vor habe ich aber ein paar Probleme für die ich mir hier im Forum eine Lösung erhoffe:

  • Nach board reset oder Trennung/Wiederverbindung der Stromversorgung macht der Servo eine kurze Bewegung. Warum tut er das? Das geht auf keinen Fall; ich will dass der keinen Mucks macht bis ich den button auf der webpage drücke.

  • Nach wie vor entsprechen die angefahrenen Winkel nicht der Realität. Unten in der Sequenz lasse ich den Servo von 0 auf 150 Grad fahren - in der Realität macht er lediglich ca. die Hälfte. Das ist für meine konkrete Anwendung nicht schlimm aber ich hätte es gerne verstanden warum und sauber gelöst. Liegt das irgendwie an der Servo library (Ich nutze einen SG-90 Microservo)? An ein Uno angehängt fährt er mit dem knob sketch brav die vollen 180 Grad (von -90 auf +90) ab.

  • Wenn ich die html page in meinem Firefoxbrowser i) initial aufrufe oder ii) refreshe, macht der Servo automatisch die Bewegungssequenz. Daraus folgt, dass ich den Zustand "AUS" nie im Browser sehen kann. Auch das ist für mich leider fatal denn es gilt: Ich will dass der keinen Mucks macht bis ich den button auf der webpage drücke :laughing:.

  • Die Statusanzeige ("Zustand") würde ich gerne noch etwas aufbereiten:

    1. Die Statusanzeige soll bei jedem drücken des buttons auf der html page zwischen "An" und "Aus" wechseln.
    2. Wenn der Status "An" für >3min angezeigt wird, soll er automatisch auf "Aus" wechseln.

    Wie kann ich das machen? Eignet sich dazu millis()? Hat jemand ein pragmatisches, für Dilettanten verständliches Beispiel?

Vielen Dank!

Unbenannt


/*****************************************************
   Date: 13 july 2018
   Written by: Usman Ali Butt
   Property off: www.microcontroller-project.com
 * ***************************************************/

#include <ESP8266WiFi.h>
#include <Servo.h>
Servo servo;

const char* ssid     = "xxx";
const char* password = "xxx";

WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);
  servo.attach(2); //Gpio-2 of nodemcu with pwm pin of servo motor

  servo.write(0); //Moving servo to 0 degree 

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address on serial monitor
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");    //URL IP to be typed in mobile/desktop browser
  Serial.print(WiFi.localIP());
  Serial.println("/");

}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while (!client.available()) {
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  String zustand = "AUS"; // initialer Zustand des Systems

  if (request.indexOf("Sequenz") != -1)  {
    servo.write(0); //Moving servo to 0 degree
    delay(1000);
    servo.write(150); //Moving servo to 150 degree --> Kontaktpunkt
    delay(500);
    servo.write(0); //Moving servo to 0 degree
    zustand = "AN"; // temporärer Zustand des Systems; soll nach 3min automatisch auf "AUS" wechseln
  }

  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<h1 align=center>Servo motor control over WiFi</h1><br><br>");
  client.println("<br><br>");
  client.print("Zustand  = ");
  client.print(zustand);
  client.println("<br><br>");
  client.println("<a href=\"Sequenz\"\"><button>Bew. Sequenz</button></a><br/>");

  client.println("</html>");
  delay(1);
  Serial.println("Client disonnected");
  Serial.println("");

}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.