Servo ansteuern (Arduino, ESP8266, ESP32)

Servo ansteuern (Arduino, ESP8266, ESP32)

In diesem Beitrag möchte ich euch zeigen wir Ihr einen Servo mit einem Arduino, ESP8266 (Wemos D1 mini lite) und ESP32 (Wemos Lolin32) betreiben könnt. Das ansteuern des Servos ist beim Arduino und ESP8266 das selbe Prinzip nur beim ESP32 gibt es eine Neuerung.
Für Arduino und ESP8266 wird die Funktion analogWrite() verwendet, die kennen wir alle, doch diese Funktion gibt es mit dem ESP32 nicht mehr. Wen man diese Funktion nutzen möchte muss man nun mit ledcWrite(channel, duty) arbeiten, wie das genau geht zeige ich euch hier.

Was sind Servomotoren?

Servomotoren werden oft im Modellbau eingesetzt, man sagt auch Getriebemotoren dazu. An der Drehachse des Servos ist ein Potentiometer befestigt, mit dem wird die aktuelle Position bestimmt. Servos sind recht Präzise und lassen sich sehr einfach Ansteuern, daher auch gut geeignet in der Robotertechnik. Sie haben im Normalfall einen Bewegungsbereich von 0°-180°, angesteuert werden Sie mit einem Analogen Signal oder auch PWM Signal.

Ich habe mal das Signal von der Ansteuerung mit einem Osziloskop angesehen.
Arduino und ESP8266, standart bei 50 Hz.

0 Grad, Arduino 90 Grad, Arduino 180 Grad, Arduino

ESP32
Mit der neuen Funktion (ledcWrite) kann die Frequenz selber bestimmt werden, mehr dazu weiter unten im Beitrag.

esp32-0 esp32-90 esp32-180

Servo mit Arduino Uno ansteuern.

Servo Arduino

Funktion

Mit #include Servo.h wird die Bibliothek in den Sketch eingebunden. Servo servoblau; definiert den Namen des Servos, servoblau.attach(3); hier gibt die 3 den Pin an mit dem der Servo geschalten wird und zu guter letzt servoblau.write(90); damit übergibt man den Winkel in Grad an den Servo, in diesem Fall 90 Grad.

Programmcode

Wo Ihr die Bibliothek U8g2lib bekommt könnt Ihr hier nachlesen.

#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);

#include <Servo.h>
Servo servoblau;

void setup() {
  servoblau.attach(3);
  u8g2.begin();
  u8g2.enableUTF8Print();
}

void loop() {
  u8g2.setFont(u8g2_font_courB18_tf);
  u8g2.setFontDirection(0);

  servoblau.write(0);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "0 Grad");
  } while ( u8g2.nextPage() );
  delay(3000);
  servoblau.write(90);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "90 Grad");
  } while ( u8g2.nextPage() );
  delay(3000);
  servoblau.write(180);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "180 Grad");
  } while ( u8g2.nextPage() );
  delay(3000);
  servoblau.write(120);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "120 Grad");
  } while ( u8g2.nextPage() );
  delay(3000);
  servoblau.write(45);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "45 Grad");
  } while ( u8g2.nextPage() );
  delay(3000);
}

Servo ansteuern mit ESP8266 als Web Server (Wemos D1 mini Lite)

Servo ESP8266

Funktion

Die Funktion ist die selbe wie beim Arduino.

Programmcode

Wo Ihr die Bibliothek U8g2lib bekommt könnt Ihr hier nachlesen.
Für die Biliothek ESP8266 habe ich auch schon einen Beitrag gemacht.

#include <Servo.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);

const char* ssid     = "WLAN NAME";
const char* password = "PASSWORT";
Servo servoblau;
ESP8266WebServer server ( 80 );

void setup()
{
  Serial.begin(9600);
  servoblau.attach(12);
  u8g2.begin();
  u8g2.enableUTF8Print();
  connectWifi();
  beginServer();
  servoblau.write(0);
  u8g2.setFont(u8g2_font_courB18_tf);
  u8g2.setFontDirection(0);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "0 Grad");
  } while ( u8g2.nextPage() );
}

void loop() {
  server.handleClient();
  delay(1000);
}

void connectWifi()
{
  WiFi.enableSTA(true);
  delay(2000);
  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());
}

void beginServer()
{
  server.on ( "/", handleRoot );
  server.begin();
  Serial.println ( "HTTP server started" );
}

void handleRoot() {
  if ( server.hasArg("SERVO") ) {
    handleSubmit();
  } else {
    server.send ( 200, "text/html", getPage() );
  }
}

void handleSubmit() {

  String SERVOValue;
  SERVOValue = server.arg("SERVO");
  Serial.println("Set GPIO ");
  Serial.print(SERVOValue);

  if ( SERVOValue == "0" ) {
    servoblau.write(0);
    server.send ( 200, "text/html", getPage() );
    u8g2.setFont(u8g2_font_courB18_tf);
    u8g2.setFontDirection(0);
    u8g2.firstPage();
    do {
      u8g2.drawStr(0, 20, "0 Grad");
    } while ( u8g2.nextPage() );
  }
  else if ( SERVOValue == "90" )
  {
    servoblau.write(90);
    server.send ( 200, "text/html", getPage() );
    u8g2.setFont(u8g2_font_courB18_tf);
    u8g2.setFontDirection(0);
    u8g2.firstPage();
    do {
      u8g2.drawStr(0, 20, "90 Grad");
    } while ( u8g2.nextPage() );
  }
  else if ( SERVOValue == "180" )
  {
    servoblau.write(180);
    server.send ( 200, "text/html", getPage() );
    u8g2.setFont(u8g2_font_courB18_tf);
    u8g2.setFontDirection(0);
    u8g2.firstPage();
    do {
      u8g2.drawStr(0, 20, "180 Grad");
    } while ( u8g2.nextPage() );
  } else
  {
    Serial.println("Error Servo Value");
  }
}

String getPage() {
  String page = "‹html lang=en-EN›‹head›‹meta http-equiv='refresh' content='60'/›";
  page += "‹title›arduino-projekte.info‹/title›";
  page += "‹style› body { background-color: #fffff; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }";
  page += ".button {display: inline-block; padding: 15px 15px; font-size: 25px; cursor: pointer; text-align: center; text-decoration: none;";
  page += "outline: none; color: #ffffff; background-color: #4db2ec; border: none; border-radius: 15px;}";
  page += ".button:hover {background-color: #4DCAEC; color:#ffffff;}";
  page += ".button:active {background-color: #4DCAEC; box-shadow: 0 3px #666; transform: translateY(3px); }‹/style›";
  page += "‹/head›‹body›‹h1›ESP8266 WebServer‹/h1›";
  page += "‹h3>Servo Test‹/h3›";
  page += "‹form action='/' method='POST'›";
  page += "‹INPUT class='button' type='submit' name='SERVO' value='0'›    ";
  page += "‹INPUT class='button' type='submit' name='SERVO' value='90'›    ";
  page += "‹INPUT class='button' type='submit' name='SERVO' value='180'›";

  page += "‹/body>";
  return page;
}

Servo ansteuern mit einem ESP32 als Web Server (Wemos Lolin32)

servo wemos lolin32

Funktion

Die Funktion ist vom Prinzip die selben wie schon in den ersten beiden Versionen. Doch eine Grundlegende Sache ist anders, wie schon ober beschrieben gibt es die Funktion analogWrite() mit mehr. Die Neue Funktion heißt ledcWrite(channel, duty).

Wie wird ledcWrite(channel, duty) verwendet?

Im Setupteil müssen die Befehle ledcSetup(Kanal, Frequenz, Bit); und ledcAttachPin(Pin, Kanal); eingetragen werden und im Loopteil ledcWrite(Kanal, Zeit);.

ledcSetup(Kanal, Frequenz, Bit);

Kanal: Es git 16 Kanäle die Verwendet werden können. (einstellbar von 0-15)
Frequenz: Die Frequenz kann von 1Hz-40MHz eingestellt werden, das sagt aus wie schnell ein wechsel der Periode (Ein Aus Zustand) dauert. Bei dem Servo hat sich 166Hz als gut gezeigt.
Bit: Gibt die Aufteilung der Periode an, wieviel Schritte Sie hat und das ganze wird so gerechnet. Nehmen wir na wir haben 8 Bit, dann muss man 28-1 rechnen ergibt 255, dass ergibt dann die Zeit oder Teilung für den Befehl ledcWrite(Kanal, Zeit);.

ledcAttachPin(Pin, Kanal);

Hier wird der Kanal an einen Pin übergeben.
Pin: Hier wird der Pin am EPS32 angeben, wo in diesem Fall der Servo angeschlossen ist.
Kanal: Das muss der Selbe sein wie im Befehl ledcSetup.
Beispiel:
Kanal 1 mit 166Hz und 8 Bit, wird an Pin 13 übergeben. Kanal 1 wird mit 127 ausgegeben, das heißt 127 (2,5 Volt am Arduino, 1,6 Volt am EPS32) ist ca. die hälte von den 255. 255 ist quasi das Signal 1 (high) (5 Volt am Arduino, 3,2 Volt am EPS32)
ledcSetup(1, 166, 8);
ledcAttachPin(13, 1);
ledcWrite(1, 127);

Programmcode

Die Bibliothek Webserver bekommt Ihr hier. https://github.com/bbx10/WebServer_tng
Wie Ihr die Bibliothek U8g2lib installiert könnt Ihr hier nachlesen.
Und zu guter Letzt die Bibliothek um den Wemos Lolin32(ESP32) zu installieren, findet Ihr hier.

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
const char* ssid     = "WLAN NAME";
const char* password = "PASSWORT";

WebServer server ( 80 );

void setup()
{
  ledcSetup(1, 166, 8);
  ledcAttachPin(13, 1);
  Serial.begin(9600);
  u8g2.begin();
  u8g2.enableUTF8Print();
  connectWifi();
  beginServer();
  servoblau.write(0);
  u8g2.setFont(u8g2_font_courB18_tf);
  u8g2.setFontDirection(0);
  u8g2.firstPage();
  do {
    u8g2.drawStr(0, 20, "0 Grad");
  } while ( u8g2.nextPage() );
}

void loop() {
  server.handleClient();
  delay(1000);
}

void connectWifi()
{
  WiFi.enableSTA(true);
  delay(2000);
  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());
}

void beginServer()
{
  server.on ( "/", handleRoot );
  server.begin();
  Serial.println ( "HTTP server started" );
}

void handleRoot() {
  if ( server.hasArg("SERVO") ) {
    handleSubmit();
  } else {
    server.send ( 200, "text/html", getPage() );
  }
}

void handleSubmit() {

  String SERVOValue;
  SERVOValue = server.arg("SERVO");
  Serial.println("Set GPIO ");
  Serial.print(SERVOValue);

  if ( SERVOValue == "0" ) {
    ledcWrite(1, 2);
    server.send ( 200, "text/html", getPage() );
    u8g2.setFont(u8g2_font_courB18_tf);
    u8g2.setFontDirection(0);
    u8g2.firstPage();
    do {
      u8g2.drawStr(0, 20, "0 Grad");
    } while ( u8g2.nextPage() );
  }
  else if ( SERVOValue == "90" )
  {
    ledcWrite(1, 60);
    server.send ( 200, "text/html", getPage() );
    u8g2.setFont(u8g2_font_courB18_tf);
    u8g2.setFontDirection(0);
    u8g2.firstPage();
    do {
      u8g2.drawStr(0, 20, "90 Grad");
    } while ( u8g2.nextPage() );
  }
  else if ( SERVOValue == "180" )
  {
    ledcWrite(1, 125);
    server.send ( 200, "text/html", getPage() );
    u8g2.setFont(u8g2_font_courB18_tf);
    u8g2.setFontDirection(0);
    u8g2.firstPage();
    do {
      u8g2.drawStr(0, 20, "180 Grad");
    } while ( u8g2.nextPage() );
  } else
  {
    Serial.println("Error Servo Value");
  }
}

String getPage() {
  String page = "‹html lang=en-EN›‹head›‹meta http-equiv='refresh' content='60'/›";
  page += "‹title›arduino-projekte.info‹/title›";
  page += "‹style› body { background-color: #fffff; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }";
  page += ".button {display: inline-block; padding: 15px 15px; font-size: 25px; cursor: pointer; text-align: center; text-decoration: none;";
  page += "outline: none; color: #ffffff; background-color: #4db2ec; border: none; border-radius: 15px;}";
  page += ".button:hover {background-color: #4DCAEC; color:#ffffff;}";
  page += ".button:active {background-color: #4DCAEC; box-shadow: 0 3px #666; transform: translateY(3px); }‹/style›";
  page += "‹/head›‹body›‹h1›ESP8266 WebServer‹/h1›";
  page += "‹h3>Servo Test‹/h3›";
  page += "‹form action='/' method='POST'›";
  page += "‹INPUT class='button' type='submit' name='SERVO' value='0'›    ";
  page += "‹INPUT class='button' type='submit' name='SERVO' value='90'›    ";
  page += "‹INPUT class='button' type='submit' name='SERVO' value='180'›";

  page += "‹/body>";
  return page;
}

Folgende Bauteile wurde verwendet:

1x Wemos Lolin32 http://amzn.to/2Aivjh6 *
1x Wemos D1 mini lite http://amzn.to/2igu51r *
1x Servo http://amzn.to/2BijqHC *
1x Oled Display 0,96 Zoll http://amzn.to/2ic44AC *

3 Thoughts to “Servo ansteuern (Arduino, ESP8266, ESP32)”

  1. Uwe Straube

    Guten Tag,
    ihre Seite finde ich sehr interessant, insbesondere zum Thema Servo-Steuerung mit dem ESP8266 ! Ich habe ein funktionsfähiges Modell für einen Solartracker mit dem Arduino Uno oder Nano aufgebaut. Dabei werden in 4 LDR abgefragt und die PWM-Ausgänge (2) auf je eine H-Brücke LN289N Motortreiber ausgegeben. Nun wäre es natürlich toll, wenn ich über das Smarfon die Stellung der Panele abfragen könnte! Ich benutze für den Solarmonitor erfolgreich das Blynk-App. Welche Idee haben Sie dazu ? Gerne auch gegen eine “Spende” ! Gruss Uwe

    1. Arduino Projekte

      Hallo Uwe,
      was wollen Sie den genau Abfragen? Über ein Spende würde ich mich natürlich freuen, muss aber nicht sein.
      Vielleicht schicken Sie mir mal den Sketch zu.

      Gruß
      Tobias

    2. rainer

      ich denke, dieser artikel könnte interessant sein :: https://learn.adafruit.com/analog-feedback-servos/about-servos-and-feedback

      https://www.arduino.cc/en/Reference/ServoRead == gibt den zuletzt übermittelten wert zurück

Leave a Comment