Wi-Fi/Bluetooth Sensor Node Design
0x44Table
| Function | ESP32-C3 GPIO / Module Pin | Net | Connected To | Direction | Notes |
|---|---|---|---|---|---|
| USB D- | GPIO18 / IO18 | USB_DMINUS | USB-C D- through USBLC6-2SC6 | USB | Native USB Serial/JTAG |
| USB D+ | GPIO19 / IO19 | USB_DPLUS | USB-C D+ through USBLC6-2SC6 | USB | Native USB Serial/JTAG |
| I2C SDA | GPIO4 / IO4 | I2C_SDA | SHT41 SDA, 10 kΩ pull-up | Bidirectional | SHT4x address 0x44 |
| I2C SCL | GPIO5 / IO5 | I2C_SCL | SHT41 SCL, 10 kΩ pull-up | Output | I2C clock |
| Status LED | GPIO10 / IO10 | STATUS_LED_GPIO | R10 → D2 → GND | Output | Active high |
| Boot button | GPIO9 / IO9 | ESP_BOOT_GPIO9 | SW2 to GND | Input | Hold low during reset for download mode |
| Reset / enable | EN | ESP_EN | R6 pull-up, C11 delay, SW1 to GND | Input | Hardware reset, not a GPIO |
| Boot strap pull-up | GPIO2 / IO2 | ESP_GPIO2_BOOT_STRAP | R7 to 3V3 | Input | Boot robustness |
platformio.ini:Ini
[env:esp32-c3-devkitm-1] platform = espressif32 board = esp32-c3-devkitm-1 framework = arduino monitor_speed = 115200 upload_speed = 460800 build_flags = -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 lib_deps = adafruit/Adafruit SHT4x Library@^1.0.5 adafruit/Adafruit BusIO@^1.16.1
src/main.cpp:Cpp
#include <Arduino.h> #include <Wire.h> #include <WiFi.h> #include <Adafruit_SHT4x.h> // Pin definitions from schematic #define I2C_SDA_PIN 4 // U1 IO4 -> I2C_SDA -> U2 SDA #define I2C_SCL_PIN 5 // U1 IO5 -> I2C_SCL -> U2 SCL #define STATUS_LED_PIN 10 // U1 IO10 -> R10 -> D2 -> GND, active high #define BOOT_BUTTON_PIN 9 // U1 IO9 -> SW2 -> GND, also boot strap #define USB_D_MINUS_PIN 18 // Native USB Serial/JTAG D- #define USB_D_PLUS_PIN 19 // Native USB Serial/JTAG D+ // WiFi placeholders const char* WIFI_SSID = "YOUR_WIFI_SSID"; const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"; const char* REPORT_HOST = "192.168.1.100"; // replace with your server const uint16_t REPORT_PORT = 8080; // Timing #define SENSOR_READ_INTERVAL_MS 5000UL #define WIFI_RECONNECT_INTERVAL_MS 30000UL Adafruit_SHT4x sht4; WiFiClient client; unsigned long lastSensorRead = 0; unsigned long lastWiFiAttempt = 0; bool sensorPresent = false; void setStatusLed(bool on) { digitalWrite(STATUS_LED_PIN, on ? HIGH : LOW); } void blinkStatus(uint8_t count, uint16_t onMs = 80, uint16_t offMs = 120) { for (uint8_t i = 0; i < count; i++) { setStatusLed(true); delay(onMs); setStatusLed(false); delay(offMs); } } void initPins() { pinMode(STATUS_LED_PIN, OUTPUT); setStatusLed(false); // GPIO9 is a boot strap. Do not enable an internal pull that fights the boot button. pinMode(BOOT_BUTTON_PIN, INPUT); } void initI2CAndSensor() { Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN, 400000); if (!sht4.begin(&Wire)) { Serial.println("SHT4x not detected at I2C address 0x44"); sensorPresent = false; blinkStatus(5); return; } sensorPresent = true; sht4.setPrecision(SHT4X_HIGH_PRECISION); sht4.setHeater(SHT4X_NO_HEATER); Serial.println("SHT4x initialized at I2C address 0x44"); } void initWiFi() { WiFi.mode(WIFI_STA); WiFi.setSleep(true); // enables modem sleep between activity windows WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to WiFi"); uint8_t attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 20) { delay(500); Serial.print('.'); digitalWrite(STATUS_LED_PIN, !digitalRead(STATUS_LED_PIN)); attempts++; } if (WiFi.status() == WL_CONNECTED) { Serial.printf("\nWiFi connected, IP=%s\n", WiFi.localIP().toString().c_str()); setStatusLed(true); delay(150); setStatusLed(false); } else { Serial.println("\nWiFi not connected; continuing offline"); setStatusLed(false); } } bool readSHT41(float& temperatureC, float& humidityRH) { if (!sensorPresent) return false; sensors_event_t humidity; sensors_event_t temp; if (!sht4.getEvent(&humidity, &temp)) { Serial.println("SHT4x read failed"); return false; } temperatureC = temp.temperature; humidityRH = humidity.relative_humidity; return true; } void reportSerial(float temperatureC, float humidityRH) { Serial.printf("T=%.2f C, RH=%.2f %%\n", temperatureC, humidityRH); } void reportWiFi(float temperatureC, float humidityRH) { if (WiFi.status() != WL_CONNECTED) return; if (!client.connect(REPORT_HOST, REPORT_PORT)) { Serial.println("Report server connection failed"); return; } String payload = String("{\"temperature_c\":") + String(temperatureC, 2) + String(",\"humidity_rh\":") + String(humidityRH, 2) + String("}"); client.println("POST /environment HTTP/1.1"); client.print("Host: "); client.println(REPORT_HOST); client.println("Content-Type: application/json"); client.print("Content-Length: "); client.println(payload.length()); client.println("Connection: close"); client.println(); client.println(payload); client.stop(); } void maybeReconnectWiFi() { unsigned long now = millis(); if (WiFi.status() == WL_CONNECTED) return; if (now - lastWiFiAttempt < WIFI_RECONNECT_INTERVAL_MS) return; lastWiFiAttempt = now; Serial.println("Attempting WiFi reconnect..."); WiFi.disconnect(); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } void setup() { Serial.begin(115200); delay(500); Serial.println("USB-C WiFi/BLE T-RH Sensor Node starting..."); initPins(); initI2CAndSensor(); initWiFi(); } void loop() { maybeReconnectWiFi(); unsigned long now = millis(); if (now - lastSensorRead >= SENSOR_READ_INTERVAL_MS) { lastSensorRead = now; float temperatureC = NAN; float humidityRH = NAN; if (readSHT41(temperatureC, humidityRH)) { setStatusLed(true); reportSerial(temperatureC, humidityRH); reportWiFi(temperatureC, humidityRH); delay(40); setStatusLed(false); } else { blinkStatus(2, 60, 60); } } delay(20); }
Bash
pio run pio run -t upload pio device monitor
WiFi.setSleep(true) for modem sleep between transmissions.SENSOR_READ_INTERVAL_MS for lower average current.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.