Build a compact weather station that measures temperature and humidity in real time. This project uses an ESP32 microcontroller paired with an AHT20 sensor and a small OLED display to create a standalone environmental monitor that updates every 2 seconds.
The guide includes a complete wiring diagram showing how to connect the AHT20 sensor and OLED display to the ESP32 via I2C, a full parts list, ready-to-use firmware, and step-by-step assembly instructions. Once assembled and programmed, the station displays current temperature in Celsius and relative humidity percentage on the blue OLED screen.
Wiring diagram
Gather all the parts
Assemble it in 6 steps
1. Posez les modules
Placez l’ESP32 DevKit v1, le capteur AHT20 et l’écran OLED sur la plaque d’essai, avec leurs rangées de broches dans des lignes séparées. Gardez le capteur éloigné du régulateur et de la puce de l’ESP32 : leur chaleur fausserait légèrement la mesure.
- Lisez les étiquettes imprimées près des broches, pas seulement leur ordre : les OLED qui se ressemblent n’ont pas toujours le même ordre de broches.
2. Alimentez le capteur
Reliez VIN du capteur AHT20 à la broche 3V3 de l’ESP32 avec un fil rouge (alimentation), puis GND du capteur à une broche GND de l’ESP32 avec un fil noir (retour de masse).
- Ne branchez pas VIN du capteur sur 5V : cette réalisation utilise le 3,3 V de l’ESP32 afin que les fils de données restent sûrs.
3. Branchez le capteur à mesurer
Reliez SDA du capteur AHT20 à GPIO21 de l’ESP32 avec un fil vert (données), puis SCL du capteur à GPIO22 avec un fil jaune (horloge).
- Ces deux fils seront aussi reliés à l’écran ; c’est normal, ils peuvent être partagés.
4. Alimentez l’écran
Reliez VCC de l’écran OLED à 3V3 de l’ESP32 avec un fil rouge (alimentation), puis GND de l’écran à GND de l’ESP32 avec un fil noir (retour de masse).
- Assurez-vous que VCC et GND ne sont pas inversés ; une alimentation inversée peut endommager l’écran.
5. Reliez les deux fils de l’écran
Reliez SDA de l’écran OLED à GPIO21 de l’ESP32 avec un fil vert (données), puis SCL à GPIO22 avec un fil jaune (horloge). Les fils SDA et SCL de l’écran et du capteur aboutissent donc chacun à la même broche de l’ESP32.
- Sur le module retenu, l’ordre imprimé est VCC, GND, SCL, SDA : suivez les noms imprimés même si vos fils se croisent.
6. Faites la vérification avant alimentation
Vérifiez une dernière fois les huit liaisons : chaque module a bien son 3V3 et son GND, et chacun a SDA vers GPIO21 et SCL vers GPIO22. Branchez ensuite l’ESP32 au port USB de votre ordinateur.
- Ne laissez aucun fil toucher deux rangées voisines de la plaque d’essai : cela pourrait court-circuiter l’alimentation.
Review all connections
1. Connections between "aht20_1" and "ESP32"
2. Connections between "oled_1" and "ESP32"
Deploy the firmware
#include <Wire.h>
#include <math.h>
#include <Adafruit_AHTX0.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
constexpr int I2C_SDA_PIN = 21;
constexpr int I2C_SCL_PIN = 22;
constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;
constexpr unsigned long SAMPLE_INTERVAL_MS = 2000;
Adafruit_AHTX0 aht;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
bool sensorReady = false;
int lastTemperatureTenths = -10000;
int lastHumidityTenths = -10000;
unsigned long lastSampleMs = 0;
void drawReading(int temperatureTenths, int humidityTenths) {
const float temperature = temperatureTenths / 10.0f;
const float humidity = humidityTenths / 10.0f;
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("STATION METEO"));
display.drawLine(0, 12, 127, 12, SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 20);
display.println(F("Temperature"));
display.setTextSize(2);
display.setCursor(0, 31);
display.print(temperature, 1);
display.println(F(" C"));
display.setTextSize(1);
display.setCursor(76, 20);
display.println(F("Humidite"));
display.setTextSize(2);
display.setCursor(76, 31);
display.print(humidity, 1);
display.println(F("%"));
display.setTextSize(1);
display.setCursor(0, 55);
display.println(F("Mise a jour: 2 s"));
display.display();
}
void drawSensorError() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("STATION METEO"));
display.drawLine(0, 12, 127, 12, SSD1306_WHITE);
display.setCursor(0, 25);
display.println(F("Capteur AHT20"));
display.println(F("introuvable"));
display.setCursor(0, 52);
display.println(F("Verifier les fils"));
display.display();
}
void setup() {
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
for (;;) {
delay(1000);
}
}
sensorReady = aht.begin();
if (!sensorReady) {
drawSensorError();
}
}
void loop() {
const unsigned long now = millis();
const unsigned long elapsed = now - lastSampleMs;
if (elapsed < SAMPLE_INTERVAL_MS) {
delay(SAMPLE_INTERVAL_MS - elapsed);
return;
}
lastSampleMs = millis();
if (!sensorReady) {
sensorReady = aht.begin();
if (!sensorReady) {
delay(1);
return;
}
lastTemperatureTenths = -10000;
lastHumidityTenths = -10000;
}
sensors_event_t humidityEvent;
sensors_event_t temperatureEvent;
aht.getEvent(&humidityEvent, &temperatureEvent);
if (isnan(temperatureEvent.temperature) || isnan(humidityEvent.relative_humidity)) {
sensorReady = false;
drawSensorError();
delay(1);
return;
}
const int temperatureTenths = (int)lroundf(temperatureEvent.temperature * 10.0f);
const int humidityTenths = (int)lroundf(humidityEvent.relative_humidity * 10.0f);
if (temperatureTenths != lastTemperatureTenths || humidityTenths != lastHumidityTenths) {
drawReading(temperatureTenths, humidityTenths);
lastTemperatureTenths = temperatureTenths;
lastHumidityTenths = humidityTenths;
}
delay(1);
}Remix this project
Make it yours in one click
Open a full copy of this project in your own Schematik workspace, diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.




