ESP32 mit Arduino Code programmieren

Über den Beitrag

Nachdem ich in meinem vorletzten Beitrag über die I2C Schnittstellen des ESP32 berichtet habe, möchte ich hier nun einen Gesamtüberblick über diesen leistungsstarken Mikrocontroller geben.

Alles, worüber ich hier berichte, ist im Grunde schon mehr als einmal von irgendwem zuvor beschrieben worden. Warum also noch ein Artikel zu diesem Thema? Es ist der Versuch, die grundlegenden Funktionen, Besonderheiten und Stolpersteine in einem einzigen Beitrag zusammenzufassen. Insbesondere richte ich mich dabei an Arduinonutzer, die in den ESP32 einsteigen wollen. Aber vielleicht findet auch der ESP32-Erfahrene hier die eine oder andere interessante Information.

Ich beziehe mich bei meinen Ausführungen und Beispielen hauptsächlich auf den weitverbreiteten ESP32-WROOM-32, bzw. die auf ihm basierten Boards. Das Meiste ist aber auf andere Vertreter wie den ESP32-PICO übertragbar.

Der Beitrag ist recht lang geworden – hier könnt ihr zu den Abschnitten springen:

ESP32 Boards

Es gibt die verschiedensten ESP32 Boards. Die meisten basieren auf dem ESP32-WROOM-32.  Sehr beliebt sind die Entwicklungsboards wie das oben links abgebildete Modell. Es hat allerdings eine für Breadboards nicht ideale Breite, denn ihr habt nur auf einer Seite Platz für Steckverbindungen (s.u.). Legt ihr zwei Breadboards nebeneinander, sind die Module nicht breit genug, um die +/- Leisten zu überbrücken. Das mag ein Luxusproblem sein, aber nervig ist es schon. Als Lösung empfehle ich Mehrfach-Breadboards, die nur eine +/- Leiste zwischen den einzelnen Boards haben.

Nicht alle ESP32 Module passen auf alle Breadboards
Nicht alle ESP32 Module harmonieren mit allen Breadboards

Alternativ könnt ihr auch zum „Arduino UNO-like“ D1 R32 Board greifen. Oder ihr nehmt einen ESP32 Pico, denn der ist etwas schlanker.

Eigenschaften des ESP32-WROOM-32

Die Leistungsfähigkeit der ESP32 Boards lässt AVR basierte Arduinos wie den UNO schon recht alt aussehen. Die vier- bis zwölffach höhere Taktrate und ein im Vergleich riesiger Flashspeicher sind eine andere Dimension. Ein klarer Vorteil für die Arduino (AVR) Boards ist allerdings, dass man die zugrundeliegenden Mikrocontroller sehr einfach auch „standalone“ betreiben kann. Damit lassen sich platz- und energiesparende Projekte realisieren. Einen blanken ESP32 zu verdrahten, ist hingegen nicht unbedingt jedermanns Sache.

Hier nun die wichtigsten Daten des ESP32-WROOM-32 im Überblick:

  • Betriebsspannung: 3.3 Volt
  • Stromverbrauch: 1µA (Hibernation) bis max ca. 240 mA
    • Strombedarf ist abhängig vom Modus und den aktivierten Komponenten
    • im Normalbetrieb ohne WiFi und Bluetooth: ca. 50-70 mA
  • Taktrate bis 240 MHz
  • 520 kByte interner SRAM (für Daten und Befehle)
  • Externer Flash-Speicher bis zu 16 MByte
    • die meisten Module haben 4 MByte Speicher, davon ca. 1 MByte „zur freien Verfügung“
  • 34 Ein-/Ausgänge:
    • nutzbar: 22 GPIOs, 4 GPIs (reine Eingänge)
    • einige mit gewissen Einschränkungen
  • 2 I2C Schnittstellen
  • 2 nutzbare SPI Schnittstellen
  • 3 UART Schnittstellen
  • Echtzeituhr
  • 10 Touchsensoren
  • Integrierter Hallsensor
  • 16 PWM Kanäle
  • 2 „echte“ analoge Ausgänge
  • Bis zu 18 analoge Eingänge
  • WiFi 802.11 b/g/n 2.4 GHz
  • Bluetooth 4.2 / BLE (Bluetooth Low Energy)

Den ESP32 in die Arduino IDE integrieren

Wie ihr die Arduino IDE ESP32-fähig macht, ist schon unendlich oft beschrieben worden. Ich halte mich deswegen kurz.

  1. Geht in der Arduino IDE auf Datei -> Voreinstellungen.
  2. Dort klickt ihr auf das kleine Symbol hinter „Zusätzliche Boardverwalter URLs“.
  3. Tragt „https://dl.espressif.com/dl/package_esp32_index.json“ als separate Zeile ein (ohne Anführungszeichen).
  4. Geht auf Werkzeuge -> Board -> Boardverwalter.
  5. Sucht nach „esp32“ und installiert „esp32 by Espressif Systems“.
  6. Ggf. müsst ihr die Arduino IDE neu starten.

Nach der Installation findet ihr mehrere Dutzend ESP32 Boards zur Auswahl. Da müsst ihr schauen welches passt. Weitverbreitet ist das „ESP32 Dev Module“.

Pinout des ESP32 Development Boards

Es gibt verschiedene Ausführungen ESP32-WROOM-32 basierter Boards. Das bedeutet, dass die Pins bei eurem Board vielleicht anders angeordnet sind und ggf. auch Pins fehlen. Was aber immer übereinstimmt, ist die Mehrfachfunktion der Pins. Das heißt, dass beispielsweise GPIO4 immer auch HSPI_HD, ADC2_CH0, TOUCH_0 und RTC_IO 10 ist.

Pins des ESP32 Development Boards
Pins des ESP32 Development Boards

„Verbotene“ / eingeschränkt nutzbare Pins

Einige Pins sind nur eingeschränkt benutzbar, andere solltet ihr grundsätzlich unverbunden lassen. Zu letzterer Gruppe gehören die Pins GPIO6 bis GPIO11. Sie werden intern für die SPI Kommunikation mit dem Flash-Speicher benutzt. Ich habe sie deshalb grau gekennzeichnet. Ignoriert sie am besten.

Einige Pins senden beim Booten des ESP32 PWM Signale oder gehen kurz in den HIGH Status. Je nachdem, was ihr an die Pins hängt, kann das stören, es muss aber nicht. Dabei handelt es sich um die Pins GPIO0, GPIO1, GPIO3, GPIO5, GPIO14 und GPIO15.

GPIO0, GPIO2, GPIO4, GPIO5, GPIO12 und GPIO15 sind sogenannte „Strapping Pins“, die den ESP32 über ihren Zustand beim Booten in den Bootloader- oder Flashmodus bringen. Wenn ihr dort beim Booten etwas dranhängt, was die Pins in den HIGH- oder LOW-Zustand zieht, kann das zu unerwartetem Verhalten führen. Ihr kennt das vielleicht vom GPIO0 Pin des ESP8266 ESP-01.

Die ADC2_CHx Pins können nicht als analoge Eingänge benutzt werden, wenn Wi-Fi aktiv ist.

Digitale Ein-/Ausgänge des ESP32

Die Nutzung der GPIOs als digitale Ein- und Ausgänge funktioniert im Wesentlichen wie beim Arduino mit den Funktionen pinMode(), digitalWrite() und digitalRead(). Der Arduino (AVR) Umsteiger muss sich dabei vor allem an die reduzierte Spannung von 3.3 Volt gewöhnen. Der maximale Strom sollte 12 mA nicht überschreiten.

Einen wichtigen Unterschied zum Arduino gibt es beim Betrieb der GPIOs als Eingang. Um bei Verwendung von pinMode(pin, INPUT) ein LOW-Level am Pin zu erreichen, müsst ihr beim Arduino einen externen Pull-Down Widerstand verwenden. Hingegen könnt ihr beim ESP32 einen internen Pull-Down Widerstand über INPUT_PULLDOWN zuschalten. Wählt Ihr das einfache INPUT, dann ist der Pin-Level undefiniert.

Die Pins GPIO34-39 sind reine Eingänge, weshalb die Bezeichnung GPI passender ist. Außerdem steht an diesen Pins kein interner Pull-Up oder Pull-Down Widerstand zur Verfügung.

Analoge Ein-/Ausgänge des ESP32

Analoge Eingänge

Der ESP32 besitzt zwei A/D-Wandler mit einer Auflösung von 12 Bit. Die ADC1- und die ADC2-Eingänge teilen sich also jeweils einen A/D-Wandler. Das Auslesen erfolgt wie gewohnt mittels analogRead(pin). Die Spannung U ist dann (theoretisch):

U\;\text{[V]} = \frac{3.3 \cdot \text{analogRead()}}{4096}

So hervorragend die Leistung des ESP32 sonst ist – die A/D-Wandler sind es definitiv nicht:

  1. Die Streuung der Messwerte ist sehr hoch.
  2. Noch schlimmer: das Verhalten ist nicht linear.

Die Streuung bekommt man in den Griff. Espressif empfiehlt (hier) einen 0.1 µF Kondensator an den Eingang zu hängen und Messwerte zu mitteln. Ohne Kondensator habe ich 500 – 1000 Messwerte mitteln müssen, um die Schwankung auf unter 0.01 Volt zu bringen.

Problematischer ist die Nicht-Linearität. Ich habe das mal nachgemessen und mein Ergebnis deckt sich mit den Angaben, die ich an anderen Stellen im Netz gefunden habe:

Messwerte des ESP32 A/D-Wandlers vs. tatsächliche Spannung
Messwerte des ESP32 A/D-Wandlers vs. tatsächliche Spannung

Einige empfehlen den Einsatz von „Look-Up“ Tabellen, um den Fehler auszugleichen (z.B. hier auf GitHub), andere empfehlen Ausgleichspolynome (z.B. hier). Wenn ihr genaue Messwerte braucht, rate ich zu einem vernünftigen externen A/D Wandler wie den ADS1115.

Analoge Ausgänge

analogWrite()

Die analogWrite() Funktion steht an allen Output Pins zur Verfügung. Wie gewohnt stehen Werte zwischen 0 und 255 zur Verfügung. Die zugrundeliegende PWM-Frequenz beträgt 1 kHz.

Die dacWrite Funktion

Zusätzlich zu analogWrite() gibt es für den ESP32 die dacWrite() Funktion. Sie liefert ein echtes analoges Signal zwischen 0 und 3.3 Volt, das an den zwei DAC Pins ausgegeben werden kann. So wird die Funktion aufgerufen:

dacWrite(pin, value) mit pin = 25 oder 26 und value = 0, 1, 2 …. 255.

Theoretisch ist die Spannung U:

U\;\text{[V]}=\frac{3.3}{255}\cdot value

Praktisch sieht es so aus:

Theoretische und tatsächliche Spannung an den DAC Pins des ESP32
Theoretische und tatsächliche Spannung an den DAC Pins

Der Minimalwert lag bei meinen Messungen bei 0.086 Volt, der Maximalwert bei 3.18 Volt. Immerhin ist die Steigung weitestgehend linear, sodass man hier mit einer Kalibriergeraden arbeiten kann.

Pulsweitenmodulation (PWM)

Eine detaillierte Einführung in Pulsweitenmodulation (PWM) würde den Rahmen dieses Beitrages sprengen. Also nur so viel: PWM wird unter anderem für die Ansteuerung von Servomotoren oder zum Dimmen von LEDs verwendet. Ein PWM Signal ist ein Rechtecksignal mit bestimmter Frequenz (= 1/Periode) und einem bestimmten Tastgrad (Duty Cycle). Hier ein Beispiel mit einem Tastgrad von 25 %:

PWM-Signal mit 25% Tastgrad (Duty Cycle)

Der ESP32 hat 16 PWM Kanäle, die den GPIO Pins zugeordnet werden können. Die reinen Eingänge GPI32 – GPI39 können jedoch nicht für PWM verwendet werden. Mit der Funktion ledcAttach(pin, freq, res) legt ihr die Grundeinstellungen fest. Dabei ist pin der GPIO-Pin, freq ist die Frequenz und res die Auflösung in Bit. Alternativ legt ihr den Kanal selbst mit ledcAttachChannel(pin, freq, res, channel) fest.

Den Duty Cycle legt ihr mit der Funktion ledcWrite(pin, dutyCycle) fest und startet damit die Ausgabe. Der Duty Cycle in Prozent ist dutyCycle/2res x 100.

Hier ein kleiner Beispielsketch, der eine LED an GPIO18 periodisch dimmt und aufleuchten lässt.

const int pwmPin = 18;  // = GPIO18
const int freq = 1000;
const int pwmChannel = 0; // choose 0 - 15
const int res = 8; // 2^8 = 256
 
void setup(){
  ledcAttach(pwmPin, freq, res); // channel is chosen automatically
  // ledcAttachChannel(pwmPin, freq, res, pwmChannel); // choose channel youself
}
 
void loop(){
  for(int dutyCycle = 0; dutyCycle <= 256; dutyCycle++){   
    ledcWrite(pwmPin, dutyCycle);
    delay(3);
  }
  for(int dutyCycle = 256; dutyCycle >= 0; dutyCycle--){
    ledcWrite(pwmPin, dutyCycle);   
    delay(3);
  }
}

Ich komme noch einmal kurz auf analogWrite() zurück. Beim Arduino Uno erzeugt analogWrite() an den meisten Pins ein PWM Signal mit einer Frequenz von 490 Hz und einer Auflösung von 8 Bit (siehe hier auf den Arduino Seiten). Mit ledcAttach(pin, 490, 8) könnt ihr das leicht nachstellen.

Maximale PWM Auflösungen und Frequenzen

Als Auflösung könnt ihr Werte zwischen 1 und 15 Bit wählen. Die Auflösung bestimmt zusammen mit der internen Timerfrequenz (80 MHz) die maximale Frequenz des PWM Signals:

f_{\text{max}}=\frac{80000000}{2^\text{(res in bit)}} \;\;\;\;\;\;\text{z.B.:}\;\; \text{res} = 10\;\text{Bit}\;\;\; =>\;\;\;f_{\text{max}}=\frac{80000000}{2^{10}}= 78125\; \text{[Hz]}

Im Extremfall wählt ihr eine Auflösung von einem Bit. Damit ist der Duty Cycle unveränderbar 50 % und die maximale Frequenz liegt bei gigantischen 40 MHz. Das ist ein Bereich, in dem mein Oszilloskop an seine Grenzen stößt.

PWM mit dem ESP32 - links: 78125 Hz, rechts: 40 MHz
PWM mit dem ESP32 – links: 78125 Hz, rechts: 40 MHz, Duty Cyle: 50%

Ein freundlicher Leser (vielen Dank an Stefan Groß), hat damit seinem professionellen Equipment (aktiver Tastkopf, 1 GHz, 10:1) einmal nachgemessen:

40 MHz PWM - gemessen mit besserem Equipment
40 MHz PWM – gemessen mit besserem Equipment

I2C mit dem ESP32

Im Gegensatz zum Arduino (UNO) hat der ESP32 zwei I2C Schnittstellen. Die Standardschnittstelle befindet sich an GPIO21 und GPIO22. Wenn ihr diese verwendet, ist die Bedienung wie beim Arduino. D.h. ihr bindet wie gewohnt die Wire.h Bibliothek ein und benutzt ihre Funktionen.

Ihr müsst aber bedenken, dass der ESP32 auf 3.3 Volt läuft. Wenn ihr ein 5 Volt Bauteil per I2C anschließt, solltet ihr einen Level Shifter oder Spannungsteiler dazwischen setzen. Das gilt natürlich auch für SPI, UART und alle anderen Verbindungen.

Ein weiterer Unterschied ist, dass ihr die I2C Schnittstelle anderen GPIOs zuordnen könnt. Wie ihr das bewerkstelligt, wie ihr die zweite I2C Schnittstelle verwendet und wie ihr die entsprechenden TwoWire Objekte an andere Objekte übergebt, habe ich sehr detailliert hier beschrieben. Ich gehe deswegen nicht noch einmal näher darauf ein.

SPI mit dem ESP32

Der ESP32 besitzt insgesamt vier SPI Schnittstellen. Allerdings stehen euch nur zwei davon zur freien Verfügung, nämlich VSPI und HSPI. Die anderen beiden SPI Schnittstellen werden intern verwendet. VSPI ist die Standardschnittstelle. Sie findet sich an den GPIOs 18 (VSPI_CLK), 19 (VSPI_MISO), 23 (VSPI_MOSI) und 5 (VSPI_CS = Chip Select). Verwendet ihr VSPI, müsst ihr euch nicht umgewöhnen. Ihr bindet SPI.h ein und benutzt die üblichen Funktionen dieser Klasse. Obwohl die Schnittstelle VSPI heißt, sprecht ihr sie mit SPI an.

Wenn ihr zusätzlich HSPI verwenden wollt, dann müsst ihr zunächst das entsprechende SPI Objekt erzeugen. Hier ein einfaches kleines Beispiel, bei dem ich zwei MPU9250 Module an HSPI und VSPI gehängt habe. Die verwendete MPU9250 Bibliothek von Bolderflight ist hier auf Github zu finden. Ihr müsst euch damit aber nicht wirklich beschäftigen. Das Entscheidende sind die ersten Zeilen. Sie sollen das Prinzip verdeutlichen.

#include "MPU9250.h"
#include "SPI.h"

SPIClass SPI_2(HSPI); // create SPI_2 object
MPU9250 IMU_1(SPI,5);  // pass standard SPI object (VSPI) and Chip Select
MPU9250 IMU_2(SPI_2,15);  // pass SPI_2 object (HSPI) and Chip Select

int status;

void setup() {
  Serial.begin(115200);
 
  status = IMU_1.begin();
  if (status < 0) {
    Serial.println("IMU 1 initialization unsuccessful");
    while(1) {}
  }
  status = IMU_2.begin();
  if (status < 0) {
    Serial.println("IMU 2 initialization unsuccessful");
    while(1) {}
  } 
}

void loop() {
  IMU_1.readSensor();
  Serial.println("IMU 1 Acceleration Data:");
  Serial.print(IMU_1.getAccelX_mss(),6);
  Serial.print("\t");
  Serial.print(IMU_1.getAccelY_mss(),6);
  Serial.print("\t");
  Serial.println(IMU_1.getAccelZ_mss(),6);

  IMU_2.readSensor();
  Serial.println("IMU 2 Acceleration Data:");
  Serial.print(IMU_2.getAccelX_mss(),6);
  Serial.print("\t");
  Serial.print(IMU_2.getAccelY_mss(),6);
  Serial.print("\t");
  Serial.println(IMU_2.getAccelZ_mss(),6);
 
  delay(1000);
}

 

Wechsel der Standard SPI Pins

Ihr könnt VSPI und HSPI auch anderen Pins zuordnen. Einen ausführlichen Sketch dazu findet ihr hier auf Github.

UART (Serial) mit dem ESP32

Der ESP32 besitzt drei serielle Schnittstellen, die als U0UXD, U1UXD und U2UXD bezeichnet werden. Die drei Schnittstellen sind folgenden Pins zugeordnet:

Voreinstellung für die UART Pins des ESP32
Voreinstellung für die UART Pins des ESP32

U0UXD ist die Standardschnittstelle, die unter anderem für die Ausgabe auf dem seriellen Monitor benutzt wird. Sie wird wie gewohnt über Serial.begin(baud rate) initialisiert. Wenn ihr U1UXD und U2UXD nutzen wollt, dann legt ihr mit Serialx.begin(baud rate, protocol, RXPin, TXPin) die Eigenschaften der Schnittstelle fest (x = 1 oder 2). Ruft ihr die begin Funktion nur mit der Baudrate auf, greifen die Voreinstellungen.

Sehr theoretisch, aber mit dem Beispiel sollte es klar werden:

#define RX1 16
#define TX1 17
#define RX2 12
#define TX2 13

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200, SERIAL_8N1, RX1, TX1);
  Serial2.begin(115200, SERIAL_8N1, RX2, TX2);
  delay(100);
  if(Serial1){
    Serial.println("Serial1 successfully set up");
  }
  if(Serial2){
    Serial.println("Serial2 successfully set up");
  }
}

void loop(){}

 

Dabei bedeutet SERIAL_8N1: 8 Bits, keine Parität (N = no), 1 Stopp Bit. Das ist der Standard. Eine Sammlung möglicher Protokoll-Parameter habe ich hier auf GitHub gefunden.

Ihr könnt nach demselben Schema auch die Pins für die Standardschnittstelle ändern: Serial.begin(baud rate, protocoll, RXPin, TXPin).

Touch Pins

Die Touch Pins des ESP32 reagieren auf Kapazitäten. Je größer die Kapazität, desto kleiner der Messwert. Da der menschliche Körper auch eine Kapazität darstellt, reagieren die Touch Pins auf Berührung. Der kleine Beispielsketch zeigt, wie es geht:

void setup() {
  Serial.begin(9600);
  while(!Serial){} 
  Serial.println("ESP32 Touch Test");
}

void loop() {
  Serial.println(touchRead(4));  // get value of Touch 0 pin = GPIO 4
  //Serial.println(touchRead(T0)); // alternative 
  delay(1000);
}

 

Ich habe den Touch Pin mit einem Steckbrückenkabel verbunden und das lose Ende des Kabels zunächst nicht berührt, dann berührt und dann mit einem 10 µF Elko verbunden. So sah die Ausgabe dazu aus:

Ausgabe von ESP32_touch_test.ino
Ausgabe von ESP32_touch_test.ino

Hall Sensor

Für den Fall, dass ihr irgendwo etwas von der Hall-Sensorfunktion hallRead() gelesen habt: Sie wird nicht mehr unterstützt. Besonders gut war der Hall-Sensor nicht, aber man hätte die Unterstützung ja nicht unbedingt streichen müssen.

Interrupts

Was die Interruptprogrammierung des ESP32 angeht, könnte ich einen eigenen Beitrag füllen. Ich beschränke mich hier auf externe GPIO Interrupts.

Ihr könnt Interrupts an jedem GPIO Pin einrichten, einschließlich der reinen Eingänge GPI34 – GPI39. Die Handhabung ist wie bei den Arduino Boards, bis auf eine Besonderheit. Wenn ihr bei der Interrupt Service Routine (ISR) das Attribut IRAM_ATTR anwendet, wird der Code nicht im Flash, sondern im RAM gespeichert. Damit wird die Ausführung wesentlich schneller. Dann müsst ihr aber die ISR noch vor setup() platzieren (zumindest ist das so in der Arduino IDE). Klingt vielleicht kompliziert, ist es aber nicht.

In meinem kurzen Beispiel gibt ein Tasterdruck ein HIGH Signal an GPIO4. Das löst einen Interrupt aus. Hier zunächst die höchst komplexe 😉 Schaltung:

ESP32 Interrupt Test an GPIO4
Interrupt Test an GPIO4

Und nun der Sketch:

int interruptPin = 4; // define GPIO4 as interrupt pin
volatile bool event = false;

void IRAM_ATTR eventISR(){
  event = true;
  detachInterrupt(interruptPin);
}

void setup() {
  Serial.begin(115200);
  while(!Serial){}
  pinMode(interruptPin, INPUT_PULLDOWN);
  attachInterrupt(interruptPin, eventISR, RISING);
}

void loop() {
  if(event){
    Serial.println("Interrupt!");
    delay(1000); //debouncing
    event = false;
    attachInterrupt(interruptPin, eventISR, RISING);   
  }
}

 

Ihr könnt auch problemlos mehrere Interrupts definieren. Wäre doch eine schöne Übung!

Strom sparen – Schlafmodi

Der ESP32 ist ebenso leistungsstark wie stromhungrig. Bei batteriebetriebenen Projekten kann das zum Problem werden. Es gibt aber Möglichkeiten, den Stromverbrauch auf einen Bruchteil zu senken. Zunächst einmal könnt ihr bestimmte Komponenten abschalten. Die größten Stromfresser sind WiFi und Bluetooth. Solltet ihr sie benutzen, dann denkt darüber nach, sie, wenn möglich, zwischendurch abzuschalten. Dazu gibt es die Funktionen WiFi.mode(WIFI_OFF) und btStop(). Darüber hinaus gibt es verschiedene Schlafmodi, die ihr aktivieren könnt.

In diesem ESP32 Überblick muss ich mich ein wenig beschränken und werde nur kurz „Light Sleep“ und „Deep Sleep“ behandeln. Mit esp_sleep_enable_timer_wakeup() definiert ihr eine Schlafphase, nach der der ESP32 wieder aufwacht. Als Parameter übergebt ihr die Zeit in Mikrosekunden. Aber erst, wenn ihr esp_deep_sleep_start() oder esp_light_sleep_start() aufruft, beginnt die Schlafphase.

Nach dem Light Sleep fährt das Programm dort fort, wo es gestoppt hat. Nach dem Deep Sleep startet es neu. Ihr könnt das mit dem folgenden Sketch ausprobieren:

const int unsigned long microSecToSec = 1000000;
const int sleepTime = 5; 

void setup(){
  Serial.begin(115200);
  while(!Serial){}

  esp_sleep_enable_timer_wakeup(sleepTime * microSecToSec);
  Serial.println();
  Serial.println("ESP32 will go to sleep for 5 seconds....");
  delay(2000);
  Serial.println("...now");
  esp_deep_sleep_start();
  //esp_light_sleep_start(); 
  Serial.println("This message will only be printed after light sleep");
}

void loop(){ 
}

 

Aufwachen per externem Signal

Ihr könnt den ESP32 auch über ein externes Signal an einem der RTC_IO Pins wecken. Das richtet ihr mit esp_sleep_enable_ext0_wakeup(GPIO_NUM_x, HIGH/LOW) ein. Die Funktion erwartet als erstes Argument die Pin Nummer im Format GPIO_NUM_x. Wenn ihr stattdessen einfach ein Integer übergebt, gibt es eine Fehlermeldung. Der zweite Parameter legt fest, ob ein HIGH oder ein LOW Signal den ESP32 wecken soll.

void setup(){
  Serial.begin(115200);
  while(!Serial){};
  pinMode(GPIO_NUM_4, INPUT_PULLDOWN); 
  Serial.println();
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_4,1);
  Serial.println("ESP32 will go to deep sleep...");
  delay(1000);
  Serial.println("...now");
  esp_deep_sleep_start(); //
  Serial.println("This message will only be printed after light sleep");
}

void loop(){ 
}

 

Aufwachen durch Touch

Das Aufwachen per Berührung (touch) steuert ihr mit der Funktion esp_sleep_enable_touchpad_wakeup(). Vorher müsst ihr aber noch einen Touch Interrupt einrichten. So geht’s:

#define THRESHOLD 40
void callback(){}

void setup(){
  Serial.begin(115200);
  delay(1000);
  touchAttachInterrupt(T4, callback, THRESHOLD); //T4 = GPIO13
  esp_sleep_enable_touchpad_wakeup();
  Serial.println("Going to deep sleep...");
  delay(1000);
  Serial.println("...now");
  esp_deep_sleep_start();
}

void loop(){
}

 

Ihr müsst also nur den GPIO13 berühren (am einfachsten über ein Steckbrückenkabel) und schon wacht der ESP32 auf. Wenn ihr möchtet, könnt ihr die Funktion callback(){} noch mit weiteren Anweisungen füllen. Der Touch Interrupt funktioniert natürlich auch ohne Weckfunktion.

WiFi

Der Gebrauch der WiFi Funktion ist ein komplexes Thema, das ich einem separaten Beitrag behandele. Schaut hier.

Bluetooth

Auch das Thema Bluetooth ist sehr umfangreich. Ich beschränke mich in diesem Beitrag auf ein einfaches Beipiel, und zwar zeige ich, wie ihr LEDs per Smartphone oder Computer am ESP32 schaltet. Dazu braucht ihr erst einmal ein Bluetooth Terminal Programm. Für den PC schlage ich Bluetooth Serial Terminal vor, für das Smartphone die App Bluetooth Terminal.

Auf der ESP32 Seite hängt ihr zwei LEDs an GPIO4 und GPIO13. Ihr könnt natürlich auch andere Pins wählen und das Beispiel beliebig erweitern.

Ladet den folgenden Sketch hoch, dann koppelt ihr den ESP32 mit dem Smartphone oder PC. Der ESP32 erscheint unter dem Namen, den ihr ihm mit espBT.begin("name") verleiht. Nach dem Koppeln müsst ihr den ESP32 im Computerprogramm oder in der Smartphone-App noch verbinden. In der App geht ihr dazu auf die drei Punkte, im PC Programm ist es offensichtlich. 

Sendet ihr nun beispielsweise eine „+4“ an den ESP32, schaltet ihr die LED an GPIO4 damit ein. Mit „-4“ hingegen schaltet ihr sie aus.

#include "BluetoothSerial.h" 

BluetoothSerial espBT; 

void setup() {
  Serial.begin(115200);
  pinMode(4, OUTPUT);
  pinMode(13, OUTPUT);
  espBT.begin("ESP32 Bluetooth Example");
  Serial.println("Pair your BT device now");  
}

void loop(){
  if(espBT.available()){
    char command = espBT.read();
    int state = LOW;
    int pin = espBT.parseInt();
    Serial.print("Received: "); 
    Serial.print(command);
    Serial.println(pin);

    if((command == '+')||(command == '-')){
      if(command == '+'){
        state = HIGH;
      }
      else state = LOW;
      digitalWrite(pin, state);
    }
    
    espBT.print("Received: "); 
    espBT.print(command);
    espBT.println(pin);
  }     
}

 

Und so sieht das Programmfenster des Bluetooth Serial Terminal aus:

Bluetooth Serial Terminal Programmfenster
Bluetooth Serial Terminal Programmfenster

Noch ein paar kurze Erläuterungen:

  • BluetoothSerial espBT erzeugt das Bluetooth Objekt.
  • espBT.read() liest das erste Zeichen, also „+“ oder „–“.
  • espBT.parseInt() identifiziert in den ankommenden Zeichen die nächste Ziffernfolge und liest sie als Integer ein (sehr praktische Funktion).

Den Rest müsstet ihr euch erschließen können. Falls nicht, dann gibt es zum Beispiel hier ein ausführlicheres Tutorial.

Fashhungriges BluetoothSerial – den Flash vergrößern

Nach dem Einbinden von BluetoothSerial.h werdet ihr sehen, dass der Programmspeicher auf einmal sehr stark belegt ist. Falls ihr den Programmspeicher vergrößern möchtet, dann geht zu Werkzeuge → Partition Scheme und wählt dort die Einstellung „HugeAPP (3MB NoOTA/1 MB SPIFFS)“.

„Exotische“ Pin-Funktionen

Wenn ihr noch einmal zu dem Pinout Diagramm vom Anfang zurückgeht, seht ihr, dass ich die meisten Pinfunktionen erklärt habe. Ein paar fehlen jedoch noch. Wahrscheinlich werden die meisten sie nie nutzen.

Die APIs (Application Programming Interfaces)

Wie ihr gesehen habt, gibt es einige Funktionen wie beispielsweise ledcAttach(), die ihr aus dem Standardrepertoire der Arduinofunktionen nicht kennt. Diese gehören zu den ESP32 APIs, die ihr hier findet. Es lohnt sich, da mal hinzuschauen.

Danksagung

Die Wolke im Beitragsbild stammt von Clker-Free-Vector-Images auf Pixabay.

49 thoughts on “ESP32 mit Arduino Code programmieren

  1. Hallo Herr Ewald,
    Ich versuche für meinen Enkel das Board ESPDUINO-32 (bestellt war WEMOS D1 R32) mit der Arduino IDE zu verbinden. 340-Treiber sind installiert. Welches Board aus der Vielzahl der ESP-Espressiv könnte da passen?
    Mit dem Board DOIT Espduino-32 klappts nicht.

      1. Vielen Dank für die schnelle Antwort!!
        Das ESP32 Dev Module hatte ich bereits ausprobiert. Leider erfolglos. Auch der Wemos D1 Mini ESP32 verbindet sich nicht.
        Der USB Anschluss sollte intakt sein, wenn beim Einstecken das übliche Tonsignal kommt.
        Ich werde mich jetzt mal an den Händler halten.
        Dankeschön und einen schönen Nachmittag noch!
        Friedhelm

  2. Hallo Herr Ewald,
    Danke für Ihre sehr informativen Seiten!!!
    1. Es gibt drei UART-Ports beim ESP32. In Ihrer Tabelle oben steht zu U1UXD „Die voreingestellten Pins ((9 und 10)) sollten nicht benutzt werden.“ Wie ist das zu verstehen? Kann man U1UXD garnicht verwenden oder nur nicht mit diesen Pins? Gibt es im letzteren Fall Empfehlungen? Im „theoretischen“ Beispielsketch werden die Pins 12 und 13 benutzt.
    2. Über der UART-Tabelle wird von U0UXD, U1UXD und U2UXD gesprochen. In der Tabelle findet sich statt U2UXD der Begriff UART2. Was hat das zu bedeuten?

    1. Hallo,
      zu 1: es gibt Pins auf dem ESP32, die man gar nicht nutzen sollte oder die nur eingeschränkt nutzbar sind (siehe Kapitel: Verbotene / Eingeschränkt nutzbare Pins). U1UXD kann an allen nicht eingeschränkten/verbotenen Pins genutzt werden. GPIO34 – 39 sind als rein Input Pins auch ungeeignet. Zu 2: Anstelle UART2 sollte da natürlich U2UXD stehen. Danke für den Hinweis.

  3. Hallo Herr Ewald, super und vor allem verständlicher Beitrag zum ESP32 mit vielen hilfreichen Informationen!
    Beschäftige mich gerade das erste mal mit dem Thema ESP32, weil ich eine Alternative zu einer bereits bestehenden Steuerung suche. Derzeit habe ich eine Fernbedienung bestehend aus einem Arduino Mega, einem Touchscreen und 2 HC-05 Modulen, die als Master agieren. Leider kommt es bei der Kopplung zwischen den beiden Mastern und den beiden Slaves, die jeweils an einem Nano hängen, immer mal zu Verbindungsproblemen, weil sich die Master nicht immer mit dem richtigen Slave verbinden.
    Aus diesem Grund bin ich auf der Suche nach einer Alternative und auf das ESP32-Board und Ihren Beitrag gestoßen.
    Meine Frage ist jetzt:
    Verstehe ich Ihren Beitrag richtig, dass ich mit dem ESP32 in der Lage bin, die beiden HC-05 Slaves an den beiden Nanos direkt anzusteuern, und dabei auf die beiden HC-05 Master verzichten kann, da ich die Slaves über das Bluetooth des ESP32 direkt bzw. gezielt ansteuern kann?
    Sprich, ich drücke auf dem Touchscreen „A“ und Slave/Nano A reagiert und beim drücken von „B“ reagiert Slave/Nano B?
    Eine weitere Frage hätte ich noch zur Stromversorgung.
    Derzeit wird der Mega mit einem 9V-Block betrieben. Wenn ich es jetzt richtig verstehe, bräuchte ich noch ein Step-Down Modul, welches aus den 9V dann 3.3V macht und kann den ESP32 dann über den 3.3V Anschluss betreiben, wobei ich den Touchscreen dann über den 5V-Pin des ESP32 betreiben kann?
    Ist durch die höhere Taktrate des ESP32 auch eine schnellere Aktualisierung des Touchscreens (Auf- und Abbau der Menü-Grafiken) zu erwarten?

    Vielen Dank im voraus und viele Grüße
    Marc

    1. Hallo Marc,
      ich sag mal „du“ (andersherum natürlich auch). Erst einmal gibt es eine Lösung für das willkürliche Verbinden der Master und Slaves. Wenn du die Slaves in den CMODE 1 bringst dann verbinden sie sich nur mit den Partnern deren MAC Adresse du mit AT+BIND=xxxx,yy,zzzzzz hinterlegt hast. Du findest mehr dazu hier:
      https://wolles-elektronikkiste.de/hc-05-und-hc-06-bluetooth-module
      im Kapitel „AT-Kommandos für das HC-05 Modul“.

      Du kannst mit dem ESP32 einen HC-05 direkt über Bluetooth ansteuern. Hier ist ein Beipiel:
      https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino
      Ich habe es mal probiert und es funktionierte (leider nicht 100% zuverlässig). Dann habe ich mal versucht zwei Module zu steuern, das habe ich allerdings nicht hinbekommen. Wobei ich jetzt aber auch nicht allzu lange probiert habe. Heißt nicht mit Sicherheit, dass es nicht geht, ich kann es dir bloß nicht sagen.

      Wenn du das Projekt ganz auf ESP32 Module umstellen würdest, dann könntest du die Module sehr bequem mit ESP-NOW kommunizieren lassen. Dann brauchst du keine extra BT-Module. Siehe hier: https://wolles-elektronikkiste.de/esp-now

      Zur Stromversorgung: ja 3.3 V am 3.3 Volt Pin geht. Du kannst aber auch mit 5 Volt am 5V Pin reingehen. Dahinter sitzt ein Spannungsregler, der auf 3.3 Volt herunterregelt. Andersherum geht es nicht. D.h. wenn du mit 3.3 V versorgst, arbeitet der Spannungsregler nicht als Step-Up Konverter.

      Zur Geschwindigkeit: Da ist immer die Frage, wo der Flaschenhals ist. Wenn er bei der Berechnung der Daten liegt, die du an den Touchscreen sendest, sollte der ESP32 schneller sein. Es könnte aber auch der Touchscreen selbst sein oder die Datenübertragung (SPI?) sein. Ich würde mir einfach mal einen ESP32 besorgen und ein wenig spielen.

      Wahrscheinlich nicht ganz die Antworten, die du hören wolltest, aber ich hoffe, es hilft trotzdem weiter.

      VG, Wolfgang

      1. Hallo Wolfgang, danke für Deine Antworten. 🙂
        Sorry, hätte ich vielleicht im Vorfeld noch erwähnen sollen. Grundsätzlich sind die HC-05 schon mit BIND und CMODE eingerichtet gewesen. Daher auch meiner Verwunderung darüber, dass die sich ab und zu falsch verbinden. Jetzt habe ich aber das erste Mal in der Anleitung von Deinem Link gelesen erst CMODE=1, dann pairen, und dann CMODE=0 und wohl ohne BIND?
        Hatte die anderen Anleitungen immer so verstanden, dass ich die Adresse vom Slave auslesen, dem Master diese mit BIND zuweisen und im Anschluss CMODE=0 einstellen soll. Da war nie die Rede von, dass man erst mit CMODE=1 pairen soll..
        Da werde ich mich nochmal dran machen.

        Sind jedenfalls 3 ESP32 unterwegs und mal sehen ob ich es hinbekomme den einen mit den anderen beiden kommunizieren zu lassen. Bei dem was ich auch bisher im Netz dazu gefunden habe, sollte es mit der BLE 4.2 Technologie wohl nicht unmöglich sein, sofern ich das alles richtig verstanden habe.
        ESP-NOW hört sich super an und werde auf jeden Fall mal versuchen die 3 miteinander kommunizieren zu lassen. Allein schon aus sportlichem Interesse.🙃 Das nächste Projekt kommt bestimmt. 🙂
        Ganz werde ich mein Projekt zum jetzigen Zeitpunkt wohl nicht mehr auf ESP umstellen können. Das Modell in dem ein HC-05 Slave arbeitet ist schon fertig gebaut, wobei der 2. Slave im Podest noch zugänglich ist und noch umgebaut werden kann. Da käme dann der 2. ESP in Frage. Den ersten würde ich dann statt des Mega in die FB einbauen und notfalls zusätzlich noch ein HC-05-Master dran anschließen falls ich die Kommunikation zwischen 2 ESP32 und einem HC-05-Slave nicht hinbekomme. Da wäre dann der 3.3V-Pin vom ESP auch interessant.

        Verstehe ich Dich an der Stelle dann richtig, dass wenn ich den ESP mit 3.3V am 3.3V-Pin betreiben würde der 5V-Pin dann prinzipiell nutzlos ist, wohingegen wenn ich den ESP am 5V-Pin mit Spannung versorge, den 3.3V-Pin dann als Spannungsquelle für beispielsweise den HC-05 nutzen kann?

        Der Touchscreen wird über SPI angesteuert. Die 5V werde ich mir dann wohl auch vom StepDownModul holen müssen und kann den ESP32 dann auch noch an das StepDownModul hängen und über den 5V-Pin mit Spannung versorgen.

        Vielen Dank für die nützlichen Antworten und Links. 🙂
        VG, Marc

        1. Hallo, da hab ich mich (aber nur hier im Kommentar) vertan. Im Master muss die Slave Adresse mit der BIND Anweisung hinterlegt werden. Kannst du dir also sparen. Komisch nur, dass es nicht zuverlässig funktioniert.

          Dein Verständnis zu den 3.3 und 5V Pins ist richtig. Bei Versorgung mit 3.3V ist der 5V Pin nutzlos. Der 5V Pin greift die 5V ab, die (ggf.) über den USB Anschluss geliefert werden. Andersherum kannst du dort auch mit 5V hineingehen. Der Spannungsregler wandelt sie auf 3.3V für den ESP32. Der 3.3V Pin ermöglicht dir diese 3.3V abzugreifen oder direkt 3.3V einzusteigen. Der Betrieb mit 5V ist zu empfehlen, da er Spannungsschwankungen abfängt.

          VG, Wolfgang

          1. Hallo, ja das verstehe ich auch nicht so ganz, warum das nicht zuverlässig geht.

            Dann werde ich die 5V-Versorgung nehmen.

            Nochmals Danke für Deine hilfreichen Antworten und weiterhin alles Gute. 🙂

            Viele Grüße
            Marc

      2. Hallo bitte entschuldige ich bin am verzweifeln, da ich mein X-box controller mit einem ESP32 über die mac adresse automatisch über bluetooth verbinden lassen – bisher habe ich da keinen passenden Code gefunden mir ist im Prinzip egal ob es in C oder Micro Python ist. Kannst Du mir irgendwie helfen?
        VG Michael

        1. Hi, ich kann dir keine fertige Lösung anbieten, da ich keine X-Box habe und nicht genau weiß, wie das Bluetooth (BT) der X-Box funktioniert. Was ich dir aber sagen kann, ist dass es zwei verschiedene BT Typen gibt und zwar BT Classic, wie es beispielsweise von Arduino BT Modulen verwendet wird und BLE (BT Low Energy). Ziemlich sicher wirst du letzteres verwenden müssen. Die gute Nachricht: Der ESP32 kann beides. Die schlechte Nachricht: BLE ist komplexer im Umgang. Ich selbst habe noch nichts dazu gemacht, aber vielleicht hilft dieser Artikel weiter:

          https://randomnerdtutorials.com/esp32-bluetooth-low-energy-ble-arduino-ide/

          VG, Wolfgang

    1. Vielen Dank! 0.1 F wäre wohl ein bisschen viel. Da ist mir das µ irgendwie verloren gegangen.

  4. Hallo Hr. Ewald,
    auch ich möchte mich erst mal bei Ihnen für die vielen Informationen auf Ihrer Seite bedanken, die mir als Anfänger sehr viel brachten und lehrreich waren.
    Allerdings habe ich bei Ihrem Sketch „Pulsweitenmodulation (PWM)“ ein Problem, dass ich die Funktion nicht wieder abschalten kann.

    #define PIN_LED1 12
    #define PIN_LED2 13
    const int freq = 5000;
    const int ledChannel = 0;
    const int resolution = 8;

    void setup()
    {
    pinMode(PIN_LED1, OUTPUT);
    pinMode(PIN_LED2, OUTPUT);
    ledcSetup(ledChannel, freq, resolution);
    }

    void loop()
    {
    for (byte i=0; i<6; i++) { //Blinken lang
    digitalWrite(PIN_LED1, !digitalRead(PIN_LED1));
    digitalWrite(PIN_LED2, !digitalRead(PIN_LED2));
    delay(500);
    }
    for (byte i=0; i<16; i++) { //Blinken kurz
    digitalWrite(PIN_LED1, !digitalRead(PIN_LED1));
    digitalWrite(PIN_LED2, !digitalRead(PIN_LED2));
    delay(50);
    }

    delay(1000);

    ledcAttachPin(PIN_LED1, ledChannel);
    ledcAttachPin(PIN_LED2, ledChannel);

    for (byte i=0; i0; i–) { //PWM dunkler
    ledcWrite(ledChannel, i);
    delay(10);
    }
    ledcDetachPin(PIN_LED1);
    ledcDetachPin(PIN_LED2);
    }

    Die Funktion ledcDetachPin habe ich in der Library gefunden, doch statt zu Blinken bleiben die LED’s im oberen Loopteil ( Blinken lang / kurz) ab dem 2ten Loop an.
    Wo ist da mein Gedankenfehler?

    1. Hallo, da ist irgendetwas verlorengegangen:
      for (byte i=0; i0; i–) { //PWM dunkler
      ledcWrite(ledChannel, i);
      delay(10);
      }
      Die vorgegebene Formatierung für die Kommentare macht einiges kaputt. Können Sie mir den Sketch per E-Mail schicken? (wolfgang.ewald@wolles-elektronikkiste.de)
      VG, Wolfgang

      1. Herzlichen Dank,
        e-Mail ist unterwegs und hier der untere Bereich nochmal ab dem delay (1000)


        delay(1000);
        ledcAttachPin(PIN_LED1, ledChannel);
        ledcAttachPin(PIN_LED2, ledChannel);

        for (byte i=0; i heller
        ledcWrite(ledChannel, i);
        delay(10);
        }
        for (byte i=255; i>0; i–) { // –> dunkler
        ledcWrite(ledChannel, i);
        delay(10);
        }
        ledcDetachPin(PIN_LED1);
        ledcDetachPin(PIN_LED2);
        }

        MfG

        Michael

  5. Hallo!

    Mittlerweile habe ich etliche wirklich gute Tipps und Anregungen von Ihren fundierten Beiträgen entdecken und verwenden können. Vielen Dank an dieser Stelle dafür:-).

    Nun beschäftige ich mich seit einiger Zeit mit schicken ESP32-Modulen und möchte eine zweite UART Schnittstelle nutzen. Prinzipiell habe ich die Sache mit Begin & Co. verstanden. Aber ich bin mir unsicher, ob man z.B. die Zeile „HardwareSerial Serial1(1);“ tatsächlich braucht. Für welchen Zweck ist die uart_nr in der Klammer eigentlich gedacht/sinnvoll? Ich hab gelesen, dass damit irgendwie die UART Nr. definiert wird (0,1,2) – um damit die RX- und TX-Pinbelegung festzulegen?! Dies wird doch aber in Serial1.begin mitgeteilt, oder? Mein Rätseln rührt auch daher, dass manche dieses HardwareSerial weglassen (wie hier: https://github.com/G6EJD/ESP32-Using-Hardware-Serial-Ports/blob/master/ESP32_Using_Serial2.ino).

    Ist wahrscheinlich keine so spannende Frage, aber ich bleibe neugierig, was es damit auf sich hat;-).

    Viele Grüße
    Robert Jaeger

    1. Hallo,

      danke für die Frage! Denn man kann die Zeilen HardwareSerial Serialx(x) nicht nur weglassen, man muss es auch. Das sind Definitionen, die schon zuvor gemacht wurden. Keine Ahnung wie das da reingeraten ist.

      VG, Wolfgang

  6. Hallo
    Wie gelesen habe sind Sie richtig Fit und könnten mir weiterhelfen.
    Ich habe ein
    ESP32 NodeMCU WLAN Development Kit C WiFi Bluetooth Board WROOM32 Espressif
    gekauft um meione Raumthermometer in Iobroker einzubindenä
    Mit der Anleitung unten sah das recht einfach aus.
    https://www.smarthomejetzt.de/esp32-board-als-ble-bluetooth-mqtt-gateway-fuer-temperatursensoren-oder-anwesenheitserkennung-in-iobroker-einbinden/

    Leider habe ich das Gefühl dass ich den ESP32 nicht zum download der Firmware bringe.
    Ich kann das Tool starten aber es ladet nichts auf den ESP32
    Ich habe es mit der Boot Taste in allen Variatinen versucht.
    Wie muss ich richtig vorgehen
    Danke Fränki

    1. Hallo,
      ich habe mal auf die Schnelle versucht, die Anleitung nachzuvollziehen. Ich bin dabei aber auf Probleme gestoßen. Zunächst ist da ein Link, der zum Flash-Tool führen soll. Auf der Seite finde ich das Flash Tool aber nicht. Ich habe es mir dann woanders her besorgt. Dann habe ich versucht, die vier Dateien mit dem Flash-Tool hochzuladen bzw. erst einmal zu finden. Die ersten beiden sind kein Problem, für die anderen beiden ist ein Link zu esp32dev-ble-libraries.zip angegeben. Die habe ich heruntergeladen und entpackt, aber in den vielen Dateien die Firmware- und die Partitions-Datei nicht gefunden. Dann hat mich die Lust verlassen.
      Ich würde mich direkt auf der Anleitungsseite melden und fragen. Um die Kollegen, die die Anleitung erstellt haben, in den Schutz zu nehmen: ich weiß, wie schwer es ist, Anleitungen aktuell zu halten.
      Viel Glück!
      VG, Wolfgang Ewald

      1. Hallo
        Erstmal vielen Dank dass Sie sich so viel Mühe gemacht haben.
        Ich habe mal wenn Sie noch Lust haben die Dateien die ich gefunden habe in eine Google Drive Ordner zur Verfügung gestellt. Ich habe das noch nie gemacht und hoofe es klappt.

        1) Mich würde auf jeden Fall interessieren ob ich den esp32 irgendwie in einen Flashmodus bringen muss, wenn ja wie.

        2) Ich habe mal ein Bild mit esp32-bild-start.jpg dazu gemacht das sehe ich wenn ich auf start drücke die Punkte unten wandern ewig bis sie stehen bleiben . Wie auf anderen Bildern im Netz habe ich unten keinen grünen Fortschrittbalken.
        Irgendwann bleibt es stehen und es steht immer noch groß SYNC im Tool

        3) köönen Sie kurz schreiben wie der Ablauf richtig ist. Ich habe bei dem Tool das ich herunterladen kann auch nicht die Auswahl Flash Size (braucht man vieleicht nicht)

        https://drive.google.com/drive/folders/1cH0GurW_Tm12UeatQcxDnWcqnjsd4oW7

        Danke Frank

        1. Hallo, bei mir klappt es jetzt. Aber nicht auf Anhieb. Das dumme ist, dass ich jetzt nicht mehr genau sagen kann was der entscheidende Schritt war…
          Also beim Flashtool Aufruf habe ich ESP32 und develop gewählt. Und ich habe einmal ERASE gewählt. Ich hatte ein paar mal probiert erst die Boottaste zu drücken, dann den START Button im Flashtool geklickt und dann die Boottaste losgelassen. Ich hatte auch mal die Baudrate im Gerätemanager auf die Baudrate im Flashtool angepasst.
          Das „Problem“ ist: jetzt geht es immer, egal was ich mache….
          Tut mir leid, dass ich genau sagen kann, was es war.

          1. Hallo
            Danke für den Aufwand. Ich werde aufspielen klappt. Nun ist die LED dauernd rot und es zeigt mir kein Wlan Netz an.
            Das werde ich mit anderen Bin Dateien testen
            Gruß Fränki

  7. Hallo Herr Ewald,
    ich programmiere eine Bagger der mithilfe eines ESP32 und L298N. Und benötige eine Pinout Belegung für den WiFi betrieb… können Sie mir hierbei helfen?

    1. Hallo,

      ich gehe davon aus, dass es sich bei dem L298N um eine solches Modul handelt:
      https://smile.amazon.de/ARCELI-ST%C3%9CCKE-Controller-Schrittmodul-Arduino/dp/B07MY33PC9/ref=sr_1_4?crid=3EWW7CAWDU3ER&keywords=ln298n&qid=1649251095&sprefix=ln298%2Caps%2C65&sr=8-4
      Also nicht den blanken L298 IC.

      Ein Tutorial, wie man mit dem L298N Motoren ansteuert, gibt es hier:
      https://funduino.de/nr-34-motoren-mit-h-bruecke-l298n-ansteuern
      Da müssen Sie nur die digitalen Pins durch Pins des ESP32 ersetzen. Und da es kein analogWrite() gibt, müssen Sie das durch PWM ersetzen. Das habe ich ja im Beitrag beschrieben.

      Wie man mit WiFi auf dem ESP32 umgeht, habe ich hier beschrieben:
      https://wolles-elektronikkiste.de/wlan-mit-esp8266-und-esp32
      Dafür braucht man ja keine spezielle Schaltung.
      VG, Wolfgang Ewald

  8. Hallo Herr Ewald,

    zur Zeit versuche ich, aus der Atmel-Arduinowelt (Nano, Uno und Konsorten) auf den ESP32 zu wechseln. Beim Surfen im Netz fällt mir immer wieder auf, dass es Unterschiede im Befehlssatz zwischen beiden Prozessortypen gibt. Sie stellen das in Ihrem Beitrag sehr schön an Beispielen dar. Danke dafür!

    Es sind aber immer nur Beispiele, die man bei der Suche findet. Was mir sehr helfen würde, wäre eine Sammlung aller Befehle, die es speziell für den ESP32 gibt. Haben Sie da vielleicht einen Tipp (Buch, Website, …) für mich?

    Danke & Gruß

    Heiko Bade

  9. Hei,
    im UART (Serial)-Kapitel hat sich – glaube ich – ein Fehlerchen eingeschlichen;
    Serial1 wird auf TX2 gesetzt, muss doch TX1 sein, oder?
    Serial1.begin(115200, SERIAL_8N1, RX1, TX2);


    Stefan

  10. Hallo Herr Ewald,
    die Oszi- Messung bei „Maximale PWM Auflösungen und Frequenzen“ sieht aber eher nach einem Problem mit dem Oszi (zu nahe an der oberen Grenzfrequenz / Tastkopfabgleich?) als nach einem digitalen Ausgang an einem µC aus… 😉
    Grüße, Stefan

    1. Hallo,
      ich habe noch einmal nachgeschaut, bei 20 MHz ist das Signal ein sauberes Rechteck. Bei 40 MHz bekommt es diese eigentümlich Form. Das Oszilloskop schafft nach Herstellerangabe 50 MHz. Dass es bei 40 MHz nicht mehr ganz sauber arbeitet, kann natürlich sein. Herausfinden kann ich es selbst nicht, da ich nur dieses Oszilloskop zu Verfügung habe. Ich habe auch keinen Funktionsgenerator mit dieser Frequenz.
      Falls jemand diesen Kommentar liest, der die Mittel zur Verfügung hat wäre ich für eine Nachmessung dankbar.
      VG, Wolfgang Ewald

      1. Hallo Herr Ewald,
        ich werde es die Tage einmal nachmessen, ich habe Zugriff auf entsprechendes Equipment.
        (Oberlehrer ein 😉 ) Allerdinges ergibt die Messung anhand der Oszi- Eckdaten durchaus Sinn: Wenn die Grenzfrequenz bei 50MHz (Sinus!) liegt, kann das Teil eben kein Rechteck mit 40MHz sauber auflösen, da bereits die erste Oberwelle bei 80MHz liegt… (Oberlehrer aus 😉 )
        Auf alle Fälle war diese Messung für mich sehr hilfreich, da sie mich mit der Nase auf einen Umstand gestoßen hat, den ich erst einmal nicht auf dem Schirm hatte:
        Ich habe mir den ESP32 besorgt, da ich eine RGB- LED- Steuerung realisieren will. Um bei so einer Steuerung bei den LEDs eine für das Auge stufenfreie Dimmung hinzubekommen, braucht man eine 16- Bit- Auflösung bei der PWM, darunter sind Stufen noch gut erkennbar (die 10 Bit beim ESP8266 z.B. reichen definitiv nicht). Wie die sehr schön angegebene Berechnung für die PWM ergibt, liegt die maximale PWM- Frequenz bei 16 Bit Auflösung bei 1,22kHz. Damit liegt dann der kürzeste Impuls bei 40MHz oder bei einer Impulsbreite von 25ns.
        Das muss der für die LED- Leistung zuständige Transistor oder MOSFET erst einmal können!
        Ansonsten besteht die Gefahr, dass man bei größeren Leistungen die Leistungsstufe verheizt, wenn man die PWM- Frequenz zu hoch ansetzt (bin ja froh, dass ich zum Testen mit kleiner Leistung gefahren bin, als ich die PWM- Frequenz auf 1kHz festgelegt hatte, und mich gewundert habe, warum bei PWM 1 nix geleuchtet hat… 😉 ).
        Soweit zu diesem Thema…
        Was ich bisher noch nicht erwähnt habe:
        Danke für diese Seite, sie hat meine Recherchen zum Thema ESP32 um einiges verkürzt… 🙂
        Grüße, Stefan

        1. Vielen Dank nochmal für die Nachmessung! Ich habe den Text geändert und das Bild der guten Messung zugefügt.

  11. Hallo Herr Ewald,
    wir setzen den ESP32 bei uns an der Technikerschule ein.
    Vielen Dank zunächst für die vielen detaillierten und sehr wichtigen Informationen. Ich möchte allerdings noch etwas zur PWM ergänzen bzw. auf einen Fehler in Ihrem Programmcode zur PWM hinweisen.
    Bei der Funktion ledcWrite(CHANNEL, dutycycle) ist zu beachten, dass die maximale Leistung (konstante Gleichspannung) bei einer Auflösung von 8 Bit dann generiert wird, wenn dutycycle = 256 ist. Bei einer 4 Bit-Auflösung muss dutycycle = 16 sein. Das gilt dann entsprechend auch für die anderen Auflösungen. Ich habe das durch Messungen mit dem Oszilloskop überprüft.
    Auch für den ESP32 lässt sich ein PWM-Signal über den Befehl analogWrite generieren. Es muss dazu die Bibliothek „ESP32 AnalogWrite“ by ERROPiX installiert und zu Beginn des Programms
    #include „analogWrite.h“ eingefügt werden. Mit analogWrite(pin, dutycycle) kann dann ein Signal mit der festen Frequenz von 1 kHz und mit einer nicht änderbaren dutycycle-Auflösung von 8 Bit ausgegeben werden. Im Gegensatz zu ledcWrite(CHANNEL, dutycycle) muss für die maximale PWM-Leistung dutycycle = 255 eingegeben werden. Werden größere Werte für dutycycle gewählt, wertet der ESP diese so aus, als wäre der Wert 255.
    Ich wünsche Ihnen einen guten Rutsch in das Jahr 2022!

    1. Vielen Dank, Sie haben absolut recht. Ich habe den Sketch entsprechend abgeändert. VG, Wolfgang Ewald

  12. Ich bin heute erst auf diesen Blog gestoßen und spreche schonmal meine Anerkennung für dieses Schmankerl aus. Hier steckt Enthusiasmus und Liebe an der Materie dahinter… toll!

    Zum ESP – speziell der ESP-01 – ist wirklich ein vielseitig einsetzbarer MCU. Der wurde von mir schon in viele Projekte eingebunden. Vor allem durch den DeepSleep (beim ESP-01 muss ein Pin gelötet werden) sind bei Batterie- oder Akku-Projekten wirklich gigantische Laufzeiten möglich, dazu muss man die RTC noch erwähnen: Das ist der einzige Speicherbereich, der beschrieben und aus dem dann auch nach einem Wake aus DeepSleep noch Variablen ausgelesen werden können. Muss man auch wissen 😉

    1. Vielen Dank für das Feedback und auch für die sinnvollen Anmerkungen – da habe ich auch noch was gelernt!

  13. Erst einmal: Ihre Seite ist sehr hilfreich, übersichtlich und sehr informativ.
    Ich habe Probleme mit dem ESP32. Im Wesentlichen habe ich die Installation so vorgenommen wie von Ihnen beschrieben. Leider lassen sich sowohl in Windows als auch beim Raspberry keine Sketches aufspielen.
    RPI: Beim Hochladen gibt es folgende Fehlermeldung (Arduino IDE 1.8.13). Das Board ist ein ESP32 WROOM 32 (AZ-Delivery).

    Arduino: 1.8.13 (Linux), Board: „ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None“

    Der Sketch verwendet 197736 Bytes (15%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes.
    Globale Variablen verwenden 13084 Bytes (3%) des dynamischen Speichers, 314596 Bytes für lokale Variablen verbleiben. Das Maximum sind 327680 Bytes.
    esptool.py v3.0-dev
    Serial port /dev/ttyAMA0
    Connecting…
    Traceback (most recent call last):
    File „/home/pi/.arduino15/packages/esp32/tools/esptool_py/3.0.0/esptool.py“, line 3682, in

    usw.

    die letzten Zeilen sind
    serial.serialutil.SerialTimeoutException: Write timeout
    Der ausgewählte serielle Port serial.serialutil.SerialTimeoutException: Write timeout
    ist nicht vorhanden oder das Board ist nicht angeschlossen

    Ich habe auch den Boot-Button zu drücken, bis Connect erscheint.

    Alles führt nicht zum Erfolg.
    Das USB-Kabel ist in Ordnung. Mit dem ESP8266 klappt nämlich alles.

    Zur Zeit bin ich ziemlich ratlos. Haben Sie einen Tipp, was ich falsch bzw. nicht durchgeführt habe.

    MfG
    H.Sporenberg

    1. Hallo Herr Sporenberg,
      ich vermute, dass irgendetwas noch nicht richtig installiert ist. Als Erstes würde ich mal schauen, was im Gerätemanager steht, wenn Sie den ESP32 anschließen. Er müsste eigentlich unter „Anschlüsse (COM und LPT)“ als „Silicon Labs CP210x USB to UART Bridge (COMx)“ auftauchen. Wenn dort „unbekanntes Gerät“ oder so etwas steht, dann fehlt der entsprechende Treiber.
      Dann muss in der Arduino IDE die Boardverwalter-URL angegeben sein, d.h. in den Voreinstellungen muss der Eintrag „https://dl.espressif.com/dl/package_esp32_index.json“ stehen. Das Paket für das Board (Werkzeuge – Board – Boardverwalter) scheinen Sie ja installiert zu haben, sonst könnten Sie das BOard nicht auswählen.
      Dann fällt mir nur noch ein zu prüfen, ob es sich wirklich um ein ESP32 Development Board handelt. Es gibt ja eine ganze Anzahl verschiedener ESP32 Boards.
      Vielleicht prüfen Sie das erst einmal und melden sich wieder, wenn all das nichts nützt.
      VG, Wolfgang Ewald

  14. gute erklärungen – auch hier… danke!

    frage zur stromversorgung:
    -3.3V – ok
    -5V über USB auch.
    wie ist es mit 5V am VCC? Geht das? Im netz wird vom Vin geredet, da soll es gehen, aber auf dem D1 mini z.b. gibt’s den Vin ja gar nicht…

    1. Eigentlich habe ich weniger Bedenken am 5V Pin (bei mir heißt er so und nicht VCC) als am 3.3 V Pin. AZ Delivery schreibt in seiner Beschreibung des ESP32 (ESP32 NodeMCU), dass man das Modul nicht über den 3.3 V Pin versorgen darf, da man dann den Spannungsregler von hinten betreibt:
      https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/esp32-das-multitalent

      Ähnliche Aussagen habe ich über den D1 Mini gelesen, z.B. hier:
      https://www.mikrocontroller.net/topic/435178#5143574

      Dann habe ich wieder andere Stellen über den D1 Mini gelesen, dass man doch über 3.3 Volt versorgen kann:
      http://stefanfrings.de/esp8266/
      Da steht sogar explizit, dass man mit 500 mA reingehen kann.

      Also: widersprüchliche Aussagen.

      Wo ich vorsichtig wäre, ist eine gleichzeitige Stromversorgung über den 5 V Pin und USB. Wenn die Spannung am 5 V Eingang doch ein bisschen höher ist, wird könnte das Probleme geben. Wenn das Board ordentlich entworfen ist, dann ist da eine Diode zwischen dem USB 5V und dem 5V Pin. Aber da es so viele verschiedene Boards gibt, bin ich da mit allgemeinen Aussagen lieber vorsichtig.

  15. Ich habe schon einige MQTT-Anwendungen mit dem ESP32 erstellt – aber diese hervorragende Uebersicht eröffnet einige neue Anwendungsfelder. Danke für diese ausgezeichneten und gut verständlichen Ausführungen!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert