Small enclosure with 0.96 inch OLED showing temperature and humidity, outdoors on a railing

Beginner

Build a Mini Weather Station

SensorsDisplaysIoT

A local temperature and humidity readout you can build in an afternoon — no cloud account, no app, just real numbers on a real screen.

7 real parts included

Total for this kit: 1,829.00 ฿

Doesn't include any order discount you may get at checkout.

What you'll need

Project Goal

This project builds a small local instrument that reads and displays temperature and humidity in real time, with no cloud account, app, or network dependency required -- just a controller, a sensor, and a screen showing real numbers.

What the Controller Does

The controller runs one small program on a loop: read the sensor, format the values, send them to the display, wait briefly, and repeat. It's the only "brain" in the project -- the sensor and display are both dumb peripherals that do exactly what the controller tells them to.

What the AHT20 Sensor Does

The AHT20 measures temperature and relative humidity and reports both values to the controller over I2C, doing its own analog-to-digital conversion internally rather than handing the controller a raw voltage to interpret. It's worth being clear about what this build is and isn't: with only the AHT20 on board, this is a temperature and humidity station -- it does not measure barometric pressure, and no pressure sensor is used in this project. A "full" weather station with pressure and altitude sensing would need an additional barometric sensor added on top of this build; this project intentionally keeps to temperature and humidity.

What the Display Does

The 0.96" OLED exists purely to show the two current values somewhere legible. It has no logic of its own -- the controller sends it exactly what to draw, on every refresh.

Common I2C Wiring Concepts

The AHT20 and the OLED both typically communicate over I2C: two shared signal wires (clock and data) plus power and ground, with each device identified by its own address on the bus. Since both modules can share the same two signal wires, confirm their default addresses don't conflict before wiring both up at once -- most OLED and AHT20 modules ship at different default addresses, but it's worth checking rather than assuming.

Software and Library Concepts

Both the sensor and the display will have working example code available for common controller platforms. Start from a manufacturer or community example for each part individually, confirm both work on their own, and only then combine them into one program -- debugging two new, untested parts at once is significantly harder than debugging one at a time.

Testing and Troubleshooting

  • No readings at all -- check power and ground first, then confirm the sensor's I2C address matches what your code expects.
  • Display stays blank -- confirm its own power connection separately from the sensor; a shared-bus issue with one device can sometimes affect the other.
  • Readings look wrong or jump around -- check for a loose wire or an address conflict on the shared I2C bus before assuming the sensor itself is faulty.
  • Nothing updates after the first reading -- confirm your loop actually re-reads the sensor each cycle rather than reusing the first value it captured.

Optional Future Upgrade: Remote Data Logging

Once this local readout is working reliably, a natural next step is adding a wireless connection so readings can be logged remotely instead of only being visible on the local display -- see the Wireless Environmental Data Logger project for the concepts involved.

Wiring

  • AHT20 sensor VCC → ESP32-C3 3V3
  • AHT20 sensor GND → ESP32-C3 GND
  • AHT20 sensor SDA → ESP32-C3 GPIO8 — default I2C SDA
  • AHT20 sensor SCL → ESP32-C3 GPIO9 — default I2C SCL
  • OLED display VCC → ESP32-C3 3V3
  • OLED display GND → ESP32-C3 GND
  • OLED display SDA → ESP32-C3 GPIO8 — shared bus with AHT20 (different I2C addresses: 0x38 vs 0x3C)
  • OLED display SCL → ESP32-C3 GPIO9 — shared bus with AHT20
  • ESP32-C3 SuperMini → USB-C cable → computer/power bank (power + programming)
  • Enclosure: mount the ESP32-C3 and OLED so the screen is visible through a window/opening, with the AHT20 exposed to ambient air (not sealed against a warm board) for an accurate reading

Since both I2C devices share the same two wires, wire and test the AHT20 alone first (confirm readings over Serial), then add the OLED — isolating a bad connection is much easier with one device at a time. If placing this outdoors or anywhere humid, keep the AHT20 shielded from direct water while still allowing airflow, since it's not a submersible sensor.

Wiring Diagram

VCC → 3V3 GND SDA → GPIO8 SCL → GPIO9 VCC → 3V3 GND SDA → GPIO8 SCL → GPIO9 ESP32-C3 AHT20 sensor OLED display USB-C cable

Starter Code

// Mini Weather Station — ESP32-C3 SuperMini + AHT20 + OLED
#include <Wire.h>
#include <Adafruit_AHTX0.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// --- Pins — adjust to match your board's silkscreen if different ---
#define SDA_PIN 8
#define SCL_PIN 9

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C

Adafruit_AHTX0 aht;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);

  if (!aht.begin()) {
    Serial.println("AHT20 not found — check wiring");
    while (1) delay(1000);
  }

  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println("SSD1306 not found — check wiring");
    while (1) delay(1000);
  }
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp);

  float tempC = temp.temperature;
  float tempF = tempC * 9.0 / 5.0 + 32.0;
  float rh = humidity.relative_humidity;

  display.clearDisplay();

  display.setTextSize(2);
  display.setCursor(0, 0);
  display.print(tempC, 1);
  display.println(" C");

  display.setTextSize(1);
  display.setCursor(0, 20);
  display.print(tempF, 1);
  display.println(" F");

  display.setCursor(0, 40);
  display.print("Humidity: ");
  display.print(rh, 0);
  display.println(" %");

  display.display();

  Serial.print("Temp: "); Serial.print(tempC); Serial.print(" C / ");
  Serial.print(tempF); Serial.print(" F  Humidity: "); Serial.print(rh);
  Serial.println(" %");

  delay(2000);
}

Not sure about a step? Ask us