ESP32 Wroom

Lese­zeit: 14 Minu­ten

Den ESP32-WROOM gibt es in ver­schie­de­nen Bau­for­men, das abge­bil­de­te Modell hat 38 Pins
Er ver­fügt über Blue­tooth und WiFi.

Board instal­lie­ren

Tra­ge unter Datei -> Ein­stel­lun­gen eine zusätz­li­che Board­ver­wal­ter-URL ein:

https://​dl​.espres​sif​.com/​d​l​/​p​a​c​k​a​g​e​_​e​s​p​3​2​_​i​n​d​e​x​.​j​son

Board aus­wäh­len

  • Icon für den Board­ver­wal­ter ankli­cken oder Wer­k­­­zeu­­­ge-> Board -> Boardverwalter
  • nach ESP32 suchen
  • Board instal­lie­ren

Wenn der ESP32-WROOM nicht auto­ma­tisch erkannt wur­de, kli­cke auf "Wäh­le ein ande­res Board und einen ande­ren Port" und suche nach esp32-wroom. Je nach Betriebs­sys­tem wird der USB-Port eine ande­re Bezeich­nung haben.

Mit Steck­brett verwenden

Lei­der ist der ESP32-Wroom nicht "steck­brett­taug­lich". Ich habe daher zwei Steck­bret­ter zu einem zusam­men­ge­fügt. Es ist wich­tig, dass auf einer Sei­te die Plus- und Minus­leis­te erhal­ten bleibt.

Die opti­ma­le Posi­ti­on auf dem Steckbrett.

Pin­be­le­gung

I2C-Bus

Info

I2C-Pins

22 -> SCL
21 -> SDA

Bei­spiel: Anschluss eines LCD

So sieht es aus:

Das dazu­ge­hö­ri­ge Programm:

Benö­tig­te Biblio­thek installieren

#include "LCDIC2.h"

// 4-zeiliges LCD
LCDIC2 lcd(0x27, 20, 4);

// 2-zeiliges LCD
// LCDIC2 lcd(0x3f, 16, 2);

void setup()
{
  // Zufallsgenerator starten
  randomSeed(analogRead(A0));

  // LCD starten
  lcd.begin();

  // Cursor "verstecken"
  lcd.setCursor(false);

  // Ausgabe auf dem LCD
  // Cursor auf Position 0 in Zeile 0 setzen
  lcd.setCursor(0, 0);
  lcd.print("Zufallszahlen:");
  lcd.setCursor(0, 1);
  for (int i = 1; i <= 6; i++)
  {
    int Zahl =  random(1, 7);
    lcd.print(String(Zahl));
    lcd.print(" ");
  }
}

void loop()
{
  // bleibt leer, Programm läuft nur einmal  
}

SPI-Bus

Info

SPI-Pins

23 -> COPI/SDO
19 -> CIPO/SDI
18 -> CLK
5 -> CS

Schalt­plan mit Adafruit 1,8-Zoll TFT

schwarz - GND
rot -> 5V
gelb - 22
grün -> 2
weiß -> 5
blau -> 23
grau -> 18
rot -> 3,3V oder 5V

Bei­spiel: Demo TFT

// Bibliotheken einbinden
#include "Adafruit_GFX.h"
#include "Adafruit_ST7735.h"

/*
  SPI-Pins
  23 -> COPI/SDO
  19 -> CIPO/SDI (nicht verwendet)
  18 -> CLK
  5 -> CS
*/
#define TFT_CS        5
#define TFT_RST      22
#define TFT_DC        2

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

void setup()
{
  Serial.begin(9600);
  delay(500);
  Serial.println("Bildschirm: " + String(tft.height()) + " x " + String(tft.width()));

  tft.initR(INITR_BLACKTAB);

  // Rotation anpassen
  tft.setRotation(2);

  // schwarzer Hintergrund
  tft.fillScreen(ST7735_BLACK);

  // verschiedene Schriftgrößen
  tft.setTextSize(1);
  tft.setCursor(1, 5);
  tft.setTextColor(ST7735_BLUE);
  tft.print("Text");
  delay(500);

  tft.setTextSize(2);
  tft.setCursor(1, 20);
  tft.setTextColor(ST7735_GREEN);
  tft.print("Text");
  delay(500);

  tft.setTextSize(3);
  tft.setCursor(1, 40);
  tft.setTextColor(ST7735_RED);
  tft.print("Text");
  delay(500);

  tft.setTextSize(4);
  tft.setCursor(1, 70);
  tft.setTextColor(ST7735_YELLOW);
  tft.print("Text");
  delay(2000);

  // Linien ziehen
  tft.fillScreen(ST7735_BLACK);
  for (int i = 1; i < tft.height(); i+=10)
  {
    tft.drawLine(1, i, tft.width(), i, ST7735_ORANGE);
  }
  delay(2000);

  // Kreise zeichnen
  tft.fillScreen(ST7735_BLACK);
  tft.fillCircle(tft.width() / 2, tft.height() / 2, 50, ST7735_MAGENTA);
  tft.fillCircle(tft.width() / 2, tft.height() / 2, 30, ST7735_GREEN);
  tft.fillCircle(tft.width() / 2, tft.height() / 2, 10, ST7735_YELLOW);
  delay(2000);

  // Rechtecke zeichnen
  tft.fillScreen(ST7735_BLACK);
  tft.drawRect(1, 1, 50, 50, ST7735_ORANGE);
  tft.drawRect(5, 5, 50, 50, ST7735_ORANGE);
  tft.drawRect(10, 10, 50, 50, ST7735_ORANGE);
  delay(2000);

  // ausgefüllte Rechtecke zeichnen
  tft.fillScreen(ST7735_BLACK);
  tft.fillRect(5, 5, 50, 50, ST7735_GREEN);
  tft.fillRect(10, 10, 70, 70, ST7735_BLUE);
  tft.fillRect(15, 15, 90, 90, ST7735_RED);
}

void loop()
{
  // nichts zu tun, das Programm
  // läuft nur einmal
}

Touch-Pins

Touch-Pins

32
33
27
14
12
13
4
2
15

Die Touch-Pins reagie­ren auf Ver­än­de­run­gen der Fähig­keit von Kör­pern oder Gegen­stän­den elek­tri­sche Ladung zu spei­chern. Die mensch­li­che Haut ist dazu in der Lage. Wird einer der Touch-Pins berührt, ver­än­dert sich der Messwert.

Bei­spiel:
Schlie­ße ein Kabel am Touch-Pin 32 an.

void setup() 
{
  Serial.begin(9600);
  delay(1000);
}

void loop() 
{
  Serial.print("Wert: ");
  Serial.print(touchRead(32));
  if (touchRead(32) < 20) Serial.println(" -> Pin berührt");
  else Serial.println(" -> Pin nicht berührt");

  delay(1000);
}

Bei­spiel: ⇒Kla­vier mit ESP32-Wroom

Digi­ta­le Pins

Digi­ta­le Pins

rechts
23
22 (I²C)
21 (I²C)
19
18
5
17
16
4
2
15

Das Blink­pro­gramm an Pin 18

int LED = 18;

void setup()
{
  pinMode(LED, OUTPUT);
}

void loop()
{
  digitalWrite(LED, HIGH);
  delay(1000);
  digitalWrite(LED, LOW);
  delay(1000);
}

Ana­lo­ge Pins

Es ste­hen zwei ADC-Wand­ler (Ana­log Digi­tal Con­ver­ter) mit einer Auf­lö­sung von 9 Bit bis 12 Bit zur Ver­fü­gung. Wenn WiFi ver­wen­det wird, kön­nen nur die Pins 32 bis 39 als ana­lo­ge Ein­gän­ge ange­spro­chen wer­den. Das Signal wird in Wer­te zwi­schen 0 und 4095 umgewandelt.

Die Auf­lö­sung des ADC-Wand­lers kann zwi­schen 9-Bit (0 - 511), 10 Bit (0 - 1023), 11 Bit (0 - 2047) und 12 Bit (0 - 4095) Die Stan­dard­ein­stel­lung ist 12 Bit. Die Anwei­sung ana­logRe­ad­Re­so­lu­ti­on() beein­flusst den ADC-Wandler.

Bei­spiel:

void setup() 
{
  Serial.begin(9600);
  analogReadResolution(10);
}

void loop() 
{
  Serial.println("ADC-Wert: " + String(analogRead(35)));
  delay(200);
}

Ana­lo­ge Pins

36
39
34
35
32
33

Bei­spiel:
Poten­tio­me­ter an Pin 35

// Potentiometer an Pin 35
int Potentiometer = 35;

// Variable für den gelesenen Wert
int GelesenerWert = 0;

void setup()
{
  Serial.begin(9600);
  delay(1000);
}

void loop()
{
  // analogen Wert lesen
  GelesenerWert = analogRead(Potentiometer);
  Serial.println(GelesenerWert);
  delay(500);
}

Aus­ga­be im Seri­el­len Plot­ter bei der Dre­hung des Potentiometers

Mit ana­logRe­ad­Mil­li­Volts kann der Wert in Mil­li­volt gele­sen werden.

// Potentiometer an Pin 35
int Potentiometer = 35;

// Variable für den gelesenen Wert
int GelesenerWert;
int milliVolt;

void setup() 
{
  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
}

void loop() 
{
  // Werte lesen
  GelesenerWert = analogRead(Potentiometer);
  milliVolt = analogReadMilliVolts(Potentiometer);

  // oder mit map Wertebereich übertragen
  // milliVolt = map(analogReadMilliVolts(Potentiometer), 0, 3300, 0, 4095);

  // Werte schreiben
  // Titel im Plotter
  Serial.print("Digital:");
  Serial.print(GelesenerWert);

  // mit , abschließen
  Serial.print(",");
  Serial.print("Millivolt:");
  Serial.print(milliVolt);

  // letzter Wert: mit Serial.println und , abschließen
  Serial.println(",");
  delay(500);
}

DAC-Pins

Die Pins 25 und 26 kön­nen mit dac­Wri­te ange­spro­chen wer­den. Das Pro­gramm erhöht die Hel­lig­keit der LED in 5er-Schrit­ten, anschlie­ßend wird die LED gedimmt.

DAC-Pins

25
26

void setup() 
{
  // kein setup notwendig
}

void loop() 
{
  // LED an Pin 25
  // Helligkeit in 5er -Schritten erhöhen
  for (int i = 50; i < 255; i+=5) 
  {
    dacWrite(25, i);
    delay(20);
  }

  // Helligkeit in 5er-Schritten verringern
  for (int i = 255; i > 50; i-=5) 
  {
    dacWrite(25, i);
    delay(20);
  }
}

Blue­tooth BLE

Das Pro­gramm

Zunächst musst du die Biblio­thek Ardui­no­BLE installieren:

Das Pro­gramm schal­tet eine LED an Pin 18:
1 -> ein­schal­ten, 0 -> ausschalten:

#include "ArduinoBLE.h"

/* 
  eindeutige  UUID bestimmen: 
  https://www.guidgenerator.com/online-guid-generator.aspx
  https://www.uuidgenerator.net/
  BLERead | BLEWrite | BLENotify
  -> schreiben, lesen, Info
*/

// Name BLE-Service
BLEService LEDSchalten("19b10000-e8f2-537e-4f6c-d104768a1214");

BLEUnsignedCharCharacteristic Auswahl("19b10000-e8f2-537e-4f6c-d104768a1214", BLERead | BLEWrite | BLENotify);

// LED an Pin 18
int LED = 18;

void setup()
{
  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // pinMode festlegen
  pinMode(LED, OUTPUT);
 
  // BLE starten
  if (!BLE.begin()) Serial.println("Bluetooth-Modul konnte nicht gestartet werden!");
  else Serial.println("Bluetooth-Modul erfolgreich gestartet!");

  // Name festlegen (wird in der App angezeigt) und den Service (LEDSchalten) zuweisen
  BLE.setLocalName("LED schalten");
  BLE.setAdvertisedService(LEDSchalten);

  // Auswahl als Platzhalter für den in der App gewählten Wert
  LEDSchalten.addCharacteristic(Auswahl);

  // Service LEDSchalten hinzufügen
  BLE.addService(LEDSchalten);

  // Startwert für die Kommunikation schreiben
  Auswahl.writeValue(0);

  // Zuweisung starten
  BLE.advertise();
}

void loop()
{
  // auf die Verbindung zu Geräten warten
  BLEDevice Verbindung = BLE.central();

  // wenn der ESP32 mit einem Gerät verbunden ist ...
  if (Verbindung)
  {
    Serial.println("Verbunden ... ");

    // solange der Controller mit einem Gerät verbunden ist ...
    while (Verbindung.connected())
    {

      if (Auswahl.written())
      {
        // LED einschalten
        if (Auswahl.value() == '1')
        {
          Serial.print(char(Auswahl.value()));
          Serial.println(" -> LED ein");
          digitalWrite(LED, HIGH);
        }

        // LED ausschalten
        if (Auswahl.value() == '0')
        {
          Serial.print(char(Auswahl.value()));
          Serial.println(F(" -> LED aus"));
          digitalWrite(LED, LOW);
        }    
      }
    }
  }
}

Smart­phone-Apps

Light­Blue (iOS Android)

Android zeigt als Name LED schalten

BLE Ter­mi­nal (Android: Inno­va­tors Den)

ESP32 BLE Ter­mi­nal (iOS)

BLE Ter­mi­nal (iOS)

Blue­tooth­LE (iOS)

Zeit mit der Biblio­thek time.h anzeigen

ESP32-Mikro­con­trol­ler kön­nen mit der Stan­dard­bi­blio­thek Datum und Zeit anzeigen.

Bei­spiel: ⇒Anzei­ge von Datum und Zeit auf einem OLED-Display

#include "WiFi.h"
#include "time.h"

char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

// NTP-Server aus dem Pool
#define Zeitserver "de.pool.ntp.org"

/*
  Liste der Zeitzonen
  https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
  Zeitzone CET = Central European Time -1 -> 1 Stunde zurück
  CEST = Central European Summer Time von
  M3 = März, 5.0 = Sonntag 5. Woche, 02 = 2 Uhr
  bis M10 = Oktober, 5.0 = Sonntag 5. Woche 03 = 3 Uhr
*/
#define Zeitzone "CET-1CEST,M3.5.0/02,M10.5.0/03"

// time_t enthält die Anzahl der Sekunden seit dem 1.1.1970 0 Uhr
time_t aktuelleZeit;

/* 
  Struktur tm
  tm_hour -> Stunde: 0 bis 23
  tm_min -> Minuten: 0 bis 59
  tm_sec -> Sekunden 0 bis 59
  tm_mday -> Tag 1 bis 31
  tm_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  tm_mon -> Monat: 0 (Januar) bis 11 (Dezember)
  tm_year -> Jahre seit 1900
  tm_yday -> vergangene Tage seit 1. Januar des Jahres
  tm_isdst -> Wert > 0 = Sommerzeit (dst = daylight saving time)
*/
tm Zeit;
WiFiServer Server(80);
WiFiClient Client;

void setup() 
{
  // Zeitzone: Parameter für die zu ermittelnde Zeit
  configTzTime(Zeitzone, Zeitserver);

  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // WiFi starten
  WiFi.begin(Router, Passwort);

  Serial.println("------------------------");
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(200);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Verbunden mit ");
  Serial.println(Router);
  Serial.print("IP über DHCP: ");
  Serial.println(WiFi.localIP());
}

void loop() 
{
  // aktuelle Zeit holen
  time(&aktuelleZeit);

  // localtime_r -> Zeit in die lokale Zeitzone setzen
  localtime_r(&aktuelleZeit, &Zeit);

  Serial.println("------------------------");

  // es kann bis zu 30 Sekunden dauern
  // bis die Zeit ermittelt wird
  // Name des Wochentages 0-6
  switch (Zeit.tm_wday)
  {
    case 0:
      Serial.print("Sonntag");
      break;
    case 1:
      Serial.print("Montag");
      break;   
   case 2:
      Serial.print("Dienstag");
      break;
   case 3:
      Serial.print("Mittwoch");
      break;
   case 4:
      Serial.print("Donnerstag");
      break;
   case 5:
      Serial.print("Freitag");
      break;
   case 6:
      Serial.print("Samstag");
      break;
  }

  Serial.print(",");
  if (Zeit.tm_mday < 10)  Serial.print("0");
  Serial.print(Zeit.tm_mday);
  Serial.print(".");

  // Monat: führende 0 ergänzen
  // Zählung beginnt mit 0 -> +1
  if ((Zeit.tm_mon + 1) < 10) Serial.print("0");

  Serial.print(Zeit.tm_mon + 1);
  Serial.print(".");

  // Anzahl Jahre seit 1900
  Serial.print(Zeit.tm_year + 1900);
  Serial.print(" ");

  // Stunde: wenn Stunde < 10 -> 0 davor setzen
  if (Zeit.tm_hour < 10) Serial.print("0");
  Serial.print(Zeit.tm_hour);
  Serial.print(":");

  // Minuten
  if (Zeit.tm_min < 10) Serial.print("0");
  Serial.print(Zeit.tm_min);
  Serial.print(":");

  // Sekunden
  if (Zeit.tm_sec < 10) Serial.print("0");
  Serial.print(Zeit.tm_sec);

  Serial.println();
  Serial.println("Tage seit dem 1.1. " + String(Zeit.tm_yday));

  // Normalzeit/Sommerzeit
  if(Zeit.tm_isdst > 0) Serial.println("MESZ = Mitteleuropäische Sommerzeit");
  else Serial.println("MEZ = Mitteleuropäische Zeit");
  delay(5000);
}

Web­ser­ver

Bei­spiel

Das Pro­gramm zeigt im Brow­ser 6 Zufalls­zah­len an.
Im Seri­el­len Moni­tor wird die mit DHCP ermit­tel­te IP des ESP32-Wroom angezeigt.

Die­se Adres­se musst du in einem Brow­ser dei­ner Wahl eingeben

Cli­ent-Metho­de

#include "WiFi.h"

char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

WiFiServer Server(80);
WiFiClient Client;

// Minimum und Maximum der Zufallszahlen
int Minimum = 1;
int Maximum = 49;

// statischeIP = false -> IP-Adresse über DHCP vergeben
// statischeIP = true -> statische IP festlegen
bool statischeIP = false;

// ip und gateway müssen an das lokale Netz angepasst werden
IPAddress ip(192, 168, 1, 100);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

void setup() 
{
  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);

  // WiFi starten
  WiFi.begin(Router, Passwort);

 // statische IP vergeben
  if (statischeIP) 
  {
    WiFi.config(ip, gateway, subnet); 
    Serial.print("Verbunden mit ");
    Serial.println(Router);

    // IP anzeigen
    Serial.print("Statische IP: ");
    Serial.println(ip);
  }

  // IP über DHCP ermitteln
  else
  {
    while (WiFi.status() != WL_CONNECTED) 
    {
      delay(200);
      Serial.print(".");
    }
    Serial.println();
    Serial.print("Verbunden mit ");
    Serial.println(Router);
    Serial.print("IP über DHCP: ");
    Serial.println(WiFi.localIP());
  }

  Server.begin();

  // SSID des Routers anzeigen
  Serial.println();
  Serial.print("Verbunden mit ");
  Serial.println(WiFi.SSID());

  // IP anzeigen
  Serial.println(WiFi.localIP());

  // Zufallsgenerator mit dem Signal an A0 starten
  randomSeed(analogRead(A0));
}

void loop() 
{
  Client = Server.available();
  if (Client) 
  {
    // Seite aufbauen wenn SeiteAufbauen true ist
    boolean SeiteAufbauen = true;

    // solange der Client verbunden ist ...
    while (Client.connected()) 
    {
      if (Client.available()) 
      {
        // Anforderung vom Clienten lesen ...
        char Zeichen = Client.read();

        // return (\n) gesendet
        if (Zeichen == '\n') 
        {
          // wenn SeiteAufbauen den Wert true hat
          if (SeiteAufbauen) 
          {
            /*
              HTML-Seite aufbauen
              die folgenden Anweisungen müssen
              mit print oder println gesendet werden
              println "verschönert" den Quelltext
              (erzeugt einen Zeilenumbruch im Quelltext)
            */

            // HTML-Seite aufbauen
            Client.println("HTTP/1.1 200 OK");
            Client.println("Content-type:text/html");

            // Leerzeile zwingend erforderlich
            Client.println();

            Client.println("<!doctype html>");
            Client.println("<html>");
            Client.println("<body>");

            // alle 60 Sekunden aktualisieren mit meta-Tag
            Client.println("<meta http-equiv=\"refresh\" content=\"60\">");
            
            // <h2> Überschrift H2
            Client.println("<h2>Zufallszahlen</h2>");

            // <hr> horizontale Linie
            Client.println("<hr>");
            
            // Zufallszahlen anzeigen
            for (int i = 0; i < 7; i++ )
            {
              int Zahl = random(Minimum, Maximum);
              Client.println(Zahl);
              Client.println(" ");
            }

            Client.print("<hr>");

            // Seite schließen
            Client.println("</body>");
            Client.println("</html>");

            // HTTP-Antwort endet mit neuer Zeile
            Client.println();

            // Seite vollständig geladen -> loop verlassen
            break;
          }

          // wenn new line (\n) gesendet wurde -> Seite aufbauen
          if (Zeichen == '\n') SeiteAufbauen = true;

          else if (Zeichen != '\r') SeiteAufbauen = false;
          delay(1);
          Client.stop();
        }
      }
    }
  }
}

Server.on -Metho­de

#include "WiFi.h"
#include "WebServer.h"

// SSID und Passwort des Routers
char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";

WebServer Server(80);

// Minimum und Maximum der Zufallszahlen
int Minimum = 1;
int Maximum = 49;

// statischeIP = false -> IP-Adresse über DHCP vergeben
// statischeIP = true -> statische IP festlegen
bool statischeIP = false;

// ip und gateway müssen an das lokale Netz angepasst werden
IPAddress ip(192, 168, 1, 100);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

void setup() 
{
  Serial.begin(9600);

  // auf serielle Verbindung warten
  while (!Serial);
  delay(1000);

  // WiFi starten
  WiFi.begin(Router, Passwort);

  // statische IP vergeben
  if (statischeIP) 
  {
    WiFi.config(ip, gateway, subnet); 
    Serial.print("Verbunden mit ");
    Serial.println(Router);

    // IP anzeigen
    Serial.print("Statische IP: ");
  }

  // IP über DHCP ermitteln
  else
  {
    while (WiFi.status() != WL_CONNECTED) 
    {
      delay(200);
      Serial.print(".");
    }
    Serial.println();
    Serial.print("Verbunden mit ");
    Serial.println(Router);
    Serial.print("IP über DHCP: ");
  }

  // IP anzeigen
  Serial.println(WiFi.localIP());

  // Zufallsgenerator mit dem Signal an A0 starten
  randomSeed(analogRead(A0));

  Server.begin();
  Server.on("/", SeiteBauen);
}

void loop() 
{
  Server.handleClient();
}

void SeiteBauen() 
{
  // Seite zusammenbauen
  // Kopf der HTML-Seite: aktualisierung alle 60 Sekunden
  // kann angepasst werden
  String Nachricht = "<head><meta http-equiv=\"refresh\" content=\"60\"></head>";
  Nachricht += "<h1>Zufallszahlen</h1>";
  Nachricht += "<hr>";

  // Zufallszahlen anzeigen
  for (int i = 0; i < 7; i++) 
  {
    int Zahl = random(Minimum, Maximum);
    Nachricht += String(Zahl) + " ";
  }

  Nachricht += "<hr>";

  // Nachricht senden -> Seite anzeigen
  Server.send(200, "text/html", Nachricht);
}

WiFI-Daten auf dem ESP32 speichern


Letzte Aktualisierung: Jan. 6, 2025 @ 18:29