ESP32 Projekte – Pollux Labs https://polluxlabs.net Arduino, ESP32 & ESP8266 | Projekte & Tutorials Thu, 19 Sep 2024 18:52:51 +0000 de-DE hourly 1 https://wordpress.org/?v=6.5.5 https://polluxlabs.net/wp-content/uploads/2020/05/cropped-pollux-labs-p-32x32.png ESP32 Projekte – Pollux Labs https://polluxlabs.net 32 32 ESP32 Internetradio https://polluxlabs.net/esp8266-projekte/esp32-internetradio/ Wed, 07 Aug 2024 19:01:34 +0000 https://polluxlabs.net/?p=16902 ESP32 Internetradio Weiterlesen »

]]>
Radio übers Internet zu hören, ist heute natürlich nichts Besonderes mehr – mit einem selbstgebauten ESP32 Internetradio allerdings schon! In diesem Tutorial baust du dir deinen eigenen Empfänger, mit dem du deinen Lieblingssender hören kannst. Das Projekt ist mehrstufig aufgebaut: Zunächst baust du ein einfaches Radio mit einem ESP32-S3 Zero, einem Verstärkermodul und einem Lautsprecher. Anschließend erweiterst du die Stromversorgung und fügst zuletzt noch ein Potentiometer hinzu, das sowohl der Lautstärkeregelung dient als auch dazu, dein Internetradio an- und auszuschalten.

Diese Bauteile benötigst du:

Update: In diesem Tutorial lernst du zunächst, wie du ein Radio baust, das “nur” einen Sender empfängt und abspielt. Weiter unten findest du die Erweiterung für ein ESP32 Internetradio mit Senderwahl und Display.

Aufbau des ESP32 Internetradios

Zunächst, wie angekündigt, die einfachste Schaltung für dein Internetradio. Hierbei benötigst du nur den ESP32-S3 Zero (z.B. von Waveshare), das Verstärkermodul und einen Lautsprecher. Orientiere dich beim Aufbau an folgender Skizze:

Aufbau des einfachsten ESP32 Internetradios

Hier noch einmal als Tabelle:

VerstärkermodulESP32-S3
VIN3,3V
GNDGND
GAINGND
DINGPIO 2
BCLKGPIO 3
LRCGPIO 4

Für deinen Lautsprecher hat das Verstärkermodul eine Buchse, in der du mit einer Schraube die Kabel fixieren kannst. Aufgebaut könnte dein Radio so aussehen:

Foto des ersten ESP32 Internetradios

Der Sketch für das Radio

Zentral für dein Internetradio ist eine Bibliothek, die du nicht im Bibliotheksmanager der Arduino IDE findest – dafür jedoch auf GitHub. Lade dir die Bibliothek als ZIP-Datei hier herunter. Erstelle nun in der Arduino IDE einen neuen Sketch und binde die sie im Menü über Sketch > Bibliothek einbinden > ZIP-Datei hinzufügen ein.

___STEADY_PAYWALL___

Kopiere nun den folgenden Sketch, ergänze die Zugangsdaten für dein WLAN-Netz und lade ihn auf deinen ESP32 hoch. Solltest du hierbei Probleme mit dem ESP32-S3 Zero haben, prüfe, ob du das richtige Board ausgewählt hast. Funktionieren sollte es mit ESP32 S3 Dev Module. Schaue auch nach, ob du im Menü Tools den Eintrag USB CDC On Boot: “Enabled” siehst. Falls dieser auf Disabled steht, ändere ihn entsprechend.

Falls du noch nie einen ESP32 mit der Arduino IDE programmiert hast, wirf zunächst einen Blick dieses Tutorial.

#ESP32 Internetradio
#https://polluxlabs.net

#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"

// Verbindungen ESP32 <-> Verstärkermodul
#define I2S_DOUT  2
#define I2S_BCLK  3
#define I2S_LRC   4

Audio audio;

// WLAN Zugangsdaten
String ssid =    "DEIN NETZWERK";
String password = "DEIN PASSWORT";

void setup() {

  Serial.begin(115200);

  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid.c_str(), password.c_str());

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("");

  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);

  // Lautstärke (0-100)
  audio.setVolume(10);

  // Verbindung zum gewünschten Stream, z.B. Byte.fm
  audio.connecttohost("http://www.byte.fm/stream/bytefm.m3u");

}

void loop()

{
  audio.loop();

}

// Print der Senderinfos

void audio_info(const char *info) {
  Serial.print("info        "); Serial.println(info);
}
void audio_id3data(const char *info) { //id3 metadata
  Serial.print("id3data     "); Serial.println(info);
}
void audio_eof_mp3(const char *info) { //end of file
  Serial.print("eof_mp3     "); Serial.println(info);
}
void audio_showstation(const char *info) {
  Serial.print("station     "); Serial.println(info);
}
void audio_showstreaminfo(const char *info) {
  Serial.print("streaminfo  "); Serial.println(info);
}
void audio_showstreamtitle(const char *info) {
  Serial.print("streamtitle "); Serial.println(info);
}
void audio_bitrate(const char *info) {
  Serial.print("bitrate     "); Serial.println(info);
}
void audio_commercial(const char *info) { //duration in sec
  Serial.print("commercial  "); Serial.println(info);
}
void audio_icyurl(const char *info) { //homepage
  Serial.print("icyurl      "); Serial.println(info);
}
void audio_lasthost(const char *info) { //stream URL played
  Serial.print("lasthost    "); Serial.println(info);
}
void audio_eof_speech(const char *info) {
  Serial.print("eof_speech  "); Serial.println(info);
}

Wenn alles funktioniert, solltest du nach dem Start des ESP32 Internetradios den Sender Byte.fm hören – ein mitgliederfinanzierter Sender aus Hamburg, der abseits des Mainstreams Programmradio macht – ohne Werbung.

So funktioniert der Sketch

Zunächst bindest du wie immer einige Bibliotheken ein. Die ersten beiden sind hierbei bereits in deiner Arduino IDE verfügbar, die Bibliothek Audio.h hast du wie oben beschrieben heruntergeladen und in der IDE eingebunden.

Anschließend definierst du, an welchen Pins das Verstärkermodul am ESP32 angeschlossene ist. Diese kannst du natürlich frei wählen, vergiss nur nicht, sie entsprechend im Sketch zu hinterlegen:

#define I2S_DOUT  2
#define I2S_BCLK  3
#define I2S_LRC   4

Anschließend erstellst du ein Objekt der Audio-Bibliothek und hinterlegst die Zugangsdaten zu deinem WLAN-Netzwerk. In der Setup-Funktion startest du dann den Seriellen Monitor und verbindest den ESP32 mit dem WLAN. Wichtig sind die beiden Zeilen

audio.setVolume(10);
audio.connecttohost("http://www.byte.fm/stream/bytefm.m3u");

In der ersten stellst du die Lautstärke des Streams ein – mit einer Zahl zwischen 0 und 100. Anschließend hinterlegst du die Adresse des Streams, hier also jener von Byte.fm. Wenn du einen anderen Stream abspielen möchtest, wirst du meist recht einfach über eine Suche fündig.

Im Loop gibt es nur eine Funktion: Das Abspielen des Streams. Zuletzt folgen noch einige sogenannte Callback-Funktionen, die aufgerufen werden, wenn ich bestimmtes Ereignis auftritt oder um Informationen auszugeben. Hier sind das z.B. Infos zum Sender oder zum aktuell gespielten Titel, die dann in deinem Seriellen Monitor erscheinen.

erweiterung der Stromversorgung

Aktuell bezieht dein Internetradio bzw. dein ESP32 den Strom von deinem Computer oder vielleicht auch einer Powerbank. In diesem Abschnitt passen wir die Stromversorgung etwas an – entweder mit einem Akku oder zumindest mit dem dazugehörigen Lademodul. An diesem Modul wirst du später ein Poti mit integriertem Schalter anschließen, um damit deinen ESP32 und damit das Radio ein- und ausschalten zu können.

Einen Akku anschließen

Um dein ESP32 Internetradio unabhänging von Kabeln zur Stromversorgung zu machen, kannst du einen Akku samt Lademodul installieren. Ein wichtiger Hinweis jedoch vorab: Falls du keine Erfahrung mit Akkus für Arduino, ESP32 und Co. hast, bleibe bitte doch beim Kabel zu einer externen Stromquelle. Beachte auch auf jeden Fall die Sicherheitshinweise des Herstellers, da bei unsachgemäßem Gebrauch Feuer und sogar Explosionen drohen – für etwaige Schäden übernehme ich keine Gewähr und Haftung.

Falls du jedoch erfahren genug bist, orientiere dich beim Aufbau des ESP32 Internetradios an der folgenden Skizze:

ESP32 Internetradio mit Akkubetrieb

Mit diesem Lademodul kannst du den Akku laden während das Radio läuft. Möchtest du den Akku laden ohne Musik zu hören, installiere noch einen Schalter zwischen dem Lademodul und dem ESP32 – dazu später mehr. Am Sketch ändert sich durch diese Erweiterung nichts.

Nur das Lademodul verwenden

Du wirst dich vielleicht fragen, wozu es gut sein soll, nur das Lademodul für die Stromversorgung zu nutzen – du könntest das benötigte USB-Kabel ja auch weiterhin direkt im ESP32 unterbringen. Das stimmt – aber die abschließende Erweiterung soll ja ein Poti zum Ein- und Ausschalten sowie zur Lautstärkeregelung sein. Damit das am ESP32-S3 funktioniert benötigst du ein Verbindung, die du mit dem Schalter des Potis unterbrechen kannst – und das wird jene zwischen Lademodul und ESP32 sein.

Das in der obigen und in der folgenden Skizze verwendete Lademodul hat für Plus und Minus je zwei Anschlüsse. Einen (das mittlere Paar) für den Akku und einen (das äußere) für die dauerhafte Speisung eines Geräts, in unserem Fall also den ESP32.

Verbinde deinen ESP32 also wie folgt mit dem Lademodul:

ESP32 betrieben mit einem Lademodul

Wenn du nun das Lademodul über USB mit Strom versorgst, erhält auch dein ESP32 hierüber Energie und das Internetradio springt an.

Fehlt noch der letzte Schritt – das Potentiometer.

Das Potentiometer installieren

Hierfür benötigst du kein “Standard”-Poti mit seinen drei Anschlüssen, sondern eines mit fünf Polen. Die äußersten zwei sind hierbei mit einem Schalter auf der Unterseite des Potis verbunden und können einen Stromkreis unterbrechen. In der Praxis drehst du das Poti nach rechts, bis ein Klicken des Schalters ertönt – nun fließt Strom (in unserem Fall springt der ESP32 an).

Drehst du nun weiter, übernimmt das Poti seine übliche Funktion und regelt den Widerstand, den du als Wert im ESP32 auslesen kannst. Orientiere dich beim Aufbau an der folgenden Skizze, wobei dort die oberen zwei Anschlüsse am Poti in der Realität oft die äußeren sind.

ESP32 Internetradio mit Potentiometer zur Lautstärkeregulierung

Wie du siehst, führt der Pluspol des Lademoduls zum Poti und von dort aus wieder zurück aufs Breadboard zu einem Kabel, das mit dem ESP32 verbunden ist. Sobald du das Poti anschaltest, fließt also Strom vom Lademodul zum ESP32.

Erweiterung des Sketchs

Nun ist das Poti zwar installiert und der Ein- und Ausschaltmechanismus funktioniert auch schon. Was jedoch deinem ESP32 Internetradio noch fehlt, ist die Lautstärkeregelung. Hierfür muss der bestehende Sketch um eine Funktion erweitert werden, die den aktuellen Wert des Potis ausliest und auf die Lautstärke des Radio-Streams “mappt”.

Das erreichst du mit dem folgenden Code:

void loop() {
  audio.loop();
  
  int volumeValue = analogRead(VOLUME_PIN);
  int volume = map(volumeValue, 0, 4095, 0, 21);
  audio.setVolume(volume);

Hier liest du das Poti aus, und verwendest die Funktion map(), um dessen Werte von 0 bis 4095 auf eine Lautstärke von 0 bis 21 zu “mappen”. Je weiter du also das Poti aufdrehst, desto lauter wird das Radio – bis ganz rechts der Wert 21 erreicht ist. Hier kannst du auch eine höhere Zahl eintragen, die zu deinem Lautsprecher passt – wie du oben gelesen hast, reicht die Spanne bis 100. Zuletzt übergibst du den gefunden Wert in der Variable volume an die Funktion audio.setVolume().

Das Problem an dieser Methode ist jedoch, dass die Funktion audio.loop(), also der Stream, immer wieder kurz unterbrochen wird. Dies führt zu unangenehmen Rucklern. Deshalb benötigen wir eine etwas ausgefeiltere Methode, um die Lautstärke (mehr oder weniger) unterbrechungsfrei zu gestalten.

Zum einen liest du nur noch alle 500ms den Werte des Potis aus und führst eine Anpassung in audio.setVolume() nur dann aus, wenn sich etwas geändert, du also am Poti gedreht hast. Außerdem glättest du die die Messwerte des Potis rechnerisch, was zu einer etwas sanfteren Anpassung führt.

Wenn du bereits das Poti installiert hast, lade den folgenden Sketch auf deinen ESP32:

#ESP32 Internetradio
#https://polluxlabs.net

#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"

#define I2S_DOUT 2
#define I2S_BCLK 3
#define I2S_LRC 4
#define VOLUME_PIN 5

Audio audio;

const char* ssid = "DEIN NETZWERK";
const char* password = "DEIN PASSWORT";

const int SAMPLES = 5;
int volumeReadings[SAMPLES];
int readIndex = 0;
int total = 0;
int average = 0;
unsigned long lastVolumeCheck = 0;
const unsigned long VOLUME_CHECK_INTERVAL = 500; // Check alle 500ms

void setup() {
  Serial.begin(115200);
  pinMode(VOLUME_PIN, INPUT);

  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

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

  Serial.println("\nWiFi connected");
  Serial.println("IP address: " + WiFi.localIP().toString());

  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
  audio.setVolume(10);
  audio.connecttohost("http://www.byte.fm/stream/bytefm.m3u");

  // Erste Auswertung des Potis
  for (int i = 0; i < SAMPLES; i++) {
    volumeReadings[i] = 0;
  }
}

void loop() {
  audio.loop();
  
  unsigned long currentMillis = millis();
  if (currentMillis - lastVolumeCheck >= VOLUME_CHECK_INTERVAL) {
    lastVolumeCheck = currentMillis;
    
    // Letzten Wert entfernen
    total = total - volumeReadings[readIndex];
    // Werte des Potis auslesen
    volumeReadings[readIndex] = analogRead(VOLUME_PIN);
    // Wert hinzufügen
    total = total + volumeReadings[readIndex];
    // Zum nächsten Wert im Array wechseln
    readIndex = (readIndex + 1) % SAMPLES;

    // Durchschnitt berechnen
    average = total / SAMPLES;
    
    // Geglätteten Wert auf die Lautstärke mappen
    int volume = map(average, 0, 4095, 0, 31);
    
    // NUR wenn am Poti gedreht wurde, die Lautstärke anpassen
    static int lastVolume = -1;
    if (volume != lastVolume) {
      audio.setVolume(volume);
      lastVolume = volume;
      Serial.println("Volume set to: " + String(volume));
    }
  }
}

void audio_info(const char *info) {
  Serial.print("info        "); Serial.println(info);
}
void audio_id3data(const char *info) { //id3 metadata
  Serial.print("id3data     "); Serial.println(info);
}
void audio_eof_mp3(const char *info) { //end of file
  Serial.print("eof_mp3     "); Serial.println(info);
}
void audio_showstation(const char *info) {
  Serial.print("station     "); Serial.println(info);
}
void audio_showstreaminfo(const char *info) {
  Serial.print("streaminfo  "); Serial.println(info);
}
void audio_showstreamtitle(const char *info) {
  Serial.print("streamtitle "); Serial.println(info);
}
void audio_bitrate(const char *info) {
  Serial.print("bitrate     "); Serial.println(info);
}
void audio_commercial(const char *info) { //duration in sec
  Serial.print("commercial  "); Serial.println(info);
}
void audio_icyurl(const char *info) { //homepage
  Serial.print("icyurl      "); Serial.println(info);
}
void audio_lasthost(const char *info) { //stream URL played
  Serial.print("lasthost    "); Serial.println(info);
}
void audio_eof_speech(const char *info) {
  Serial.print("eof_speech  "); Serial.println(info);
}

Nun solltest du dein ESP32 Internetradio mit dem Poti einschalten und kurz darauf – unterbrechungsfrei – Byte.fm hören können.

Umzug auf eine Lochplatine und in das passende Gehäuse

Bis jetzt hast du die Komponenten deines ESP32 Internetradios auf einem Breadboard montiert. Wenn du es jedoch dauerhaft nutzen und es auch optisch etwas aufwerten möchtest, benötigst du ein Gehäuse – und vermutlich auch eine platzsparendere Methode für die Bauteile.

Als Gehäuse bietet sich eine alte Kassettenhülle an, in der du die Technik unterbringen kannst. Mit einer Säge oder Feile kannst du darin Löcher für das Potentiometer und das Ladekabel (falls du keinen Akku benutzt) bohren. Den Lautsprecher kannst du an der Außenseite oder innen anbringen – ganz wie es seine Maße dir ermöglichen.

So könnte anschließend dein ESP32 Internetradio aussehen:

Das Anbringen der Bauteile auf einer Lochplatine erfordert etwas Planung und durchaus fortgeschrittene Kenntnisse im Löten. Überlege dir vorher, wie du den ESP32, den Verstärker etc. anbringen möchtest, sodass du Platz hast für das Poti oder um auf die USB-Buchse zugreifen zu können. Auch die Platzierung des Lautsprechers spielt eine Rolle.

Eine gute Anleitung für das Löten auf einer Lochplatine findest du hier.

Und das war es mit dem “Einsender-Radio”. Aber was, wenn gerade Werbung kommt oder ein Song, den du nicht mehr hören kannst? Dann muss ein Radio mit Senderwahl her. Wie du dein aktuelles Radio damit erweiterst, erfährst du im folgenden Teil dieses Tutorials.

ESP32 Internetradio mit Senderwahl

Damit du an deinem Radio verschiedene Sender einstellen kannst, benötigst du eine geeignete Eingabemöglichkeit. Hierfür eignet sich ein Rotary Encoder* (oder auch Drehgeber). Dieser rastet, anders als ein stufenloses Poti, an festen Positionen ein und sendet einen entsprechenden Impuls an deinen ESP32. Mit jeder Drehung wechselst du dann zum nächsten Radiosender.

Auf deinem Breadboard ist hierfür nur ein kleiner Umbau nötig:

ESP32 Internetradio mit Senderwahl - Aufbau

Wie du siehst, wird der Rotary Encoder (rechts unten) auch vom Lademodul mit Strom versorgt. Die beiden Pins CLK und DT schließt du an die Pins 12 und 13 an.

Die bibliothek für den Rotary Encoder

Damit du die Signale des Rotary Encoders unkompliziert verarbeiten kannst, eignet sich die Bibliothek AiEsp32RotaryEncoder, die du einfach über den Bibliotheksmanager deiner Arduino IDE installieren kannst:

AiEsp32RotaryEncoder in der IDE installieren

Finde deine Lieblingssender

Als nächstes benötigst du eine Liste von Sendern, die dein ESP32 Internetradio abspielen können soll. Hierfür benötigst du die entsprechenden URLs der Streams. Die URL des Senders Byte.fm hast du ja bereits oben kennengelernt. Zusätzliche oder andere Adressen findest du oft ganz einfach über eine Suchmaschine. Suche hierfür zum Beispiel nach dem [Sendername] + Stream URL.

Ich habe in meinem Radio die folgenden vier Sender hinterlegt (als Array, das du gleich im vollständigen Sketch wiedersehen wirst):

const char* stations[] = {
    "http://www.byte.fm/stream/320.m3u", //Byte.fm
    "https://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3", //Deutschlandfunk
    "https://frontend.streamonkey.net/fho-schwarzwaldradiolive/mp3-stream.m3u", //Schwarzwaldradio
    "https://kexp-mp3-128.streamguys1.com/kexp128.mp3" //KEXP
};

Der vollständige Sketch des ESP32 Internetradios mit Senderwahl

Und hier nun der gesamte Sketch zum Herauskopieren und Anpassen:

#ESP32 Internetradio
#https://polluxlabs.net

#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"
#include "AiEsp32RotaryEncoder.h"

#define I2S_DOUT 2
#define I2S_BCLK 3
#define I2S_LRC 4
#define VOLUME_PIN 6

#define ROTARY_ENCODER_A_PIN 12
#define ROTARY_ENCODER_B_PIN 13
#define ROTARY_ENCODER_BUTTON_PIN 14
#define ROTARY_ENCODER_STEPS 4

AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);

Audio audio;

// WiFi credentials
const char* ssid = "DEIN NETZWERK";
const char* password = "DEIN PASSWORT";

// Radio stations
const char* stations[] = {
    "http://www.byte.fm/stream/bytefm.m3u",
    "https://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3",
    "https://frontend.streamonkey.net/fho-schwarzwaldradiolive/mp3-stream.m3u",
    "https://kexp-mp3-128.streamguys1.com/kexp128.mp3"
};
const int NUM_STATIONS = sizeof(stations) / sizeof(stations[0]);
int currentStation = 0;

// Volume control variables
const int SAMPLES = 5;
int volumeReadings[SAMPLES];
int readIndex = 0;
int total = 0;
int average = 0;
unsigned long lastVolumeCheck = 0;
const unsigned long VOLUME_CHECK_INTERVAL = 500; // Check every 500ms

void IRAM_ATTR readEncoderISR() {
    rotaryEncoder.readEncoder_ISR();
}

void setup() {
    Serial.begin(115200);
    pinMode(VOLUME_PIN, INPUT);

    // Rotary Encoder setup
    rotaryEncoder.begin();
    rotaryEncoder.setup(readEncoderISR);
    rotaryEncoder.setBoundaries(0, NUM_STATIONS - 1, true); // circular behavior
    rotaryEncoder.setAcceleration(0); // no acceleration

    WiFi.disconnect();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

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

    Serial.println("\nWiFi connected");
    Serial.println("IP address: " + WiFi.localIP().toString());

    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
    audio.setVolume(10);
    connectToStation(currentStation);

    // Initialize volume readings
    for (int i = 0; i < SAMPLES; i++) {
        volumeReadings[i] = 0;
    }
}

void loop() {
    audio.loop();
    checkVolumeControl();
    checkStationChange();
}

void checkVolumeControl() {
    unsigned long currentMillis = millis();
    if (currentMillis - lastVolumeCheck >= VOLUME_CHECK_INTERVAL) {
        lastVolumeCheck = currentMillis;
        
        total = total - volumeReadings[readIndex];
        volumeReadings[readIndex] = analogRead(VOLUME_PIN);
        total = total + volumeReadings[readIndex];
        readIndex = (readIndex + 1) % SAMPLES;

        average = total / SAMPLES;
        int volume = map(average, 0, 4095, 5, 23);
        
        static int lastVolume = -1;
        if (volume != lastVolume) {
            audio.setVolume(volume);
            lastVolume = volume;
            Serial.println("Volume set to: " + String(volume));
        }
    }
}

void checkStationChange() {
    if (rotaryEncoder.encoderChanged()) {
        int newStation = rotaryEncoder.readEncoder();
        if (newStation != currentStation) {
            currentStation = newStation;
            Serial.println("Changing to station: " + String(currentStation));
            connectToStation(currentStation);
        }
    }
    
    if (rotaryEncoder.isEncoderButtonClicked()) {
        Serial.println("Encoder button clicked");
        // You can add functionality here for when the encoder button is pressed
    }
}

void connectToStation(int stationIndex) {
    audio.stopSong();
    audio.connecttohost(stations[stationIndex]);
    Serial.println("Connected to: " + String(stations[stationIndex]));
}

// Audio status functions
void audio_info(const char *info) {
    Serial.print("info        "); Serial.println(info);
}
void audio_id3data(const char *info) {
    Serial.print("id3data     "); Serial.println(info);
}
void audio_eof_mp3(const char *info) {
    Serial.print("eof_mp3     "); Serial.println(info);
}
void audio_showstation(const char *info) {
    Serial.print("station     "); Serial.println(info);
}
void audio_showstreaminfo(const char *info) {
    Serial.print("streaminfo  "); Serial.println(info);
}
void audio_showstreamtitle(const char *info) {
    Serial.print("streamtitle "); Serial.println(info);
}
void audio_bitrate(const char *info) {
    Serial.print("bitrate     "); Serial.println(info);
}
void audio_commercial(const char *info) {
    Serial.print("commercial  "); Serial.println(info);
}
void audio_icyurl(const char *info) {
    Serial.print("icyurl      "); Serial.println(info);
}
void audio_lasthost(const char *info) {
    Serial.print("lasthost    "); Serial.println(info);
}
void audio_eof_speech(const char *info) {
    Serial.print("eof_speech  "); Serial.println(info);
}

Passe vor dem Upload zunächst wieder die Zugangsdaten für dein WLAN an und trage deine Lieblingssender ein. Wenn du den Sketch auf deinen ESP32 hochgeladen und gestartet hast, solltest du mit dem Rotary Encoder die einzelnen Sender auswählen können. Bei meinen Tests war es beim ersten Umschalten nötig, zweimal zu drehen. Anschließend reichte eine Drehung in die nächste Stellung.

Noch ein Hinweis: Im Sketch oben, ist auch der Button des Rotary Encoders (auf dem Modul oft SW benannt) an Pin 14 hinterlegt. Falls du deinen Drehgeber auch drücken kannst, hast du die Möglichkeit, darüber eine weitere Funktion deiner Wahl in deinem ESP32 Internetradio zu implementieren.

Auf deinem Breadboard könnte das Radio dann so aussehen:

ESP32 Internetradio mit Rotary Encoder auf dem Breadboard

Wie geht es weiter? Zwar erkennst du deine Radiosender vielleicht an der Musik, die dort läuft – ein Display wäre aber sicherlich hilfreich. Darüber könntest du nicht nur den Sendernamen, sondern auch den Song anzeigen, der gerade gespielt wird. Hierfür hilfreiche Funktionen findest du bereits im Sketch oben: void audio_showstreaminfo() zeigt dir den Sendernamen und void audio_showstreamtitle() den aktuellen Song oder den Namen der aktuellen Sendung.

Das Radio um ein OLED-Display erweitern

Nun also zum letzten Baustein deines ESP32 Internetradios – ein kleines Display, auf dem du den abgespielten Sender sowie den aktuellen Musiktitel ablesen kannst. Hierfür eignet sich ein OLED-Display mit 128×32 Pixeln*. Schließe dieses wie folgt an:

ESP32 Internetradio mit OLED-Display

Da sich auf deinem Breadboard (und auf der Skizze oben) mittlerweile eine Menge Kabel tummeln, hier noch mal die Anschlüsse im Detail:

OLED-DisplayESP32-S3 Zero
VCC (3,3V)3,3V
GNDGND
SDA8
SCK/SCL9

Hardwareseitig war es das schon – kommen wir zum Sketch. Hier musst du vor dem Upload allerdings noch eine Kleinigkeit in der Arduino IDE einstellen. Und zwar würde der folgende Sketch den standardmäßig vorgesehenen Speicherplatz auf deinem ESP32 sprengen, wenn du nicht vorab etwas mehr freigeben würdest. Das geht glücklicherweise ganz einfach:

Klicke im Menü Werkzeuge (Tools) auf den Menüpunkt Partition Scheme und wähle die Einstellung Huge APP. Damit hast du nun statt den üblichen 1,2 MB ganze 3 MB zur Verfügung.

Partition Scheme ändern in Huge APP

Nun, wo du genug Speicherplatz auf dem ESP32 hast, kann es mit dem Upload des Sketchs weitergehen. Ein Hinweis noch vorab: Dein ESP32 hat mit all der angeschlossenen Peripherie ganz schön zu tun, weswegen es passieren kann, dass er nicht zuverlässig bootet. Um das zu verhindern, werden im folgenden Sketch das Display, die Verbindung zum WLAN und der Verstärker schrittweise initialisiert. Die Setup-Funktion hingegen ist nun aufgeräumter.

Damit dein Display den richtigen Sendernamen zum jeweiligen Stream anzeigen kann, benötigst du ein Array mit den Namen. Trage dort die Sendernamen in der gleichen Reihenfolge wie im Stream-Array ein:

const char* stationNames[] = {
    "Byte.fm",
    "Deutschlandfunk",
    "Schwarzwaldradio",
    "KEXP",
    "Psychedelic Jukebox"
};

Hier nun der vollständige Sketch:

#ESP32 Internetradio
#https://polluxlabs.net

#include <Arduino.h>
#include <WiFi.h>
#include <Audio.h>
#include <AiEsp32RotaryEncoder.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define I2S_DOUT 2
#define I2S_BCLK 3
#define I2S_LRC 4
#define VOLUME_PIN 6

#define ROTARY_ENCODER_A_PIN 12
#define ROTARY_ENCODER_B_PIN 13
#define ROTARY_ENCODER_BUTTON_PIN 14
#define ROTARY_ENCODER_STEPS 4

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET     -1
#define SCREEN_ADDRESS 0x3C

#define I2C_SDA 8
#define I2C_SCL 9

AiEsp32RotaryEncoder rotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Audio audio;

// WiFi credentials
const char* ssid = "DEIN NETZWERK";
const char* password = "DEIN PASSWORT";

// Radio stations
const char* stations[] = {
    "http://www.byte.fm/stream/bytefm.m3u",
    "https://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3",
    "https://frontend.streamonkey.net/fho-schwarzwaldradiolive/mp3-stream.m3u",
    "https://kexp-mp3-128.streamguys1.com/kexp128.mp3",
    "https://eagle.streemlion.com:2199/tunein/psychedelicj.asx"
};
const char* stationNames[] = {
    "Byte.fm",
    "Deutschlandfunk",
    "Schwarzwaldradio",
    "KEXP",
    "Psychedelic Jukebox"
};

const int NUM_STATIONS = sizeof(stations) / sizeof(stations[0]);
int currentStation = 0;

char streamTitle[64] = "";  // Buffer to store the current stream title

// Volume control variables
const int SAMPLES = 5;
int volumeReadings[SAMPLES];
int readIndex = 0;
int total = 0;
int average = 0;
unsigned long lastVolumeCheck = 0;
const unsigned long VOLUME_CHECK_INTERVAL = 500; // Check every 500ms

// Flags für verzögerte Initialisierung
bool isWiFiConnected = false;
bool isDisplayInitialized = false;
bool isAudioInitialized = false;

void IRAM_ATTR readEncoderISR() {
    rotaryEncoder.readEncoder_ISR();
}

String replaceSpecialChars(String input) {
    input.replace("ä", "ae");
    input.replace("ö", "oe");
    input.replace("ü", "ue");
    input.replace("Ä", "AE");
    input.replace("Ö", "OE");
    input.replace("Ü", "UE");
    input.replace("ß", "ss");
    return input;
}

void setup() {
    delay(1000);  // Kurze Pause für stabilen Start
    Serial.begin(115200);
    while(!Serial) { delay(10); }  // Warte auf Serial-Verbindung
    Serial.println(F("ESP32-S3 Internet Radio startet..."));
    
    pinMode(VOLUME_PIN, INPUT);

    rotaryEncoder.begin();
    rotaryEncoder.setup(readEncoderISR);
    rotaryEncoder.setBoundaries(0, NUM_STATIONS - 1, true);
    rotaryEncoder.setAcceleration(0);

    Serial.println(F("Initialisiere I2C..."));
    Wire.begin(I2C_SDA, I2C_SCL);

    // Initialisiere Volumen-Readings
    for (int i = 0; i < SAMPLES; i++) {
        volumeReadings[i] = 0;
    }
}

void loop() {
    static unsigned long lastInitAttempt = 0;
    const unsigned long initInterval = 5000;  // 5 Sekunden zwischen Initialisierungsversuchen

    // Verzögerte Initialisierung
    if (!isDisplayInitialized && millis() - lastInitAttempt > initInterval) {
        initializeDisplay();
        lastInitAttempt = millis();
    }

    if (!isWiFiConnected && millis() - lastInitAttempt > initInterval) {
        connectToWiFi();
        lastInitAttempt = millis();
    }

    if (isWiFiConnected && !isAudioInitialized && millis() - lastInitAttempt > initInterval) {
        initializeAudio();
        lastInitAttempt = millis();
    }

    // Normale Loop-Funktionalität
    if (isDisplayInitialized && isWiFiConnected && isAudioInitialized) {
        audio.loop();
        checkEncoder();
        checkVolumeControl();
    }

    yield();  // Watchdog füttern
    delay(10);  // Kurze Pause für Stabilität
}

void initializeDisplay() {
    Serial.println(F("Initialisiere OLED Display..."));
    if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
        Serial.println(F("SSD1306 Initialisierung fehlgeschlagen"));
        return;
    }
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0,0);
    display.println(F("Initialisierung..."));
    display.display();
    isDisplayInitialized = true;
    Serial.println(F("OLED Display initialisiert"));
}

void connectToWiFi() {
    Serial.println(F("Verbinde mit WiFi..."));
    WiFi.begin(ssid, password);
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
        delay(500);
        Serial.print(".");
        attempts++;
    }
    if (WiFi.status() == WL_CONNECTED) {
        Serial.println(F("\nWiFi verbunden"));
        isWiFiConnected = true;
        if (isDisplayInitialized) {
            display.clearDisplay();
            display.setCursor(0,0);
            display.println(F("WiFi verbunden"));
            display.display();
        }
    } else {
        Serial.println(F("\nWiFi-Verbindung fehlgeschlagen"));
    }
}

void initializeAudio() {
    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
    audio.setVolume(10);
    connectToStation(currentStation);
    isAudioInitialized = true;
    Serial.println(F("Audio initialisiert"));
}

void checkEncoder() {
    if (rotaryEncoder.encoderChanged()) {
        currentStation = rotaryEncoder.readEncoder();
        connectToStation(currentStation);
    }
    
    if (rotaryEncoder.isEncoderButtonClicked()) {
        Serial.println(F("Encoder-Taste gedrückt"));
        // Hier könnte eine Aktion für den Tastendruck implementiert werden
    }
}

void connectToStation(int stationIndex) {
    audio.stopSong();
    audio.connecttohost(stations[stationIndex]);
    updateDisplay();
}

void checkVolumeControl() {
    unsigned long currentMillis = millis();
    if (currentMillis - lastVolumeCheck >= VOLUME_CHECK_INTERVAL) {
        lastVolumeCheck = currentMillis;
        
        total = total - volumeReadings[readIndex];
        volumeReadings[readIndex] = analogRead(VOLUME_PIN);
        total = total + volumeReadings[readIndex];
        readIndex = (readIndex + 1) % SAMPLES;

        average = total / SAMPLES;
        int volume = map(average, 0, 4095, 5, 23);
        
        static int lastVolume = -1;
        if (volume != lastVolume) {
            audio.setVolume(volume);
            lastVolume = volume;
            Serial.println("Lautstärke eingestellt auf: " + String(volume));
            updateDisplay();
        }
    }
}

void updateDisplay() {
    if (!isDisplayInitialized) return;
    display.clearDisplay();
    display.setCursor(0,0);
    display.println(replaceSpecialChars(String(stationNames[currentStation])));
    display.println();
    display.println(replaceSpecialChars(String(streamTitle)));
    display.display();
    Serial.println(F("Display aktualisiert"));
}

// Audio callback functions
void audio_info(const char *info) { 
    Serial.print("info        "); Serial.println(info);
}
void audio_id3data(const char *info) {
    Serial.print("id3data     "); Serial.println(info);
}
void audio_eof_mp3(const char *info) {
    Serial.print("eof_mp3     "); Serial.println(info);
}
void audio_showstation(const char *info) {
    Serial.print("station     "); Serial.println(info);
}
void audio_showstreaminfo(const char *info) {
    Serial.print("streaminfo  "); Serial.println(info);
}
void audio_showstreamtitle(const char *info) {
    Serial.print("streamtitle: "); Serial.println(info);
    strncpy(streamTitle, info, sizeof(streamTitle) - 1);
    streamTitle[sizeof(streamTitle) - 1] = '\0'; // Ensure null-termination
    updateDisplay();
}
void audio_bitrate(const char *info) {
    Serial.print("bitrate     "); Serial.println(info);
}
void audio_commercial(const char *info) {
    Serial.print("commercial  "); Serial.println(info);
}
void audio_icyurl(const char *info) {
    Serial.print("icyurl      "); Serial.println(info);
}
void audio_lasthost(const char *info) {
    Serial.print("lasthost    "); Serial.println(info);
}
void audio_eof_speech(const char *info) {
    Serial.print("eof_speech  "); Serial.println(info);
}

Nach dem Upload sollte dein ESP32 Internetradio starten (was nun etwas länger dauert) und den ersten Sender in deiner Liste spielen. Auf dem Display erscheint der von dir hinterlegte Sendername und – sofern verfügbar – der Name des Songs oder der Sendung, der oder die gerade läuft.

Und das war es an dieser Stelle. Viel Spaß beim Tüfteln! 🙂

]]>
OpenAI auf dem ESP32 verwenden https://polluxlabs.net/esp8266-projekte/openai-auf-dem-esp32-verwenden/ Thu, 09 May 2024 08:29:15 +0000 https://polluxlabs.net/?p=16436 OpenAI auf dem ESP32 verwenden Weiterlesen »

]]>
Hier bei Pollux Labs gibt es mittlerweile eine Vielzahl von Projekten, die OpenAI bzw. ChatGPT verwenden. Dabei kommt oft der Raspberry Pi und immer die Sprache Python zum Einsatz. Aber es geht auch anders: Wenn du in deinem nächsten Projekt ChatGPT oder auch DALL-E verwenden möchtest, kannst du hierfür auch OpenAI auf dem ESP32 verwenden.

In diesem Tutorial lernst du, wie du deinen ESP32 mit der API von OpenAI kommunizieren lässt, um dir Fragen beantworten und Bilder erstellen zu lassen. Du kommunizierst hierbei über den Seriellen Monitor – deine Fragen bzw. Anweisungen sendest du dabei als Nachricht an deinen ESP32 und erhältst die Antwort wie gewohnt im Textfeld des Monitors.

Für die folgende Anleitung benötigst du einen Account bei OpenAI und einen API-Key. Wie du beides erstellst, erfährst du zu Beginn dieses Tutorials.

Die Bibliothek, um OpenAI zu nutzen

Wie auch für Python gibt es für C++ eine Bibliothek, die du verwenden kannst, um ganz einfach auf die API von OpenAI zugreifen zu können.

___STEADY_PAYWALL___

Diese findest du aktuell jedoch nicht im Bibliotheksverwalter der Arduino IDE, sondern musst sie manuell herunterladen und in deinem Sketch verfügbar machen. Du findest sie auf der GitHub-Seite des Entwicklers Me No Dev. Klicke dort oben auf den grünen Button Code und anschließend auf Download ZIP.

GitHub-Seite der Bibliothek, um OpenAI auf dem ESP32 nutzen zu können

In deiner Arduino IDE kannst du diese Bibliothek dann ganz einfach über das Menü hinzufügen. Klicke hierfür auf Sketch -> Bibliothek einbinden -> ZIP Bibliothek hinzufügen und wähle dann die Datei, die du von GitHub heruntergeladen hast.

so verwendest du ChatGPT auf dem ESP32

Über den Menüpunkt Datei -> Beispiele -> OpenAI-ESP32 kannst du die Beispiel-Sketches finden, die in der Bibliothek enthalten sind. Wähle den Sketch ChatCompletion, der sich nun in einem neuen Fenster öffnen sollte. Trage hier zunächst die Zugangsdaten zu deinem WLAN-Netzwerk sowie deinen API-Key von OpenAI ein:

const char* ssid = "your-SSID";
const char* password = "your-PASSWORD";
const char* api_key = "your-OPENAI_API_KEY";

Etwas weiter unten im Sketch findest du folgende Zeilen:

chat.setModel("gpt-3.5-turbo");   //Model to use for completion. Default is gpt-3.5-turbo
chat.setSystem("Code geek");      //Description of the required assistant
chat.setMaxTokens(1000);          //The maximum number of tokens to generate in the completion.

In der ersten Zeile kannst du das gewünschte Sprachmodell festlegen. Voreingestellt ist GPT-3.5-turbo, mit gpt-4 kannst du jedoch auch das aktuellere Modell verwenden. Darunter kannst du die Rolle von ChatGPT einstellen. Im Beispiel ist das zunächst ein Code geek, aber wie wäre es z.B. mit einem Gärtner oder einem Designer? Deine Einstellung verhindert übrigens keine Antworten, die in einen anderen Wissenbereich fallen. Auch ein Code geek kann dir sagen, warum der Himmel blau ist.

In der nächsten Zeile kannst du einstellen, wie viele Token höchstens für die Antwort verwendet werden dürfen. Damit stellst du sicher, dass die Antworten von ChatGPT nicht zu kostspielig werden. Bei OpenAI findest du die aktuelle Preisliste. Aktuell (Mai 2024) liegst du mit 1000 Token und GPT-4 bei ungefähr 6 Cent.

In den Zeilen darunter findest du weitere Einstellungsmöglichkeiten, die du jedoch hier einmal außer Acht lassen kannst. Sobald du alles eingetragen hast, lade den Sketch auf deinen ESP32 hoch und öffne nach dem erfolgreichen Upload den Seriellen Monitor und stelle, falls nötig, eine Baudrate von 115200 ein.

Nachdem sich dein ESP32 mit deinem WLAN verbunden hat, siehst du die folgende Eingabeaufforderung:

ChatGPT im seriellen Monitor des ESP32

Hier siehst du nun also ChatGPT, das auf deine Frage oder Anweisung wartet. Um mit ChatGPT zu kommunizieren, trage oben im Feld Nachricht deine Frage ein und sende sie mit Enter ab. Testweise habe ich gefragt, warum der Himmel eigentlich blau ist. Und hier die Antwort:

Antwort von ChatGPT im Seriellen Monitor

Deine Frage wird also an die API von OpenAI übermittelt, von ChatGPT beantwortet und die Antwort in deinem Seriellen Monitor ausgegeben. Über ihr findest du die Anzahl der Tokens, die die Antwort verbraucht hat.

Falls du die Antwort nicht nur im Seriellen Monitor ausgeben, sondern zum Beispiel auf einem Display anzeigen möchtest – du findest sie in der Variablen response, die an dieser Stelle im Code befüllt wird:

String response = result.getAt(i);

Bilder mit DALL-E auf dem ESP32 erzeugen

Neben dem Chat kannst du über die API von OpenAI auch DALL-E verwenden, um damit Bilder zeichnen zu lassen. Ein Tutorial, wie du mit Python und DALL-E Bilder erzeugst, findest du übrigens auch bei Pollux Labs.

Auch hierfür verwendest du einen Sketch, der schon als Beispiel mitgeliefert wird. Öffne hierfür wieder Datei -> Beispiele -> OpenAI-ESP32 und wähle dann ImageGeneration. Trage als erstes wieder oben im Sketch deine Zugangsdaten ein. Eine weitere wichtige Stelle befindest sich etwas weiter unten:

imageGeneration.setSize(OPENAI_IMAGE_SIZE_256x256); 

Dort kannst du die Größe des Bilds angeben. Voreingestellt sind 256×256 Pixel, du kannst jedoch auch 512×512 oder 1024×2024 wählen. Im Folgenden habe ich die größte Option gewählt. Laden nun diesen Sketch auf deinen ESP32 und öffne nach dem Upload (und einem evtl. notwendigen Reset des Microcontrollers) wieder deinen Seriellen Monitor. Du erhältst wieder die Aufforderung, einen Prompt zu senden.

Ich habe es einmal mit Zeichne ein Bild eines Mannes auf dem Mond, der auf die Erde schaut – im Ukiyo-e Stil versucht. Als Ergebnis erhältst du ein URL zurück, in der letzten Zeile:

Antwort von DALL-E im Seriellen Monitor

Kopiere die gesamte URL aus dem Seriellen Monitor heraus und öffne sie in deinem Browser. Hier mein Ergebnis:

Das Ergebnis ist vielleicht nicht ganz die große Welle vor Kanagawa, aber okay, es war ja nur ein Versuch. Wie du in diesem Tutorial gesehen hast, ist die API von OpenAI also nicht nur Python und leistungsstärkeren Computern vorbehalten – auch mit einem ESP32 kannst du hier schon einiges erreichen.

]]>
Nachrichten mit dem ESP8266 und ESP32 versenden https://polluxlabs.net/arduino-tutorials/nachrichten-mit-dem-esp8266-und-esp32-versenden/ Mon, 04 Sep 2023 14:15:55 +0000 https://polluxlabs.net/?p=14335 Nachrichten mit dem ESP8266 und ESP32 versenden Weiterlesen »

]]>
Möchtest du mit deinem ESP8266 oder ESP32 Nachrichten verschicken, um zum Beispiel eine Warnung von einem Bewegungsmelder oder Temperatursensor zu erhalten? In diesem Tutorial erfährst du gleich drei Möglichkeiten, wie du das umsetzen kannst – per Telegram, E-Mail und WhatsApp.

Inhalt diese Tutorials

Nachrichten per Telegram senden

Eine gängige Möglichkeit ist es, Nachrichten per Telegram zu senden – genauer gesagt an einen Telegram-Bot. Diese Nachrichten kannst du dann umgehend auf deinem Smartphone lesen. Auf Pollux Labs gibt es einige Projekte, die auf Telegram zurückgreifen, zum Beispiel einen Dash Button oder eine Fotofalle mit der ESP32-CAM. Für letzteres Projekt ist Telegram besonders interessant, denn es ist damit auch möglich, Bilder zu senden.

Zunächst benötigst du einen Telegram-Bot. Wie du diesen im Handumdrehen einrichtest, erfährst du in diesem Tutorial. Außerdem benötigst du die Bibliothek UniversalTelegramBot, die du im Bibliotheksverwalter der Arduino IDE findest. Achte darauf, die neueste Version zu installieren und die Bibliothek aktuell zu halten. Sollte die Version im Bibliotheksverwalter veraltet sein, findest du auf GitHub immer die neueste Version zum Download.

Hier der Beispiel-Sketch für deinen ESP8266. Dieser versendet nach dem Start des Boards eine Nachricht:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Deine WLAN-Zugangsdaten
const char* ssid = "DEIN WLAN-NETZWERK";
const char* password = "DEIN PASSWORT";

// Dein Bot-Token
#define botToken "DEIN TOKEN"  // den Bot-Token bekommst du vom Botfather)

//Deine User ID
#define userID "DEINE USER ID"

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

void setup() {
  Serial.begin(115200);
  client.setInsecure();

  // Verbindung zum WLAN
  Serial.print("Verbinde mit mit: ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("Verbunden!");

  bot.sendMessage(userID, "Hier spricht dein ESP8266.", "");
}

void loop() {
}

Nach dem Upload sollte in deiner Telegram-App folgende Nachricht erscheinen:

Telegram-Nachricht vom ESP8266

So funktioniert der Sketch

Nachdem du die benötigten Bibliotheken eingebunden hast (die zwei ersten sind bereits vorinstalliert), musst du ein paar Daten ergänzen. Das sind deine WLAN-Zugangsdaten sowie dein Bot-Token und deine User-ID. Wenn du die beiden letzteren noch nicht hast, schau dir zunächst unser oben verlinktes Tutorial an.

Anschließend initialisierst du den WifiClient sowie den UniversalTelegramBot mit jeweiligen Instanzen:

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

Im Setup stellst du dann die Verbindung zu deinem WLAN her. Sobald die Verbindung steht, verwendest du die Funktion bot.sendMessage, um eine Nachricht an deinen Telegram-Bot zu senden:

bot.sendMessage(userID, "Hier spricht dein ESP8266.", "");

Der erste Parameter in dieser Funktion ist deine userID, die du zu Beginn des Sketchs hinterlegt hast – gefolgt von der Nachricht, die du senden möchtest. Und das war es im Prinzip auch schon! Du kannst dieses Muster nun für dein Projekt adaptieren, indem du die Nachricht zum Beispiel sendest, wenn eine bestimmte Temperatur überschritten wurde – als Inhalt der Nachricht könnte dann z.B. der aktuelle Messwert dienen.

Mit dem ESP32 eine Telegram-Nachricht senden

Natürlich kannst du statt des ESP8266 auch mit einem ESP32 oder einer ESP32-CAM Nachrichten per Telegram senden. Hierfür musst du nur eine Bibliothek austauschen. Statt ESP8266WiFI.h verwendest du WiFi.h.

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

Und: Um eine korrekte Nachricht zu senden, kannst du noch den Inhalt anpassen. 😉

bot.sendMessage(userID, "Hier spricht dein ESP32.", "");

E-Mails mit dem ESP8266 oder ESP32 versenden

Nach Telegram schauen wir uns den Klassiker der elektronischen Nachrichten an, E-Mails. In diesem Tutorial verwenden wir den Service Gmail, um die E-Mails zu versenden. Auch wenn du schon eine Adresse bei Gmail haben solltest, empfehlen wir fürs Experimentieren auf jeden Fall eine brandneue Mail-Adresse anzulegen. Sollte etwas schief laufen, z.B. eine Kontosperrung, weil dein ESP8266 versehentlich zahllose Mails in kurzer Abfolge versendet, ist deine private Mail-Adresse hiervon nicht betroffen.

___STEADY_PAYWALL___

Um eine neue Adresse anzulegen, rufe zunächst hier Gmail auf und klicke auf Konto erstellen. Sobald dein Konto eingerichtet ist, benötigst du ein App-Passwort, das dein ESP8266 verwenden kann. Um ein App-Passwort anzulegen, öffne dein Google-Konto und klicke auf den Menüpunkt Sicherheit. Klicke anschließend auf den Menü-Punkt Bestätigung in zwei Schritten und folge den Anweisungen, um diese Zwei-Faktor-Authentifizierung zu aktivieren – sie ist nämlich die Voraussetzung für ein App-Passwort.

Sobald du mit der Einrichtung fertig bist, öffne wieder Sicherheit > Bestätigung in zwei Schritten und scrolle ganz nach unten zum Eintrag App-Passwörter. Erstelle nun ein Passwort für E-Mail und wähle als Gerät Andere (benutzerdefinierter Name) aus. Anschließend kannst du einen Namen vergeben, also z.B. ESP8266 oder ESP32.

Das war es zunächst mit den Vorbereitungen, weiter geht es mit einem Beispielsketch, der eine E-Mail an dich versendet.

Eine E-Mail senden

Zunächst benötigst du eine Bibliothek, die du über den Bibliotheksverwalter installieren kannst: ESP Mail Client

Nach der Installation kannst du dich gleich dem Sketch zuwenden. Wir verwenden in diesem Tutorial den Sketch des Blogs RandomNerdTutorials, der ein sehr guter Startpunkt für dieses Thema ist. Im folgenden Sketch musst du nur ein paar Anpassungen machen. Trage an den folgenden Stellen deine Daten ein:

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID" //Dein WLAN-Name
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD" //Dein WLAN-Passwort
#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com" //Deine Absendeadresse (die du bei Gmail angelegt hast)
#define AUTHOR_PASSWORD "YOUR_EMAIL_APP_PASS" //Dein App-Passwort
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com" //Die Empfänger-Adresse

Der gesamte Sketch:

/*
  Rui Santos
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  Example adapted from: https://github.com/mobizt/ESP-Mail-Client
*/

#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

/* The sign in credentials */
#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_APP_PASS"

/* Recipient's email*/
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);

void setup(){
  Serial.begin(115200);
  Serial.println();
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  /*  Set the network reconnection option */
  MailClient.networkReconnect(true);

  /** Enable the debug via Serial port
   * 0 for no debugging
   * 1 for basic level debugging
   *
   * Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h
   */
  smtp.debug(1);

  /* Set the callback function to get the sending results */
  smtp.callback(smtpCallback);

  /* Declare the Session_Config for user defined session credentials */
  Session_Config config;

  /* Set the session config */
  config.server.host_name = SMTP_HOST;
  config.server.port = SMTP_PORT;
  config.login.email = AUTHOR_EMAIL;
  config.login.password = AUTHOR_PASSWORD;
  config.login.user_domain = "";

  /*
  Set the NTP config time
  For times east of the Prime Meridian use 0-12
  For times west of the Prime Meridian add 12 to the offset.
  Ex. American/Denver GMT would be -6. 6 + 12 = 18
  See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
  
  config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
  config.time.gmt_offset = 1;
  config.time.day_light_offset = 0;
  */

  /* Declare the message class */
  SMTP_Message message;

  /* Set the message headers */
  message.sender.name = F("ESP");
  message.sender.email = AUTHOR_EMAIL;
  message.subject = F("ESP Test Email");
  message.addRecipient(F("Sara"), RECIPIENT_EMAIL);
    
  /*Send HTML message*/
  /*String htmlMsg = "<div style=\"color:#2f4468;\"><h1>Hello World!</h1><p>- Sent from ESP board</p></div>";
  message.html.content = htmlMsg.c_str();
  message.html.content = htmlMsg.c_str();
  message.text.charSet = "us-ascii";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;*/

   
  //Send raw text message
  String textMsg = "Hallo Mensch!";
  message.text.content = textMsg.c_str();
  message.text.charSet = "us-ascii";
  message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
  
  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;


  /* Connect to the server */
  if (!smtp.connect(&config)){
    ESP_MAIL_PRINTF("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
    return;
  }

  if (!smtp.isLoggedIn()){
    Serial.println("\nNot yet logged in.");
  }
  else{
    if (smtp.isAuthenticated())
      Serial.println("\nSuccessfully logged in.");
    else
      Serial.println("\nConnected with no Auth.");
  }

  /* Start sending Email and close the session */
  if (!MailClient.sendMail(&smtp, &message))
    ESP_MAIL_PRINTF("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());

}

void loop(){
}

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status){
  /* Print the current status */
  Serial.println(status.info());

  /* Print the sending result */
  if (status.success()){
    // ESP_MAIL_PRINTF used in the examples is for format printing via debug Serial port
    // that works for all supported Arduino platform SDKs e.g. AVR, SAMD, ESP32 and ESP8266.
    // In ESP8266 and ESP32, you can use Serial.printf directly.

    Serial.println("----------------");
    ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());
    ESP_MAIL_PRINTF("Message sent failed: %d\n", status.failedCount());
    Serial.println("----------------\n");

    for (size_t i = 0; i < smtp.sendingResult.size(); i++)
    {
      /* Get the result item */
      SMTP_Result result = smtp.sendingResult.getItem(i);

      // In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
      // your device time was synched with NTP server.
      // Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
      // You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
      
      ESP_MAIL_PRINTF("Message No: %d\n", i + 1);
      ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");
      ESP_MAIL_PRINTF("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
      ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients.c_str());
      ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str());
    }
    Serial.println("----------------\n");

    // You need to clear sending result as the memory usage will grow up.
    smtp.sendingResult.clear();
  }
}

So funktioniert der sketch

Weiter oben hast du bereits die Stellen kennengelernt, die du anpassen musst, damit der Sketch funktioniert. Außerdem kannst du noch deine Zeitzone einstellen, um der E-Mail den richtigen Timestamp zu geben:

  config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
  config.time.gmt_offset = 1;
  config.time.day_light_offset = 0;

Der gmt_offset für Deutschland (also der Abstand zur Greenwich Mean Time) wäre in diesem Beispiel 1 – in der Winterzeit. Im Sommer sind es hingegen 2 Stunden.

Den Betreff und den Absender- bzw. Empfängernamen trägst du hier ein:

  /* Set the message headers */
  message.sender.name = F("ABSENDERNAME");
  message.sender.email = AUTHOR_EMAIL;
  message.subject = F("BETREFF");
  message.addRecipient(F("EMPFÄNGERNAME"), RECIPIENT_EMAIL);

Die eigentliche Nachricht findest du hier:

  //Send raw text message
  String textMsg = "Hallo Mensch!";

Hier kannst du, je nachdem was in deinem eigenen Projekt sinnvoll ist, natürlich auch Variablen mitsenden. Lade den Sketch mit deinen Anpassungen auf deinen ESP8266 oder ESP32. Im Seriellen Monitor kannst du mitverfolgen, wie die E-Mail versendet wird und schließlich im Posteingang deines Empfängers landet.

Der obige Sketch funktioniert sowohl für den ESP8266 als auch für den ESP32. Anpassungen sind beim Wechsel der Boards nicht nötig.

Eine WhatsApp-Nachricht mit dem ESP8266 und ESP32 versenden

Kommen wir zu dritten Möglichkeit, deinen ESP8266 oder ESP32 eine Nachricht versenden zu lassen: WhatsApp. Voraussetzung ist hier ein externer Service. Im Folgenden verwenden wir CallMeBot.com – eine kostenlose API, mit deren Hilfe du WhatsApp-Textnachrichten auf dein Smartphone senden kannst.

Hierfür ist keine aufwändige Registrierung nötig, du musst nur kurz deine Mobilfunknummer bei der API anmelden, um einen API-Key zu erhalten. Über den Link oben kannst du die offizielle Anleitung aufrufen – oder einfach die folgenden Schritte ausführen:

  • Füge über WhatsApp die folgende Nummer deinen Kontakten hinzu (den Kontaktnamen kannst du frei wählen): +34 644 71 81 99
  • Sende anschließend die folgende Nachricht an diese Nummer: I allow callmebot to send me messages
  • Du erhältst daraufhin eine Antwort mit deinem API-Key – und das war’s auch schon

Die Bibliothek zum Codieren der Nachrichten

Auch um Nachrichten per WhatsApp senden zu können, benötigst du eine Bibliothek, die du ganz schnell über den Bibliotheksverwalter installieren kannst: UrlEncode

Diese brauchst du, da die Nachrichten über eine URL übertragen werden – z.B. so:

https://api.callmebot.com/whatsapp.php?phone=+49123123123&text=Dieser+Text+ist+codiert&apikey=123123

Die Bibliothek, die du gleich installierst, übernimmt die Aufgabe, deinen Nachrichten-String in das richtige Format zu bringen. Öffne also den Bibliotheksverwalter und suche nach UrlEncode. Installiere anschließend die neueste Version.

die WhatsApp-Nachricht senden

Hier kommt der vollständige Sketch, um eine WhatsApp-Nachricht mit deinem ESP8266 zu verschicken:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <UrlEncode.h>

const char* ssid = "DEIN WLAN-NETZ";
const char* password = "DEIN WLAN-PASSWORT";

// Deutschland +49, Beispiel: +49176999888777
String phoneNumber = "DEINE MOBILFUNKNUMMER";
String apiKey = "DEIN API-KEY";

void sendMessage(String message) {

  // Daten, die gesendet werden
  String url = "http://api.callmebot.com/whatsapp.php?phone=" + phoneNumber + "&apikey=" + apiKey + "&text=" + urlEncode(message);
  WiFiClient client;
  HTTPClient http;
  http.begin(client, url);

  // Header
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");

  // HTTP Post request senden
  int httpResponseCode = http.POST(url);
  if (httpResponseCode == 200) {
    Serial.print("Message sent successfully");
  } else {
    Serial.println("Error sending the message");
    Serial.print("HTTP response code: ");
    Serial.println(httpResponseCode);
  }

  http.end();
}

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

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  // WhatsApp-Nachricht
  sendMessage("Hier spricht dein ESP8266");
}

void loop() {
}

Zu Beginn des Sketchs hinterlegst du wieder deine WLAN-Zugangsdaten. Außerdem benötigst du deine eigene Mobilfunknummer, die du im internationalen Format (also z.B. für Deutschland mit einem +49 zu Beginn) hinterlegen musst. Zuletzt trägst du noch deinen API-Key ein, den du per WhatsApp-Nachricht empfangen hast:

const char* ssid = "DEIN WLAN-NETZ";
const char* password = "DEIN WLAN-PASSWORT";

// Deutschland +49, Beispiel: +49176999888777
String phoneNumber = "DEINE MOBILFUNKNUMMER";
String apiKey = "DEIN API-KEY";

Alles weitere im Sketch dient der Verbindung zu deinem WLAN und dem API-Request (in der Funktion sendMessage(String message)). Recht weit am Ende kannst du deine Textnachricht eingeben, die gesendet werden soll:

// WhatsApp-Nachricht
sendMessage("Hier spricht dein ESP8266");

Lade den Sketch auf deinen ESP8266. Nach dem Upload sollte innerhalb von wenigen Sekunden die entsprechende Nachricht auf deinem Smartphone erscheinen.

Die WhatsApp-Nachricht mit dem ESP32 senden

Wenn du statt eines ESP8266 einen ESP32 oder eine ESP32-CAM verwenden möchtest, musst du nur ein paar andere Bibliotheken zu Beginn des Sketchs einbinden:

#include <WiFi.h>
#include <HTTPClient.h>
#include <UrlEncode.h>

Den restlichen Sketch kannst du beibehalten ohne weitere Anpassungen. Beachte bitte, dass du mit CallMeBot nur reine Textnachrichten (die natürlich auch Variablen enthalten können) senden kannst. Bilder zu senden, funktioniert mit diesem Service leider nicht. Solltest du das vorhaben, verwende besser Telegram oder schaue dir einmal textmebot.com an – diese API ist allerdings kostenpflichtig.

Fazit

In diesem Tutorial hast du drei Methoden kennengelernt, mit denen du Nachrichten versenden kannst – per Telegram, E-Mail oder WhatsApp. Passende Projekte findest du auf Pollux Labs: Du könntest zum Beispiel die ESP8266 Wetterstation um Warnungen ergänzen, die du erhältst, sobald bestimmte Messwerte über- oder unterschritten werden.

]]>
Video-Livestream mit der ESP32-CAM https://polluxlabs.net/arduino-tutorials/video-livestream-mit-der-esp32-cam/ Fri, 23 Oct 2020 06:23:00 +0000 https://polluxlabs.net/?p=3211 Video-Livestream mit der ESP32-CAM Weiterlesen »

]]>
Mit der ESP32-CAM kannst du einfach und günstig deine Kameraprojekte umsetzen, wie z.B. unsere Fotofalle. Aber es müssen ja nicht immer nur Fotos sein – ein Video-Livestream geht auch!

In diesem Tutorial lernst du, wie du mit deiner ESP32-CAM einen Livestream aufsetzt, den du in deinem Browser aufrufen kannst. Hierfür benötigst du:

Vorbereitungen

Wenn du deine ESP32-CAM noch nie mit der Arduino IDE programmiert hast, musst du sie dort erst verfügbar machen. Da dieses Board keinen eigenen USB-Anschluss hat, benötigst du außerdem eine FTDI-Programmer, um deinen Sketch hochzuladen.

Wie beides funktioniert lernst du in diesem Tutorial hier bei uns. 🙂

Sobald die Verbindung von deinem Computer zur ESP32-CAM steht, kann es weitergehen.

Den Sketch hochladen

Die Konfiguration und das Hochladen des passenden Sketchs fallen in diesem Tutorial ziemlich angenehm aus: er befindet sich nämlich schon in deiner Arduino IDE. Wähle im Menü Datei -> Beispiele -> ESP32 -> Camera -> CameraWebServer. Daraufhin öffnet sich der Sketch, den du benötigst.

Zwei Kleinigkeiten musst du jedoch noch anpassen: Trage zunächst den Namen und das Passwort deines WLAN-Netzwerks ein.

Netzwerkdaten für den Videostream

Außerdem musst du noch das richtige Board auswählen. In unserem Fall (und in den meisten anderen Fällen auch) ist das AI Thinker. Lösche hierfür den Kommentar vor dem Board, sodass nur deines aktiv ist.

Board auswählen für den Video-Livestream

Lade nun den Sketch auf die ESP32-CAM. Vergiss nicht für den Upload die Pins IO0 und GND zu verbinden. Sobald der Code auf dem Board ist, trenne diese Verbindung wieder, starte deinen Seriellen Monitor und drücke zuletzt den RESET-Button auf dem Board.

Den Video-Livestream starten

Nun solltest du nach ein paar Sekunden (zwischenzeitliche Fehlermeldungen machen nichts) folgendes in deinem Seriellen Monitor sehen. Die IP-Adresse kann variieren.

Ausgabe im Seriellen Monitor

Klicke nun auf den Link oder kopiere dir die Adresse heraus und setze sie in deinem Browser ein. Du solltest nun auf der linken Seite eine ganze Reihe von Einstellungsmöglichkeiten sehen. Ganz unten befindet sich der Button Start Stream – ein Klick darauf startet den Stream.

Der Video-Livestream

Und das war es auch schon. Du kannst nun mit den Einstellungen experimentieren, um die bestmögliche Leistung zu erhalten. Außerdem hast du ganz unten auch die Option, eine Gesichtserkennung zu aktivieren, die wir hier jedoch nicht weiter behandeln.

Zwei Hinweise noch: Du kannst den Livestream nur aus deinem eigenen WLAN-Netz aus aufrufen. Dieses Tutorial ist zum Ausprobieren gedacht – wenn du die Kamera produktiv einsetzen möchtest, mache dir vorab Gedanken zur IT-Sicherheit.

]]>
Eine Fotofalle mit der ESP32-CAM und Telegram https://polluxlabs.net/esp8266-projekte/eine-fotofalle-mit-der-esp32-cam-und-telegram/ Sun, 04 Oct 2020 09:43:39 +0000 https://polluxlabs.net/?p=2870 Eine Fotofalle mit der ESP32-CAM und Telegram Weiterlesen »

]]>
ESP32- und ESP8266-Boards sind zusammen mit Telegram eine tolle Kombination. Du kannst Daten blitzschnell auf dein Smartphone senden und von dort aus deinen Microcontroller steuern.

In diesem Projekt baust du eine Fotofalle mit einem speziellen ESP32-Board – der ESP32-CAM. Diese Falle schnappt zu, sobald sich jemand vor der Kamera bewegt. Dann nimmt sie ein Foto auf und sendet es umgehend an dein Smartphone.

Fotofalle mit ESP32-CAM und Telegram

Anfänger

1 Stunde

ca. 25 €

Für dieses Projekt benötigst du (Mengen s. Beschreibung):

Bevor du loslegen kannst, musst du noch ein paar Minuten in Vorbereitungen stecken.

Telegram vorbereiten

Zunächst benötigst du einen Account bei Telegram – und die dazugehörige App für dein Smartphone oder den Computer. Im Folgenden verwenden wir ein Smartphone. Telegram ist kostenlos, werbefrei und funktioniert so ähnlich wie WhatsApp. Allerdings hast du hier die Möglichkeit, Bots zu erstellen, mit denen du interagieren kannst.

In diesem Tutorial auf Pollux Labs lernst du, wie du deinen eigenen Telegram-Bot erstellst.

Die Fotofalle aufbauen

Die ESP32-CAM hat leider keinen USB-Port, weswegen du auf einen FTDI-Adapter zurückgreifen musst, um Sketches hochladen zu können. Wenn du hier noch keine Erfahrung sammeln konntest, informiere dich in diesem Tutorial darüber, wie du die ESP32-CAM programmieren kannst.

___STEADY_PAYWALL___

Wenn du den USB/Serial-Adapter verbunden hast, fehlt nur noch der Bewegungssensor. In diesem Projekt verwenden wir den PIR-Sensor HC-SR501, für den du nur einen Daten-Pin benötigst.

Orientiere dich beim Aufbau an diesem Schema:

Aufbau Fotofalle ESP32-CAM und PIR-Sensor

Hier noch einmal die Verbindungen übersichtlich dargestellt:

FTDI-AdapterESP32-CAM
GNDGND
VCC5V
TXDU0R
RXDU0T
HC-SR501ESP32-CAM
VCC3v3
GNDGND
OUTIO13

Hinweis: Im Schema oben findest du eine Brücke in Grau – denke immer daran, dass du diese benötigst, um einen Sketch hochzuladen. Sobald der Code auf deiner ESP32-CAM ist, trenne die Brücke und drücke den RESET-Button auf dem Board. Erst dann startet dein Sketch.

Das passende Gehäuse

Möchtest du die Fotofalle diskret aufbauen? Oder passt ein Breadboard nicht in das Design des Raums drumherum? Dann sind unsere Gehäuse die richtige Wahl:

Du kannst die .STL Dateien für die Gehäuse hier bei uns herunterladen.

Der Sketch

Für dieses Projekt haben wir einen Sketch von Random Nerd Tutorials als Ausgangspunkt genommen und diesen erweitert. Rui Santos verwendet hier die ESP32-CAM, um bei einer Bewegung ein Foto auf eine SD-Karte zu speichern.

Wir haben den Aufbau und den Code so modifiziert, dass dein Board das Foto an deinen Telegram-Bot, also an dein Smartphone sendet, sobald eine Bewegung erkannt wurde.

Du findest den gesamten Sketch auf Github als .txt und am Ende dieses Artikels.

Wichtige Anpassungen im Code der Fotofalle

Damit der Sketch bei dir funktioniert, musst du ein paar Kleinigkeiten anpassen. Trage zunächst die Zugangsdaten deines WLAN-Netzwerks ein, damit sich die ESP32-CAM damit verbinden kann.

Anschließend benötigst du deinen Token und die UserID, die du beim Erstellen deines Telegram-Bots erhalten hast.

const char* ssid = "NETWORK";
const char* password = "PASSWORD";
String BOTtoken = "TOKEN"; 
String CHAT_ID = "USERID";

Eine Besonderheit, die du nach deinen Wünschen anpassen kannst, ist die Zeit zwischen den Fotos. Im Loop findest du einen delay() von 20 Sekunden. Das ist die Zeitspanne, in der der Bewegungssensor nach einem gesendeten Foto keine weitere Bewegung registriert.

Je kürzer du diese Zeitspanne einstellst, desto mehr Fotos erhältst du – sofern sich weiterhin jemand vor der Kamera bewegt.

Ebenso kannst du die Empfindlichkeit deines HC-SR501 einstellen. An ihm findest du zwei Potis: Wenn du die Platine nach oben drehst, kannst du am linken von ihnen die Empfindlichkeit einstellen. Experimentiere hier ein wenig herum, um die passende Einstellung für dich zu finden.

Die Bibliothek UniversalTelegramBot

Die Bibliothek UniversalTelegramBot.h übernimmt die Kommunikation mit deinem Telegram-Bot. Du findest sie im Bibliotheksverwalter der Arduino IDE – diese kann jedoch veraltet sein. Deshalb empfehlen wir dir, die Bibliothek hier bei uns herunterzuladen.

Anschließend musst du diese Bibliothek in deinen Sketch einbinden, indem du im Menü der Arduino IDE Sketch -> Bibliothek einbinden -> .ZIP-Bibliothek hinzufügen wählst und die gerade heruntergeladene ZIP-Datei auswählst.

Noch ein Hinweis: Dieses Projekt dient dem Ausprobieren. Wenn du die Fotofalle produktiv einsetzen möchtest, mache dir vorab Gedanken über die IT-Sicherheit und achte darauf, keine Persönlichkeitsrechte zu verletzen!

Hier nun der gesamt Sketch zum Rauskopieren:

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/telegram-esp32-cam-photo-arduino/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

  Adapted by Pollux Labs – https://polluxlabs.net
*/

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
#include <UniversalTelegramBot.h>

const char* ssid = "NETWORK";
const char* password = "PASSWORD";

// Initialize Telegram BOT
String BOTtoken = "TOKEN";  // dein Bot-Token vom Botfather)

// Trage hier deine User-ID ein
String CHAT_ID = "CHAT-ID";

bool sendPhoto = false;

WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);

//Pin of the motion sensor
#define PIR_PIN 13

//CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22


void configInitCamera() {
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  //init with high specs to pre-allocate larger buffers
  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;  //0-63 lower number means higher quality
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;  //0-63 lower number means higher quality
    config.fb_count = 1;
  }

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    delay(1000);
    ESP.restart();
  }

  // Drop down frame size for higher initial frame rate
  sensor_t * s = esp_camera_sensor_get();
  s->set_framesize(s, FRAMESIZE_CIF);  // UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
}

String sendPhotoTelegram() {
  const char* myDomain = "api.telegram.org";
  String getAll = "";
  String getBody = "";

  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();  
  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
    return "Camera capture failed";
  }  
  
  Serial.println("Connect to " + String(myDomain));


  if (clientTCP.connect(myDomain, 443)) {
    Serial.println("Connection successful");
    
    String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--RandomNerdTutorials--\r\n";

    uint16_t imageLen = fb->len;
    uint16_t extraLen = head.length() + tail.length();
    uint16_t totalLen = imageLen + extraLen;
  
    clientTCP.println("POST /bot"+BOTtoken+"/sendPhoto HTTP/1.1");
    clientTCP.println("Host: " + String(myDomain));
    clientTCP.println("Content-Length: " + String(totalLen));
    clientTCP.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
    clientTCP.println();
    clientTCP.print(head);
  
    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    for (size_t n=0;n<fbLen;n=n+1024) {
      if (n+1024<fbLen) {
        clientTCP.write(fbBuf, 1024);
        fbBuf += 1024;
      }
      else if (fbLen%1024>0) {
        size_t remainder = fbLen%1024;
        clientTCP.write(fbBuf, remainder);
      }
    }  
    
    clientTCP.print(tail);
    
    esp_camera_fb_return(fb);
    
    int waitTime = 10000;   // timeout 10 seconds
    long startTimer = millis();
    boolean state = false;
    
    while ((startTimer + waitTime) > millis()){
      Serial.print(".");
      delay(100);      
      while (clientTCP.available()) {
        char c = clientTCP.read();
        if (state==true) getBody += String(c);        
        if (c == '\n') {
          if (getAll.length()==0) state=true; 
          getAll = "";
        } 
        else if (c != '\r')
          getAll += String(c);
        startTimer = millis();
      }
      if (getBody.length()>0) break;
    }
    clientTCP.stop();
    Serial.println(getBody);
  }
  else {
    getBody="Connected to api.telegram.org failed.";
    Serial.println("Connected to api.telegram.org failed.");
  }
  return getBody;
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  // Init Serial Monitor
  Serial.begin(115200);

  //Set PIR
  pinMode(PIR_PIN, INPUT);

  // Config and init the camera
  configInitCamera();

  // Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
}

void loop() {
  Serial.println(digitalRead(PIR_PIN));
  if (digitalRead(PIR_PIN)) {
    Serial.println("Preparing photo");
    sendPhotoTelegram();
    delay(20000);
  }
}

Lade den obigen Sketch nun auf deine ESP32-CAM hoch. Achte darauf, dass du die Brücke für den Upload schließt, sie danach wieder öffnest und das Board neustartest mit dem Reset-Button. Im Seriellen Monitor solltest du nun sehen, dass sich das Board mit deinem WLAN verbindet und anschließend auf eine Bewegung wartet – hier sollten in schneller Folge Nullen durch den Seriellen Monitor jagen, bis dein PIR-Sensor eine Bewegung erkannt hat. Daraufhin sendet dir die ESP32-CAM ein Foto der aktuellen Situation an deinen Telegram-Bot.

Mögliche Fehler

Solltest du eine Fehlermeldung im Zusammenhang mit TELEGRAM_CERTIFICATE_ROOT bekommen, lade die aktuelle Version der Bibltiothek UniversalTelegramBot herunter. Möglicherweise ist die Version auf unserem Server bereits veraltet und noch nicht rechtzeitig von uns aktualisiert worden. Auf GitHub findest du die neueste Version – klicke dort rechts oben auf Code und anschließend auf Download ZIP.

]]>
Eine ESP32-CAM (AI Thinker) mit der Arduino IDE programmieren https://polluxlabs.net/arduino-tutorials/eine-esp32-cam-ai-thinker-mit-der-arduino-ide-programmieren/ Fri, 02 Oct 2020 09:08:19 +0000 https://polluxlabs.net/?p=2802 Eine ESP32-CAM (AI Thinker) mit der Arduino IDE programmieren Weiterlesen »

]]>
Du möchtest Fotos aufnehmen und sie auf einer SD-Karte speichern, übers Internet verschicken oder gleich einen Video-Stream einrichten? Dann ist die ESP32-CAM eine tolle Sache! Es gibt da nur einen Umstand: Das Board hat keinen USB-Port. Also was tun?

In diesem Tutorial lernst du, wie du deine ESP32-CAM über einen USB/Serial-Adapter direkt in der Arduino IDE programmierst. Du benötigst hierfür:

Vorbereitungen in der Arduino IDE

Wenn du die ESP32-CAM noch nicht mit deiner Arduino IDE verbunden hast, hole das schnell nach. In diesem Tutorial erfährst du, wie du ESP32-Boards verfügbar machst.

Wenn du das erledigt hast, findest du im Menü Werkzeuge > Board den Eintrag AI Thinker ESP32-CAM – den brauchst du später.

Programmieren über einen Adapter

Da du die ESP32-CAM nicht direkt an deinen Computer anschließen kannst, benötigst du einen Adapter, der die serielle Kommunikation per USB ermöglicht. Diese werden auch FTDI-Adapter genannt – nach dem Unternehmen FTDI, das sich auf diese Anwendungen spezialisiert hat. Ein bisschen wie Tempo also. 🙂

Diese Adapter gibt es in vielen Ausführungen von vielen Herstellern. Oben haben wir dir einen verlinkt, den du zwischen 3,3V und 5V umschalten kannst – was ganz praktisch ist.

Um nun also einen Sketch hochzuladen, verbinde deine ESP32-CAM und den FTDI-Adapter wie folgt:

ESP32-CAM mit FTDI-Adapter programmieren

Hier noch einmal die Verbindungen übersichtlich dargestellt:

FTDI-AdapterESP32-CAM
GNDGND
VCC5V
TXDU0R
RXDU0T

Wichtig: Wenn du einen Sketch hochlädst, musst du an deiner ESP32-CAM den Pin IO0 mit GND verbinden – im Schema oben hellblau dargestellt. Um den Sketch später auszuführen, trenne diese Verbindung wieder und drücke den Reset-Button.

Wenn du den Adapter und die ESP32-CAM wie oben beschrieben miteinander verkabelt hast, verbinde den Adapter mit deinem Computer. Wähle dann in der Arduino IDE das Board AI Thinker ESP32-CAM und den richtigen Port aus und lade deinen Sketch hoch.

Funktioniert nicht?

Der häufigste Fehler ist die fehlende Verbindung zwischen IO0 und GND, die du beim Upload herstellen musst. Wenn du hierfür ein Kabel verwendest, prüfe es auf seine Funktion.

Eine weitere Fehlerquelle kann auch das USB-Kabel sein: Kannst du damit Daten übertragen oder liefert es nur Strom? Manchmal kommt es auch zu Problemen, wenn das Kabel zu lang ist – probiere einfach mal ein anderes.

Wenn der Fehler woanders liegen muss, findest du möglicherweise in der recht umfangreichen Dokumentation bei Random Nerd Tutorials (Englisch) eine Lösung.

]]>
Deinen ESP32 mit der Arduino IDE programmieren https://polluxlabs.net/arduino-tutorials/deinen-esp32-mit-der-arduino-ide-programmieren/ Thu, 01 Oct 2020 13:52:35 +0000 https://polluxlabs.net/?p=2806 Deinen ESP32 mit der Arduino IDE programmieren Weiterlesen »

]]>
Der ESP32 ist so etwas wie der große Bruder des ESP8266. Mit ihm verfügst du nicht nur über WiFi, sondern kannst auch Bluetooth nutzen. Und das beste: Du kannst es ganz einfach mit deiner Arduino IDE programmieren – genauso wie deine Arduino-Boards. Ein paar Vorbereitungen musst du hierfür allerdings treffen.

Lerne hier, wie du in 5 Minuten deinen ESP32 in deiner Arduino IDE installierst und anschließend mit dem Programmieren loslegen kannst.

Dein Board in der Arduino IDE installieren

Öffne zuerst die Einstellungen deiner Arduino IDE. Dort findest du das Feld Zusätzliche Boardverwalter-URLs. Trage hier die folgende Adresse ein:

https://dl.espressif.com/dl/package_esp32_index.json
ESP32 URL in der Arduino IDE eintragen

Tipp: Wenn du dort schon die URL deines ESP8266 eingetragen hast, schreibe die des ESP32 einfach mit einem Komma getrennt dahinter. Dann verfügst du in der Arduino IDE über beide.

Schließe nun das Fenster mit einem Klick auf OK. Öffne als nächstes das Menü Werkzeuge und wähle dort den Menüpunkt Boards und anschließend Boardverwalter.

Suche in dem Fenster, das sich jetzt öffnet, nach ESP32. Vermutlich wirst du dort nur einen Eintrag finden. Noch ein Klick auf Installieren, kurz warten und das sollte es gewesen sein. 🙂

ESP32 im Boardverwalter
Das Paket für deinen ESP32 installieren

Einen Sketch auf den ESP32 hochladen

Schließe nun deinen ESP32 an und wähle im Menü unter Werkzeuge > Board dein Modell und den richtigen Port aus.

Unter Datei > Beispiele findest du unter WiFi den Sketch WiFiScan. Dieser eignet sich für einen ersten Test, denn er macht nichts anderes als die verfügbaren WLAN-Netzwerke in der Umgebung anzuzeigen.

Öffne also diesen Sketch und lade ihn auf deinen ESP32. Nach dem Upload findest du in deinem Seriellen Monitor (115200 Baud) die Netzwerke in der Umgebung.

Funktioniert nicht?

Solltest du beim Upload Probleme haben, probiere folgendes:

Halte den Button BOOT auf deinem ESP32 gedrückt und starte den Upload. Sobald in der Arduino IDE der Status “Connecting…” erscheint, kannst du den Button wieder loslassen. Der Upload sollte jetzt durchlaufen.

]]>
So verwendest du Bluetooth am ESP32 https://polluxlabs.net/arduino-tutorials/so-verwendest-du-bluetooth-am-esp32/ Thu, 30 Jul 2020 07:27:43 +0000 https://polluxlabs.net/?p=1845 So verwendest du Bluetooth am ESP32 Weiterlesen »

]]>
Bluetooth ist allgegenwärtig und auch dein ESP32 kann damit umgehen. Lerne in diesem Tutorial, wie du Bluetooth Classic verwendest und Daten zwischen einem Smartphone und deinem ESP32 austauschst.

Für dieses Tutorial benötigst du nur einen ESP32 und ein Android-Smartphone, auf dem du die kostenfreie App Serial Bluetooth Terminal installieren kannst.

So machst du deinen ESP32 in der Arduino IDE verfügbar

Falls du deinen ESP32 bisher noch nicht mit der Arduino IDE programmiert hast, führe bitte erst die folgenden Schritte durch:

Öffne die Einstellungen der IDE und trage in des Feld Zusätzliche Boardverwalter-URLs folgenden Link ein.

https://dl.espressif.com/dl/package_esp32_index.json

Öffne anschließend den Boardverwalter unter Werkzeuge/Board. Suche dort nach ESP32 und installiere dir die neueste Version des gleichnamigen Pakets von espressif Systems. Und das war es auch schon – du solltest deinen ESP32 nun wie jedes andere Board in der Arduino IDE auswählen und verbinden können.

Der Sketch für deinen ESP32

Für ein grundlegendes Experiment mit Bluetooth benötigst du nur wenig Code:

#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Name des ESP32
  Serial.println("Der ESP32 ist bereit. Verbinde dich nun über Bluetooth.");
}

void loop() {
  if (Serial.available()) {
    SerialBT.write(Serial.read());
  }
  if (SerialBT.available()) {
    Serial.write(SerialBT.read());
  }
  delay(25);
}

Schauen wir uns die wichtigsten Teile genauer an: Zunächst bindest du die Bibliothek BluetoothSerial.h ein, die bereits in deiner Arduino IDE verfügbar ist und nicht extra installiert werden muss. Anschließend erstellst du eine Instanz namens SerialBT.

Im Setup startest du die serielle Kommunikation mit einer Baudrate von 115200 – achte darauf, dass dein Serieller Monitor auch auf diese Rate eingestellt ist. Anschließend initialisierst du Bluetooth und gibst deinem ESP32 den Namen ESP32test.

Im Loop befinden sich zwei Abfragen: Die erste prüft, ob du etwas in den Seriellen Monitor eingetragen und abgeschickt hast.

Wenn das der Fall ist, schickst du die Daten an den ESP32:

SerialBT.write(Serial.read());

In der zweiten Abfrage wird geprüft, ob der ESP32 etwas über Bluetooth empfangen hat. Diese Daten werden dann im Seriellen Monitor ausgegeben.

Ein erster Test

Gehen wir also zur Praxis über. Für diesen Test verbindest du ein Android-Smartphone mit deinem ESP32 und schickst Nachrichten von einem Gerät aufs andere.

Lade zunächst den obigen Sketch wie gewohnt auf deinen ESP32 und starte den Seriellen Monitor mit der Baudrate 115200. Sollte sich hier nichts tun, drücke den Reset- oder Enable-Button am ESP32. Anschließend sollte nach einigen Hardware-Informationen folgender Satz aus deinem Sketch angezeigt werden: Der ESP32 ist bereit. Verbinde dich nun über Bluetooth.

In den Bluetooth-Einstellungen deines Smartphone solltest du nun deinen ESP32 mit dem Namen ESP32test sehen und eine Verbindung herstellen können.

ESP32 mit dem Smartphone pairen

Falls noch nicht geschehen, lade dir die App Serial Bluetooth Terminal aus dem Play Store und öffne sie. Unter dem Menüpunkt Devices/Bluetooth Classic erscheint nun ebenfalls dein ESP32, mit dem du dich mit einem Tap verbinden kannst.

ESP32 im Serial Bluetooth Terminal auswählen

Zeit für etwas Konversation! Schreibe deinem ESP32 in der App eine Nachricht und sende sie ab. Dein Text wird auf der Gegenseite empfangen und im Seriellen Monitor ausgegeben.

Nachricht an einen ESP32 senden

In die andere Richtung funktioniert das genauso. Schreibe etwas in das Eingabefeld oben in deinem Seriellen Monitor und klicke auf Senden. Diese Nachricht wird dann von deinem ESP32 aus an dein Smartphone gesendet und dort angezeigt:

Nachricht vom ESP32 empfangen

Und das war auch schon dein erster Test. Wenn du Nachrichten hin und herschicken kannst, geht das natürlich auch mit allen anderen Daten.

Als nächstes kannst du einen Sensor an den ESP32 anschließen und dessen Daten in regelmäßigen Abständen an dein Smartphone senden. Oder andersherum mit deinem Smartphone z.B. eine LED an deinem Microcontroller an- und ausschalten. Wie du vom Smartphone aus Geräte steuert, lernst du auch in unserem Kurs Dein eigener ESP8266 Webserver.

]]>
MicroPython installieren auf dem ESP8266 & ESP32 https://polluxlabs.net/esp8266-projekte/micropython-installieren-auf-dem-esp8266-esp32/ Tue, 25 Feb 2020 20:52:18 +0000 https://polluxlabs.net/?p=1086 MicroPython installieren auf dem ESP8266 & ESP32 Weiterlesen »

]]>
Hier erfährst du, was MicroPython ist, welche Vorteile dir diese Programmiersprache bietet und wie du sie auf deinem ESP8266* oder ESP32* installierst.

Was ist MicroPython?

MicroPython ist angelehnt an und kompatibel zu Python 3 und speziell für die Programmierung von Microcontrollern ausgelegt. Die Sprache ist dem regulären Python sehr ähnlich – das heißt, wenn du bereits mit Python programmieren kannst, kannst du das auch mit MicroPython.

Da diese Sprache darauf ausgelegt ist, unter eingeschränkten Bedingungen – nämlich auf Microcontrollern mit wenig Speicherplatz – zu arbeiten, besitzt MicroPython nicht alle Bibliotheken von Python. Die für die Programmierung von ESP8266 und ESP32 sind natürlich an Bord – insbesondere jene, die du brauchst, um mit den Pins zu arbeiten und dich mit dem Internet zu verbinden.

Welche Vorteile bietet MicroPython?

Python ist eine Programmiersprache, die sowohl leicht zu lernen als auch leicht zu lesen ist. Das gilt auch für MicroPython – wenn du etwas Python beherrschst und schon auf “richtigen” Computern programmiert hast, fällt dir der Einstieg mit MicroPython leicht. Hier findest du einen Überblick über wichtige Funktion von MicroPython (Englisch).

Weitere Vorteile sind:

  • Du kannst deinen Microcontroller “live” programmieren. D.h. über die Shell (bzw. REPL) kannst du deinen Code direkt testen, ohne erst einen ganzen Sketch hochladen zu müssen.
  • Exception und Error-Handling: Du kannst den Umgang mit Ausnahmen und Fehler bereits in deinem Code definieren.

Aber MicroPython hat auch Nachteile im Vergleich zur Arduino IDE und C, denn hier gibt es für viele Bauteile bereits Bibliotheken, die du einfach installieren, einbinden und verwenden kannst. Mit MicroPython wirst du ab und an etwas länger nach einer geeigneten Lösung suchen müssen.

MicroPython installieren mit der Thonny IDE

Um mit MicroPython auf deinem ESP8266* oder ESP32* loslegen zu können, musst du deinen Microcontroller mit einer passenden Firmware flashen. Hierfür gibt es mehrere Möglichkeiten. Eine recht einfache ist der Editor Thonny IDE. Das Tolle: Thonny ist für Anfänger bestens geeignet und du kannst auch gleich deinen Microcontroller damit programmieren.

Lade dir zunächst die neueste Version von Thonny hier herunter und starte die Installation.

Die Firmware herunterladen

Als nächstes benötigst du die aktuelle Firmware. Diese findest du hier auf der offiziellen Seite von MicroPython. Wähle den entsprechenden Abschnitt für deinen Controller und lade dir die aktuelleste (latest) Version herunter, indem du auf den Dateinamen mit der Endung .bin klickst. Mit dieser Datei flashst du gleich deinen Microcontroller.

Schließe nun deinen Microcontroller wie gewohnt über USB an deinen Computer an. Nun öffne die Thonny IDE.

Klicke als Erstes Menü Run auf Configure interpreter. Dort findest du im Dropdown-Menü mehrere Optionen – auch jeweils eine für den ESP8266 und den ESP32. Wenn du die passende Option gewählt hast, kannst du unter Port or WebREPL den USB-Port wählen, an dem dein Microcontroller angeschlossen ist.

Klicke nun auf den Link unten rechts Install or update MicroPython.

Wähle unter Port noch einmal den richtigen USB-Port aus und wähle unter Firmware die Datei, die du gerade heruntergeladen hast.

Mit einem Klick auf Install geht es los! Auf deinem Microcontroller wird MicroPython installiert. Nach wenigen Sekunden sollte das erledigt sein und du kannst die drei Fenster wieder schließen, bis du wieder auf der Oberfläche der Thonny IDE bist.

So funktioniert MicroPython und die Thonny IDE

Die Oberfläche der Thonny IDE besteht (neben dem Menü) aus zwei Fenstern. Im oberen schreibst du dein Python-Programm, dass über den grünen “Play”-Button auf deinen ESP8266 oder ESP32 hochlädst.

Im unteren Fenster findest du die Shell, mit der quasi in Echtzeit mit deinem Microcontroller interagieren kannst.

Wenn du einen ESP8266 angeschlossen hast, trage hinter die drei >>> in der Shell probeweise – Zeile für Zeile – folgenden Code ein und drücke nach jeder Zeile Enter:

from machine import Pin
Pin(2, Pin.OUT).value(0)

Nun sollte die interne LED auf deinem Controller leuchten. Wenn du in die Klammern hinter value eine 1 einträgst, geht sie wieder aus. Seltsamerweise verhält sich dieser Code beim ESP8266 “falsch herum” – eine 1 schaltet den Pin auf HIGH, eine 0 auf LOW. Beim ESP32 ist das wiederum wie gewohnt.

Wie geht es weiter?

Jetzt hast du das grundlegende Setup, um deinen Microcontroller mit MicroPython zu programmieren. Erforsche als nächstes, was du hiermit alles anstellen kannst! 🙂

Hier findest du ESP8266 Projekte, die du nachbauen oder von denen du dich inspirieren lassen kannst.

Wenn MicroPython doch nicht das Richtige für dich ist, lerne hier CircuitPython kennen.

]]>
Einen ESP8266 oder ESP32 mit dem Internet verbinden https://polluxlabs.net/esp8266-projekte/einen-esp8266-oder-esp32-mit-dem-internet-verbinden/ Wed, 29 Jan 2020 21:36:11 +0000 https://polluxlabs.net/?p=991 Einen ESP8266 oder ESP32 mit dem Internet verbinden Weiterlesen »

]]>
Stoße die Tür zum Internet of Things weit auf! Wenn du für dein Projekt eine Verbindung zum Internet benötigst, leisten dir die beiden Controller ESP8266* und ESP32* gute Dienste. Du benötigst hierfür nur ein WLAN-Netzwerk, die passenden Zugangsdaten und ein paar Zeilen Code.

Bevor du loslegen kannst, musst du deine ESP8266 oder ESP32 in deiner Arduino IDE installieren. Wie das geht, erfährst du in diesem Tutorial auf heise.de.

Die passende Bibliothek

Je nachdem, ob du mit einem ESP8266 oder mit einem ESP32 ins Internet möchtest, brauchst du eine passende Bibliothek. Für ersteren ist das die ESP8266WiFi, für den ESP32 die Bibliothek WiFi.h.

Beide Bibliotheken sollten in deiner Arduino IDE bereits verfügbar sein – sofern du dort dein Board installiert hast. Du kannst sie wie folgt am Anfang deines Sketchs – noch vor der Setup-Funktion – einbinden:

#include <ESP8266WiFi.h>
#include <WiFi.h>

Deine Zugangsdaten

Beide Bibliotheken funktionieren auf ähnliche Art und Weise. Bevor sich dein Controller mit deinem WLAN-Netzwerk verbinden kann, benötigt er die passenden Zugangsdaten. Auch diese legst du am Anfang deines Sketchs zum Beispiel in unveränderlichen Konstanten fest:

const char* ssid = "Name deines WLAN-Netzwerks";
const char* password =  "Dein WLAN-Passwort";

Und ab ins Internet!

Jetzt kann es losgehen. Es gibt mehrere Möglichkeiten, die Verbindung einzurichten und im Seriellen Monitor darzustellen. Zentral ist jedoch immer die Funktion WiFi.begin() und dass diese bestenfalls im Setup deines Sketchs ausgeführt wird, damit für den Loop alles vorbereitet ist.

So könnte der Verbindungsaufbau aussehen:

void setup() {
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Ich verbinde mich mit dem Internet...");
  }
  Serial.println("Ich bin mit dem Internet verbunden!");
}

Zunächst die Funktion WiFi.begin(), der du deine Zugangsdaten als Argumente mitgibst. Der anschließende While Loop wird solange ausgeführt, wie die Verbindung zum Internet noch nicht steht (WiFi.status() != WL_CONNECTED) und schreibt jede Sekunde in den Seriellen Monitor, dass die Verbindung aufgebaut wird. Sobald diese steht, erhältst du die Erfolgsmeldung im Seriellen Monitor.

Und das war’s, du bist drin! 🙂

Spannende Projekte

Jetzt, wo deine Verbindung ins Internet steht, probiere sie doch gleich mal mit diesen Projekten aus:

]]>