Temperature and Humidity Sensor Node Design
WiFi.h, Wire.hTable
| Function | GPIO/Pin | Connected To | Direction | Notes |
|---|---|---|---|---|
| USB D- | GPIO18 | J1 USB D- through D1 ESD | Bidirectional | Native USB data pair on ESP32-C3 |
| USB D+ | GPIO19 | J1 USB D+ through D1 ESD | Bidirectional | Native USB data pair on ESP32-C3 |
| I2C SDA | GPIO4 | U2 SDA | Bidirectional | Shared with R12 4.7 kOhm pull-up to 3V3 |
| I2C SCL | GPIO5 | U2 SCL | Output/Open-drain bus | Shared with R13 4.7 kOhm pull-up to 3V3 |
| EN / Reset | EN pin | R10 pull-up, C6 filter, S1 reset switch | Control input | Hardware reset path |
| Boot strap | GPIO9 | R11 pull-up, S2 boot switch | Input during reset | Pull low during reset for download mode |
| 3V3 supply | 3V3 | Buck output rail | Power | Main logic rail |
platformio.ini:Ini
[env:esp32-c3-devkitm-1] platform = espressif32 board = esp32-c3-devkitm-1 framework = arduino monitor_speed = 115200 build_flags = -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1
src/main.cpp:Cpp
#include <Arduino.h> #include <WiFi.h> #include <Wire.h> // ---------------- Pin definitions from schematic ---------------- static constexpr int I2C_SDA_PIN = 4; // U1 IO4 -> U2 SDA static constexpr int I2C_SCL_PIN = 5; // U1 IO5 -> U2 SCL // ---------------- SHT41 configuration ---------------- static constexpr uint8_t SHT41_I2C_ADDR = 0x44; static constexpr uint8_t SHT41_CMD_MEASURE_HIGH_PRECISION = 0xFD; static constexpr uint32_t SENSOR_PERIOD_MS = 10000; // ---------------- Wi-Fi placeholders ---------------- static const char* WIFI_SSID = "YOUR_WIFI_SSID"; static const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"; static constexpr uint32_t WIFI_RETRY_INTERVAL_MS = 10000; struct Sht41Reading { float temperatureC; float humidityRH; bool valid; }; unsigned long lastSensorReadMs = 0; unsigned long lastWifiAttemptMs = 0; static uint8_t crc8Sensirion(const uint8_t* data, size_t len) { uint8_t crc = 0xFF; for (size_t i = 0; i < len; ++i) { crc ^= data[i]; for (int bit = 0; bit < 8; ++bit) { if (crc & 0x80) { crc = static_cast<uint8_t>((crc << 1) ^ 0x31); } else { crc <<= 1; } } } return crc; } static bool sht41TriggerMeasurement() { Wire.beginTransmission(SHT41_I2C_ADDR); Wire.write(SHT41_CMD_MEASURE_HIGH_PRECISION); uint8_t result = Wire.endTransmission(); return result == 0; } static Sht41Reading sht41ReadTemperatureHumidity() { Sht41Reading reading = {NAN, NAN, false}; if (!sht41TriggerMeasurement()) { Serial.println("SHT41: failed to send measurement command"); return reading; } delay(10); // Datasheet quick-start uses 10 ms wait for 0xFD measurement constexpr uint8_t expectedBytes = 6; uint8_t rx[expectedBytes] = {0}; int received = Wire.requestFrom(static_cast<int>(SHT41_I2C_ADDR), static_cast<int>(expectedBytes)); if (received != expectedBytes) { Serial.printf("SHT41: expected %u bytes, got %d\n", expectedBytes, received); return reading; } for (uint8_t i = 0; i < expectedBytes; ++i) { rx[i] = Wire.read(); } if (crc8Sensirion(&rx[0], 2) != rx[2]) { Serial.println("SHT41: temperature CRC mismatch"); return reading; } if (crc8Sensirion(&rx[3], 2) != rx[5]) { Serial.println("SHT41: humidity CRC mismatch"); return reading; } uint16_t rawTemp = static_cast<uint16_t>((rx[0] << 8) | rx[1]); uint16_t rawRh = static_cast<uint16_t>((rx[3] << 8) | rx[4]); reading.temperatureC = -45.0f + 175.0f * (static_cast<float>(rawTemp) / 65535.0f); reading.humidityRH = -6.0f + 125.0f * (static_cast<float>(rawRh) / 65535.0f); if (reading.humidityRH > 100.0f) reading.humidityRH = 100.0f; if (reading.humidityRH < 0.0f) reading.humidityRH = 0.0f; reading.valid = true; return reading; } static void initI2C() { Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN); Wire.setClock(400000); Serial.println("I2C initialized on GPIO4/GPIO5"); } static void initWiFiIfConfigured() { if (strlen(WIFI_SSID) == 0 || strcmp(WIFI_SSID, "YOUR_WIFI_SSID") == 0) { Serial.println("Wi-Fi credentials not configured; running in local-only mode"); return; } WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.printf("Connecting to Wi-Fi SSID '%s'", WIFI_SSID); int tries = 0; while (WiFi.status() != WL_CONNECTED && tries < 20) { delay(500); Serial.print('.'); ++tries; } Serial.println(); if (WiFi.status() == WL_CONNECTED) { Serial.printf("Wi-Fi connected, IP = %s\n", WiFi.localIP().toString().c_str()); } else { Serial.println("Wi-Fi connection failed; continuing offline"); } } static void maintainWiFi() { if (strlen(WIFI_SSID) == 0 || strcmp(WIFI_SSID, "YOUR_WIFI_SSID") == 0) { return; } if (WiFi.status() == WL_CONNECTED) { return; } unsigned long now = millis(); if (now - lastWifiAttemptMs < WIFI_RETRY_INTERVAL_MS) { return; } lastWifiAttemptMs = now; Serial.println("Wi-Fi disconnected, retrying..."); WiFi.disconnect(true, true); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } void setup() { Serial.begin(115200); delay(300); Serial.println(); Serial.println("ESP32-C3 environmental node starting"); initI2C(); initWiFiIfConfigured(); lastSensorReadMs = millis(); lastWifiAttemptMs = millis(); } void loop() { maintainWiFi(); unsigned long now = millis(); if (now - lastSensorReadMs >= SENSOR_PERIOD_MS) { lastSensorReadMs = now; Sht41Reading reading = sht41ReadTemperatureHumidity(); if (!reading.valid) { Serial.println("Sensor read failed"); return; } Serial.printf("Temperature: %.2f C, Humidity: %.2f %%RH\n", reading.temperatureC, reading.humidityRH); // Placeholder for future cloud reporting: // - HTTP POST to a REST endpoint // - MQTT publish to a broker // - BLE GATT characteristic update if (WiFi.status() == WL_CONNECTED) { Serial.println("Wi-Fi is connected; add your telemetry upload here"); } } }
pio project init --board esp32-c3-devkitm-1pio runpio run -t uploadpio device monitor -b 115200S2 released and tap RESET S1 if needed.S2, tap RESET S1, then release BOOT after the upload starts.GPIO18/GPIO19) routed to the USB-C connector through ESD protection.3V3 from the buck converter and the ESP_EN net is high.Welcome 👋
Flux helps you build PCBs faster with an AI teammate!
Create your account to collaborate, stay updated, fork your own version, and get instant answers from our AI agent.