1 min read
IoTESP32 Development mit PlatformIO
ESP32 Entwicklung mit PlatformIO. WiFi, Sensoren, MQTT Integration und OTA Updates für IoT-Projekte.
ESP32PlatformIOArduinoIoTWiFiMQTT

ESP32 Development mit PlatformIO
Meta-Description: ESP32 Entwicklung mit PlatformIO. WiFi, Sensoren, MQTT Integration und OTA Updates für IoT-Projekte.
Keywords: ESP32, PlatformIO, Arduino, IoT, WiFi, MQTT, Sensors, Embedded Development
Einführung
Der ESP32 ist der vielseitigste Microcontroller für IoT-Projekte. Mit WiFi, Bluetooth, dualen Cores und zahlreichen GPIOs – kombiniert mit PlatformIO als moderne Entwicklungsumgebung.
ESP32 Overview
┌─────────────────────────────────────────────────────────────┐
│ ESP32 ARCHITECTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ CPU: Xtensa dual-core 32-bit LX6 @ 240MHz │
│ │
│ Memory: │
│ ├── 520 KB SRAM │
│ ├── 4 MB Flash (external) │
│ └── 448 KB ROM │
│ │
│ Connectivity: │
│ ├── WiFi 802.11 b/g/n (2.4 GHz) │
│ ├── Bluetooth 4.2 + BLE │
│ └── Multiple SPI, I2C, UART, I2S │
│ │
│ GPIO: │
│ ├── 34 GPIO Pins │
│ ├── 18 ADC Channels (12-bit) │
│ ├── 2 DAC Channels (8-bit) │
│ ├── 16 PWM Channels │
│ └── 10 Touch Sensors │
│ │
│ Power: │
│ ├── Operating Voltage: 3.3V │
│ ├── Deep Sleep: ~10µA │
│ └── Active WiFi: ~160mA │
│ │
│ Peripherals: RTC, Timers, Watchdog, Hall Sensor │
│ │
└─────────────────────────────────────────────────────────────┘PlatformIO Setup
# VS Code Extension installieren
# Extensions → PlatformIO IDE
# Oder CLI Installation
pip install platformio
# Neues Projekt erstellen
pio project init --board esp32dev --ide vscode; platformio.ini
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
upload_speed = 921600
; Build Flags
build_flags =
-DCORE_DEBUG_LEVEL=3
-DCONFIG_ARDUHAL_LOG_COLORS=1
; Libraries
lib_deps =
bblanchon/ArduinoJson@^7.0.0
knolleary/PubSubClient@^2.8
adafruit/DHT sensor library@^1.4.6
adafruit/Adafruit Unified Sensor@^1.1.14
; OTA Updates
upload_protocol = espota
upload_port = 192.168.1.100
; Filesystem
board_build.filesystem = littlefs
; Partitions
board_build.partitions = min_spiffs.csvWiFi Connection
// src/main.cpp
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiManager.h>
// Credentials (besser: WiFiManager oder NVS)
const char* ssid = "YourNetwork";
const char* password = "YourPassword";
// Status LED
const int LED_PIN = 2;
void setupWiFi() {
Serial.println("Connecting to WiFi...");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 30) {
delay(500);
Serial.print(".");
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Blink
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.print("RSSI: ");
Serial.println(WiFi.RSSI());
digitalWrite(LED_PIN, HIGH);
} else {
Serial.println("\nWiFi connection failed!");
// Fallback: AP Mode für Konfiguration
startConfigPortal();
}
}
void startConfigPortal() {
WiFiManager wifiManager;
// Reset settings for testing
// wifiManager.resetSettings();
// Custom Parameters
WiFiManagerParameter mqtt_server("mqtt", "MQTT Server", "mqtt.local", 40);
wifiManager.addParameter(&mqtt_server);
// Auto-connect oder Config Portal
if (!wifiManager.autoConnect("ESP32-Setup", "password123")) {
Serial.println("Failed to connect, restarting...");
delay(3000);
ESP.restart();
}
Serial.println("Connected via WiFiManager!");
Serial.println(mqtt_server.getValue());
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
setupWiFi();
}
void loop() {
// WiFi Reconnect
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi lost, reconnecting...");
setupWiFi();
}
delay(1000);
}Sensor Reading (DHT22)
// src/sensors.cpp
#include <DHT.h>
#include <ArduinoJson.h>
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
struct SensorData {
float temperature;
float humidity;
float heatIndex;
bool valid;
};
SensorData readDHT22() {
SensorData data = {0, 0, 0, false};
// Mehrere Versuche für zuverlässige Messung
for (int i = 0; i < 3; i++) {
data.temperature = dht.readTemperature();
data.humidity = dht.readHumidity();
if (!isnan(data.temperature) && !isnan(data.humidity)) {
data.heatIndex = dht.computeHeatIndex(
data.temperature,
data.humidity,
false // Celsius
);
data.valid = true;
break;
}
delay(2000); // DHT braucht Zeit zwischen Messungen
}
return data;
}
String sensorDataToJson(const SensorData& data) {
JsonDocument doc;
doc["device_id"] = WiFi.macAddress();
doc["timestamp"] = millis();
doc["temperature"] = round(data.temperature * 10) / 10.0;
doc["humidity"] = round(data.humidity * 10) / 10.0;
doc["heat_index"] = round(data.heatIndex * 10) / 10.0;
doc["valid"] = data.valid;
doc["rssi"] = WiFi.RSSI();
String output;
serializeJson(doc, output);
return output;
}
void setup() {
Serial.begin(115200);
dht.begin();
// Warm-up Zeit
delay(2000);
}
void loop() {
SensorData data = readDHT22();
if (data.valid) {
String json = sensorDataToJson(data);
Serial.println(json);
} else {
Serial.println("Sensor read failed!");
}
delay(10000); // Alle 10 Sekunden
}MQTT Integration
// src/mqtt_client.cpp
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
const char* mqtt_server = "mqtt.example.com";
const int mqtt_port = 1883;
const char* mqtt_user = "esp32";
const char* mqtt_pass = "secret";
WiFiClient espClient;
PubSubClient mqtt(espClient);
String deviceId;
String baseTopic;
void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.printf("Message [%s]: ", topic);
// Payload zu String
String message;
for (unsigned int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println(message);
// JSON parsen
JsonDocument doc;
if (deserializeJson(doc, message) == DeserializationError::Ok) {
handleCommand(doc);
}
}
void handleCommand(const JsonDocument& doc) {
const char* action = doc["action"];
if (strcmp(action, "restart") == 0) {
Serial.println("Restart command received");
ESP.restart();
}
else if (strcmp(action, "led") == 0) {
bool state = doc["state"];
digitalWrite(LED_BUILTIN, state);
Serial.printf("LED: %s\n", state ? "ON" : "OFF");
}
else if (strcmp(action, "config") == 0) {
// Konfiguration aktualisieren
int interval = doc["interval"] | 10000;
Serial.printf("New interval: %d\n", interval);
}
}
void mqttReconnect() {
while (!mqtt.connected()) {
Serial.println("Connecting to MQTT...");
// Last Will Testament
String willTopic = baseTopic + "/status";
if (mqtt.connect(
deviceId.c_str(),
mqtt_user,
mqtt_pass,
willTopic.c_str(),
1, // QoS
true, // Retain
"offline"
)) {
Serial.println("MQTT connected!");
// Online Status
mqtt.publish(willTopic.c_str(), "online", true);
// Subscribe to commands
String cmdTopic = baseTopic + "/command";
mqtt.subscribe(cmdTopic.c_str());
// Broadcast Commands
mqtt.subscribe("devices/all/command");
} else {
Serial.printf("MQTT failed, rc=%d\n", mqtt.state());
delay(5000);
}
}
}
void publishSensorData(const SensorData& data) {
if (!mqtt.connected()) {
mqttReconnect();
}
JsonDocument doc;
doc["device_id"] = deviceId;
doc["temperature"] = data.temperature;
doc["humidity"] = data.humidity;
doc["heat_index"] = data.heatIndex;
doc["rssi"] = WiFi.RSSI();
doc["uptime"] = millis() / 1000;
String output;
serializeJson(doc, output);
String topic = baseTopic + "/data";
mqtt.publish(topic.c_str(), output.c_str());
Serial.println("Data published");
}
void setupMQTT() {
deviceId = "esp32-" + WiFi.macAddress();
deviceId.replace(":", "");
baseTopic = "sensors/" + deviceId;
mqtt.setServer(mqtt_server, mqtt_port);
mqtt.setCallback(mqttCallback);
mqtt.setBufferSize(512); // Größerer Buffer für JSON
mqttReconnect();
}
void loopMQTT() {
if (!mqtt.connected()) {
mqttReconnect();
}
mqtt.loop();
}OTA Updates
// src/ota.cpp
#include <ArduinoOTA.h>
#include <ESPmDNS.h>
void setupOTA() {
// Hostname
ArduinoOTA.setHostname("esp32-sensor");
// Password
ArduinoOTA.setPassword("ota_secret");
// Port (default: 3232)
ArduinoOTA.setPort(3232);
ArduinoOTA.onStart([]() {
String type = ArduinoOTA.getCommand() == U_FLASH
? "sketch" : "filesystem";
Serial.println("OTA Start: " + type);
// MQTT disconnect
mqtt.disconnect();
});
ArduinoOTA.onEnd([]() {
Serial.println("\nOTA End");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
switch (error) {
case OTA_AUTH_ERROR: Serial.println("Auth Failed"); break;
case OTA_BEGIN_ERROR: Serial.println("Begin Failed"); break;
case OTA_CONNECT_ERROR: Serial.println("Connect Failed"); break;
case OTA_RECEIVE_ERROR: Serial.println("Receive Failed"); break;
case OTA_END_ERROR: Serial.println("End Failed"); break;
}
});
ArduinoOTA.begin();
Serial.println("OTA Ready");
}
void loopOTA() {
ArduinoOTA.handle();
}Deep Sleep für Batterie-Betrieb
// src/deep_sleep.cpp
#include <esp_sleep.h>
#define uS_TO_S_FACTOR 1000000ULL
#define SLEEP_DURATION_S 300 // 5 Minuten
RTC_DATA_ATTR int bootCount = 0;
void printWakeupReason() {
esp_sleep_wakeup_cause_t reason = esp_sleep_get_wakeup_cause();
switch (reason) {
case ESP_SLEEP_WAKEUP_EXT0:
Serial.println("Wakeup: External GPIO");
break;
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Wakeup: Timer");
break;
case ESP_SLEEP_WAKEUP_TOUCHPAD:
Serial.println("Wakeup: Touchpad");
break;
default:
Serial.printf("Wakeup: Other (%d)\n", reason);
break;
}
}
void goToSleep() {
Serial.println("Going to deep sleep...");
Serial.flush();
// Timer Wakeup
esp_sleep_enable_timer_wakeup(SLEEP_DURATION_S * uS_TO_S_FACTOR);
// GPIO Wakeup (z.B. Button)
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, LOW);
// WiFi und Bluetooth ausschalten
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
btStop();
// Deep Sleep starten
esp_deep_sleep_start();
}
void setup() {
Serial.begin(115200);
bootCount++;
Serial.printf("Boot count: %d\n", bootCount);
printWakeupReason();
// Sensor lesen und senden
setupWiFi();
setupMQTT();
SensorData data = readDHT22();
if (data.valid) {
publishSensorData(data);
}
// Kurz warten für MQTT
delay(1000);
mqtt.loop();
// Zurück in Deep Sleep
goToSleep();
}
void loop() {
// Wird bei Deep Sleep nicht erreicht
}Web Server für Konfiguration
// src/webserver.cpp
#include <ESPAsyncWebServer.h>
#include <LittleFS.h>
#include <ArduinoJson.h>
AsyncWebServer server(80);
void setupWebServer() {
// Static Files aus LittleFS
if (!LittleFS.begin(true)) {
Serial.println("LittleFS mount failed");
return;
}
server.serveStatic("/", LittleFS, "/www/")
.setDefaultFile("index.html");
// API: Sensor Status
server.on("/api/status", HTTP_GET, [](AsyncWebServerRequest *request) {
JsonDocument doc;
doc["device_id"] = deviceId;
doc["ip"] = WiFi.localIP().toString();
doc["rssi"] = WiFi.RSSI();
doc["uptime"] = millis() / 1000;
doc["free_heap"] = ESP.getFreeHeap();
doc["temperature"] = lastReading.temperature;
doc["humidity"] = lastReading.humidity;
String output;
serializeJson(doc, output);
request->send(200, "application/json", output);
});
// API: Konfiguration
server.on("/api/config", HTTP_GET, [](AsyncWebServerRequest *request) {
JsonDocument doc;
doc["mqtt_server"] = mqtt_server;
doc["mqtt_port"] = mqtt_port;
doc["interval"] = readInterval;
String output;
serializeJson(doc, output);
request->send(200, "application/json", output);
});
// API: Konfiguration speichern
AsyncCallbackJsonWebHandler* configHandler = new AsyncCallbackJsonWebHandler(
"/api/config",
[](AsyncWebServerRequest *request, JsonVariant &json) {
JsonObject obj = json.as<JsonObject>();
// Konfiguration in NVS speichern
saveConfig(obj);
request->send(200, "application/json", "{\"success\": true}");
}
);
server.addHandler(configHandler);
// API: Restart
server.on("/api/restart", HTTP_POST, [](AsyncWebServerRequest *request) {
request->send(200, "application/json", "{\"restarting\": true}");
delay(100);
ESP.restart();
});
// 404 Handler
server.onNotFound([](AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not Found");
});
server.begin();
Serial.println("Web server started");
}GPIO & PWM Control
// src/gpio_control.cpp
// LED PWM
const int LED_PIN = 2;
const int PWM_CHANNEL = 0;
const int PWM_FREQ = 5000;
const int PWM_RESOLUTION = 8;
void setupPWM() {
ledcSetup(PWM_CHANNEL, PWM_FREQ, PWM_RESOLUTION);
ledcAttachPin(LED_PIN, PWM_CHANNEL);
}
void setLEDBrightness(int brightness) {
// 0-255
ledcWrite(PWM_CHANNEL, brightness);
}
void fadeLED() {
for (int duty = 0; duty <= 255; duty++) {
ledcWrite(PWM_CHANNEL, duty);
delay(10);
}
for (int duty = 255; duty >= 0; duty--) {
ledcWrite(PWM_CHANNEL, duty);
delay(10);
}
}
// Analog Input
const int ANALOG_PIN = 34;
int readAnalog() {
// 12-bit ADC: 0-4095
int raw = analogRead(ANALOG_PIN);
// Zu Spannung konvertieren (3.3V Ref)
float voltage = (raw / 4095.0) * 3.3;
return raw;
}
// Touch Sensor
const int TOUCH_PIN = T0; // GPIO4
void setupTouch() {
touchAttachInterrupt(TOUCH_PIN, touchCallback, 40);
}
void touchCallback() {
Serial.println("Touch detected!");
}Projektstruktur
esp32-sensor/
├── platformio.ini
├── src/
│ ├── main.cpp
│ ├── wifi.cpp
│ ├── mqtt.cpp
│ ├── sensors.cpp
│ ├── ota.cpp
│ └── webserver.cpp
├── include/
│ ├── config.h
│ └── secrets.h
├── lib/
│ └── CustomLibrary/
├── data/
│ └── www/
│ ├── index.html
│ └── style.css
└── test/
└── test_main.cppFazit
ESP32 mit PlatformIO bietet:
- Dual-Core Power: 240MHz für anspruchsvolle Aufgaben
- Connectivity: WiFi + Bluetooth integriert
- Low Power: Deep Sleep für Batterie-Betrieb
- Modern Tooling: PlatformIO + VS Code
Ideale Plattform für IoT-Projekte.
Bildprompts
- "ESP32 microcontroller with connected sensors, breadboard prototype"
- "PlatformIO IDE with code and serial monitor, embedded development"
- "IoT sensor node with battery and antenna, compact device design"