Ficha 01 · ESP32 + WiFi + HTTP
Exercício 1 · Setup ESP32
Configura Arduino IDE para suportar ESP32 (adiciona URL nas preferences, instala board package). Liga ESP32 DevKit e faz upload do exemplo Blink usando LED_BUILTIN. Confirma que pisca.
Resposta:
-
File → Preferences → Additional Boards URLs:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json -
Tools → Board → Boards Manager → procurar "esp32" by Espressif → install.
-
Liga ESP32 USB. Tools → Board → ESP32 → "ESP32 Dev Module". Tools → Port → seleccionar.
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // GPIO 2 em DevKit V1
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
Upload (seta). Mantém botão BOOT premido até começar upload se necessário.
Exercício 2 · Conectar a WiFi
Cria sketch que conecta o ESP32 à tua rede WiFi e imprime no Serial Monitor o IP e RSSI.
Resposta:
#include <WiFi.h>
const char* SSID = "TUA-REDE";
const char* PASS = "TUA-PASSWORD";
void setup() {
Serial.begin(115200);
delay(100);
Serial.print("A conectar a ");
Serial.println(SSID);
WiFi.begin(SSID, PASS);
int tries = 0;
while (WiFi.status() != WL_CONNECTED && tries < 30) {
delay(500);
Serial.print(".");
tries++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nConectado!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.print("RSSI: ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
Serial.print("MAC: ");
Serial.println(WiFi.macAddress());
} else {
Serial.println("\nFalhou.");
}
}
void loop() {}
Tools → Serial Monitor → 115200 baud. Output esperado:
A conectar a TUA-REDE
....
Conectado!
IP: 192.168.1.150
RSSI: -55 dBm
MAC: 24:6F:28:AB:CD:EF
Exercício 3 · HTTP GET — clima
Faz pedido HTTP GET a http://wttr.in/Lisbon?format=%t+%C e imprime o resultado. Cada 60 segundos.
Resposta:
#include <WiFi.h>
#include <HTTPClient.h>
const char* SSID = "...";
const char* PASS = "...";
void connectWiFi() {
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void setup() {
Serial.begin(115200);
connectWiFi();
}
void fetchWeather() {
HTTPClient http;
http.begin("http://wttr.in/Lisbon?format=%t+%C");
http.setUserAgent("curl/8.0"); // wttr.in rejeita user-agents desconhecidos
int code = http.GET();
if (code == 200) {
String body = http.getString();
body.trim();
Serial.println(body);
} else {
Serial.print("Erro ");
Serial.println(code);
}
http.end();
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
fetchWeather();
}
delay(60000);
}
Output: +18°C Partly cloudy (varia).
Exercício 4 · API JSON com ArduinoJson
Faz GET a https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur e extrai o preço. Usa library ArduinoJson.
Resposta:
Library Manager → "ArduinoJson" by Benoit Blanchon.
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
void setup() {
Serial.begin(115200);
WiFi.begin("ssid", "pass");
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void fetchBTC() {
WiFiClientSecure client;
client.setInsecure(); // skip TLS validation (dev)
HTTPClient http;
http.begin(client, "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=eur");
int code = http.GET();
if (code != 200) {
Serial.print("Erro: "); Serial.println(code);
http.end();
return;
}
String body = http.getString();
http.end();
// Parse JSON
StaticJsonDocument<256> doc;
DeserializationError err = deserializeJson(doc, body);
if (err) {
Serial.println("Parse error");
return;
}
float preco = doc["bitcoin"]["eur"];
Serial.print("BTC = ");
Serial.print(preco, 2);
Serial.println(" €");
}
void loop() {
fetchBTC();
delay(300000); // cada 5 min (rate limits!)
}
Exercício 5 · POST a ThingSpeak
Cria conta thingspeak.com, cria canal com 2 fields. ESP32 lê temperatura simulada (random(20, 30)) e humidade (random(40, 70)) e envia via HTTP GET a cada 30s.
Resposta:
- thingspeak.com → sign up.
- Channels → New Channel → "Sala" → Field 1 = temp, Field 2 = humid → Save.
- API Keys tab → copia Write API Key.
#include <WiFi.h>
#include <HTTPClient.h>
const char* SSID = "...";
const char* PASS = "...";
const char* TS_KEY = "ABCDEFGH12345678";
void setup() {
Serial.begin(115200);
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
randomSeed(analogRead(34));
}
void enviar(float t, float h) {
HTTPClient http;
String url = "http://api.thingspeak.com/update?api_key=";
url += TS_KEY;
url += "&field1=" + String(t, 2);
url += "&field2=" + String(h, 2);
http.begin(url);
int code = http.GET();
http.end();
Serial.print("Enviado: t=");
Serial.print(t); Serial.print(" h=");
Serial.print(h); Serial.print(" → ");
Serial.println(code);
}
void loop() {
float t = random(200, 300) / 10.0;
float h = random(400, 700) / 10.0;
enviar(t, h);
delay(30000); // ThingSpeak free: 15s mínimo
}
Visita o teu canal em thingspeak.com → vês gráficos auto-actualizar.
Exercício 6 · DHT22 → ThingSpeak
Liga sensor DHT22 ao pino GPIO 4. Em vez de valores random, envia leituras reais ao ThingSpeak.
Resposta:
Library: "DHT sensor library" by Adafruit + "Adafruit Unified Sensor".
#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>
#define DHT_PIN 4
DHT dht(DHT_PIN, DHT22);
const char* SSID = "...";
const char* PASS = "...";
const char* TS_KEY = "...";
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) {
Serial.println("Erro DHT");
delay(2000);
return;
}
HTTPClient http;
String url = "http://api.thingspeak.com/update?api_key=";
url += TS_KEY;
url += "&field1=" + String(t, 2);
url += "&field2=" + String(h, 2);
http.begin(url);
http.GET();
http.end();
Serial.printf("T=%.1f H=%.1f\n", t, h);
delay(30000);
}
Hardware DHT22: - VCC → 3.3V (ou 5V). - DATA → GPIO 4 (com pull-up 10kΩ para VCC). - GND → GND.
Exercício 7 · OTA — actualizar via WiFi
Adiciona ao sketch do exercício 6 capacidade de OTA. Faz primeiro upload via USB, depois reinicia e faz segundo upload via Network (sem cabo).
Resposta:
#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>
#include <ArduinoOTA.h>
#define DHT_PIN 4
DHT dht(DHT_PIN, DHT22);
void setupOTA() {
ArduinoOTA.setHostname("aulify-meteo");
ArduinoOTA.setPassword("aulify-pass");
ArduinoOTA.onStart([]() {
Serial.println("OTA início");
});
ArduinoOTA.onEnd([]() {
Serial.println("OTA fim");
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("OTA erro: %u\n", error);
});
ArduinoOTA.begin();
}
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin("ssid", "pass");
while (WiFi.status() != WL_CONNECTED) delay(500);
setupOTA();
Serial.println("Pronto. IP=" + WiFi.localIP().toString());
}
unsigned long ultEnv = 0;
void loop() {
ArduinoOTA.handle(); // chamar sempre
if (millis() - ultEnv > 30000) {
ultEnv = millis();
// ... envio thingspeak
}
}
- Upload USB normal.
- Após reset, abre Tools → Port → vai aparecer
aulify-meteo at 192.168.1.x (Network). - Selecciona-o.
- Próximo upload pede password OTA → put
aulify-pass. - Sem fio!
Exercício 8 · Web server simples
Cria web server no ESP32 que serve uma página HTML com leitura actual do DHT22. URL: http://<IP_esp>.
Resposta:
#include <WiFi.h>
#include <WebServer.h>
#include <DHT.h>
#define DHT_PIN 4
DHT dht(DHT_PIN, DHT22);
WebServer server(80);
float lastT = 0, lastH = 0;
unsigned long lastRead = 0;
void readSensor() {
if (millis() - lastRead > 2000) {
lastRead = millis();
float t = dht.readTemperature();
float h = dht.readHumidity();
if (!isnan(t)) lastT = t;
if (!isnan(h)) lastH = h;
}
}
void handleRoot() {
readSensor();
String html = "<!DOCTYPE html><html><head>";
html += "<meta charset='utf-8'>";
html += "<meta http-equiv='refresh' content='5'>";
html += "<title>Aulify Meteo</title>";
html += "<style>body{font-family:sans-serif;text-align:center;padding:50px;background:#eee}";
html += "h1{font-size:6em;color:#0070f3}p{font-size:2em}</style>";
html += "</head><body>";
html += "<h1>" + String(lastT, 1) + "°C</h1>";
html += "<p>Humidade: " + String(lastH, 1) + " %</p>";
html += "<small>Aulify ESP32</small>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin("ssid", "pass");
while (WiFi.status() != WL_CONNECTED) delay(500);
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.begin();
}
void loop() {
server.handleClient();
}
Abre http://<IP_do_esp32>/ no browser → vês temperatura grande. Auto-refresh cada 5s.