Build a Wireless Environmental Data Logger
IoTSensorsWireless
Combine environmental sensing, wireless connectivity and periodic data logging to create a practical monitoring node.
8 real parts included
Total for this kit: 1,768.00 ฿
Doesn't include any order discount you may get at checkout.
What you'll need
ESP32-C3 SuperMini Development Board — Wi-Fi & Bluetooth, USB-C
670.00 ฿
AHT20 Temperature & Humidity Sensor Module — I2C
260.00 ฿
Micro SD Card Module — SPI, 3.3V/5V Compatible
75.00 ฿
DS3231 Real-Time Clock Module — Battery-Backed
149.00 ฿
830-Point Solderless Breadboard
125.00 ฿
Jumper Wire Kit — Male-Male, Male-Female, Female-Female
220.00 ฿
USB-C Data & Charging Cable — 1m
180.00 ฿
Electronic Project Enclosure — 100×60×25mm
89.00 ฿
Wiring Diagram
Starter Code
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <RTClib.h>
#include <Adafruit_AHTX0.h>
// I2C — ESP32-C3/S3 Arduino-ESP32 default pins
#define SDA_PIN 8
#define SCL_PIN 9
// SPI for the SD module — adjust to match how you wired it
#define SD_CS_PIN 7
#define SD_SCK_PIN 4
#define SD_MOSI_PIN 6
#define SD_MISO_PIN 5
const char* LOG_FILE = "/envlog.csv";
const unsigned long LOG_INTERVAL_MS = 60000; // once a minute
RTC_DS3231 rtc;
Adafruit_AHTX0 aht;
sensors_event_t humidityEvent, tempEvent;
unsigned long lastLog = 0;
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(SDA_PIN, SCL_PIN);
if (!rtc.begin()) {
Serial.println("DS3231 not found — check wiring.");
while (1) delay(1000);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting time from compile time.");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (!aht.begin()) {
Serial.println("AHT20 not found — check wiring.");
while (1) delay(1000);
}
SPI.begin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN, SD_CS_PIN);
if (!SD.begin(SD_CS_PIN)) {
Serial.println("SD card init failed — check wiring/card.");
while (1) delay(1000);
}
// Write a CSV header if the file doesn't exist yet
if (!SD.exists(LOG_FILE)) {
File f = SD.open(LOG_FILE, FILE_WRITE);
if (f) {
f.println("timestamp,temperature_c,humidity_pct");
f.close();
}
}
Serial.println("Logger ready.");
}
void loop() {
unsigned long now = millis();
if (now - lastLog < LOG_INTERVAL_MS) return;
lastLog = now;
DateTime ts = rtc.now();
aht.getEvent(&humidityEvent, &tempEvent);
char timestamp[20];
snprintf(timestamp, sizeof(timestamp), "%04d-%02d-%02d %02d:%02d:%02d",
ts.year(), ts.month(), ts.day(), ts.hour(), ts.minute(), ts.second());
File f = SD.open(LOG_FILE, FILE_WRITE);
if (f) {
f.print(timestamp);
f.print(",");
f.print(tempEvent.temperature);
f.print(",");
f.println(humidityEvent.relative_humidity);
f.close();
Serial.printf("Logged: %s, %.1fC, %.1f%%\n", timestamp, tempEvent.temperature, humidityEvent.relative_humidity);
} else {
Serial.println("Failed to open log file for writing.");
}
}Not sure about a step? Ask us