Wi-Fi/Bluetooth Sensor Node Design

Architecture and power budget are captured in the project specification. I’m adding the schematic parts now: USB-C, eFuse protection, 3.3 V buck, ESP32-C3 module, SHT41 sensor, USB ESD, and support passives.
Implemented the USB-C Wi‑Fi/BLE temperature-humidity sensor node schematic.
What’s done:
  • Added and wired USB-C 5 V sink input, CC pulldowns, USB data ESD protection, TPS25210 eFuse protection, AP63203 3.3 V buck, ESP32-C3-WROOM-02, SHT41 I2C T/RH sensor, boot/reset buttons, decoupling, pull-ups, and status LED.
  • Created the detailed Project Specification with architecture, datasheet notes, and power budget.
  • Created Firmware Starter with PlatformIO setup and compilable ESP32-C3 Arduino code.
Validation note: schematic/ERC checks did not report unresolved electrical issues in the targeted ERC pass. The remaining review errors are expected pre-layout items: unrouted airwires, overlapping unplaced footprints, and generic passive MPNs before manufacturing BOM finalization.
Next checkpoint: the schematic is ready to move into PCB layout and placement. Want me to go ahead?
Set board layout
Run ERC/DRC
Finalize passives
Auto-place components
Add mounting features

Refine this doc
Ask about this doc
Firmware Starter — ESP32-C3-WROOM-02-N4
Platform & Toolchain
  • MCU module: ESP32-C3-WROOM-02-N4
  • Framework: Arduino for ESP32
  • Build system: PlatformIO
  • Sensor: Sensirion SHT41/SHT4x family on I2C address 0x44
Pin Mapping

Table


FunctionESP32-C3 GPIO / Module PinNetConnected ToDirectionNotes
USB D-GPIO18 / IO18USB_DMINUSUSB-C D- through USBLC6-2SC6USBNative USB Serial/JTAG
USB D+GPIO19 / IO19USB_DPLUSUSB-C D+ through USBLC6-2SC6USBNative USB Serial/JTAG
I2C SDAGPIO4 / IO4I2C_SDASHT41 SDA, 10 kΩ pull-upBidirectionalSHT4x address 0x44
I2C SCLGPIO5 / IO5I2C_SCLSHT41 SCL, 10 kΩ pull-upOutputI2C clock
Status LEDGPIO10 / IO10STATUS_LED_GPIOR10 → D2 → GNDOutputActive high
Boot buttonGPIO9 / IO9ESP_BOOT_GPIO9SW2 to GNDInputHold low during reset for download mode
Reset / enableENESP_ENR6 pull-up, C11 delay, SW1 to GNDInputHardware reset, not a GPIO
Boot strap pull-upGPIO2 / IO2ESP_GPIO2_BOOT_STRAPR7 to 3V3InputBoot robustness
Dependencies & Project Setup
Create a PlatformIO project with this 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
Complete Firmware Source
Save as 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);
}
Build & Flash Instructions

Bash


pio run
pio run -t upload
pio device monitor
To force bootloader/download mode manually: hold BOOT (SW2, GPIO9 low), tap RESET (SW1, EN low), release RESET, then release BOOT.
Low-Power Firmware Notes
  • Use WiFi.setSleep(true) for modem sleep between transmissions.
  • Increase SENSOR_READ_INTERVAL_MS for lower average current.
  • For deep sleep operation, add a wake timer and reinitialize I2C/WiFi after wake; keep GPIO9 boot button unpressed during reset/wake.

    Platform & Toolchain

    Pin Mapping

    Dependencies & Project Setup

    Complete Firmware Source

    Build & Flash Instructions

    Low-Power Firmware Notes

Documents

    Project Specification — USB-C WiFi BLE T-RH Sensor Node

    Firmware Starter — ESP32-C3-WROOM-02-N4

Assets

No assets added.

USB-C WiFi BLE T-RH Sensor Node

USB-C WiFi BLE T-RH Sensor Node thumbnail
Low-power consumer temperature/humidity sensor node powered from USB-C 5V, using a Wi-Fi + BLE 5.x MCU, digital T/RH sensor, USB-C sink configuration, protected 5V input path, and efficient 3.3V regulation.

Properties

Properties describe core aspects of the project.

Pricing & Availability

Distributor

Qty 1

Arrow

$2.58–$3.94

Digi-Key

$2.90–$3.85

HQonline

$6.99–$7.09

LCSC

$8.28–$8.41

Mouser

$9.92

TME

$2.01

Verical

$3.51–$4.34

Controls