WiFi Water Flow Meter Design

I’ll build the complete schematic around an ESP32 WiFi module, USB‑C 5V input, protected 3.3V regulation, external ultrasonic sensor connector, programming/reset circuitry, and status LEDs. I’ll first select datasheet-backed parts, then add/wire the schematic, document the power budget, and run design checks.
I selected the main parts: ESP32-S3-WROOM-1, AP2112K 3.3V LDO, USB-C receptacle, USB ESD array, resettable fuse, headers, switches, and indicator LEDs. I’m adding the schematic components now, with the sensor interface kept generic until a specific ultrasonic sensor module is chosen.
Schematic is complete for the ESP32-S3 WiFi ultrasonic water flow meter: USB-C 5V input, fuse + ESD protection, AP2112K 3.3V regulator with required caps, ESP32 reset/boot network, native USB, UART header, sensor connector, and three status LEDs.
Validation: ERC is clean; remaining review errors are PCB-layout-only airwires/overlaps because placement/routing has not started yet. I also created Project Specification, Design Notes, and Firmware Starter.
One design caveat: the exact external ultrasonic sensor model is still unspecified, so the connector supports a generic pulse/UART-style sensor interface and should be updated if the chosen sensor requires 5V, 12V, RS485, or an analog ultrasonic front end. Ready to move to PCB layout when you are.
Proceed to layout
Use 5V sensor
Add RS485 option
Review power budget
Optimize BOM

Refine this doc
Ask about this doc
Firmware Starter — ESP32-S3-WROOM-1-N16R8
Platform & Toolchain
  • MCU: ESP32-S3-WROOM-1-N16R8
  • Framework: Arduino for ESP32
  • Build system: PlatformIO
  • USB programming: Native ESP32-S3 USB Serial/JTAG on IO19/IO20, plus UART0 header J3.
Pin Mapping

Table


FunctionGPIOSchematic NetConnected ToDirectionNotes
USB D-19USB_D_NJ1 USB-C D- via D1 ESDUSBNative USB serial/JTAG
USB D+20USB_D_PJ1 USB-C D+ via D1 ESDUSBNative USB serial/JTAG
Flow pulse input4FLOW_PULSEJ2 pin 3 through R10 100R; R6 100k pulldownInput interruptGeneric pulse-output flow sensor input
Sensor UART TX17SENSOR_UART_TXJ2 pin 4OutputOptional external sensor serial TX
Sensor UART RX18SENSOR_UART_RXJ2 pin 5InputOptional external sensor serial RX
Sensor aux GPIO5SENSOR_AUX_GPIOJ2 pin 6ConfigurableOptional enable/interrupt/config line
WiFi LED6LED_WIFI_DRVR8 to D3OutputHIGH turns LED on
Flow LED7LED_FLOW_DRVR9 to D4OutputHIGH turns LED on
Boot button0ESP_BOOTR4 pull-up, S2 to GNDStrap/inputHold BOOT while resetting to enter download mode
Reset buttonENESP_ENR3 pull-up, C6 delay, S1 to GNDResetPull low to reset module
UART0 TXTXD0/GPIO43UART_TXD0J3 pin 3OutputDebug/programming UART TX
UART0 RXRXD0/GPIO44UART_RXD0J3 pin 4InputDebug/programming UART RX
platformio.ini

Ini


[env:esp32-s3-devkitc-1]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
upload_speed = 921600
build_flags =
  -D ARDUINO_USB_MODE=1
  -D ARDUINO_USB_CDC_ON_BOOT=1
Complete Firmware Source (src/main.cpp)

Cpp


#include <Arduino.h>
#include <WiFi.h>

// ---------------- Pin definitions from schematic ----------------
#define FLOW_PULSE_PIN        4   // U1 IO4 -> R10 -> J2 pin 3, with 100k pulldown
#define SENSOR_UART_TX_PIN   17   // U1 IO17 -> J2 pin 4
#define SENSOR_UART_RX_PIN   18   // U1 IO18 -> J2 pin 5
#define SENSOR_AUX_GPIO_PIN   5   // U1 IO5 -> J2 pin 6
#define LED_WIFI_PIN          6   // U1 IO6 -> R8 -> D3
#define LED_FLOW_PIN          7   // U1 IO7 -> R9 -> D4

// USB native serial uses IO19/IO20 internally on ESP32-S3.
// UART0 debug is also available on J3: TXD0/GPIO43 and RXD0/GPIO44.

// ---------------- User configuration ----------------
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* HTTP_HOST = "192.168.1.100";   // Replace with your server
const uint16_t HTTP_PORT = 8080;

// Calibration: pulses per liter depends on the selected external ultrasonic sensor module.
// Replace this with the sensor manufacturer's K-factor after selecting the sensor.
volatile uint32_t flowPulseCount = 0;
const float PULSES_PER_LITER = 450.0f;  // placeholder calibration constant

unsigned long lastReportMs = 0;
uint32_t lastPulseSnapshot = 0;
float totalLiters = 0.0f;

HardwareSerial SensorSerial(1);

void IRAM_ATTR onFlowPulse() {
  flowPulseCount++;
}

void setWiFiLed(bool on) {
  digitalWrite(LED_WIFI_PIN, on ? HIGH : LOW);
}

void setFlowLed(bool on) {
  digitalWrite(LED_FLOW_PIN, on ? HIGH : LOW);
}

void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to WiFi");

  uint8_t tries = 0;
  while (WiFi.status() != WL_CONNECTED && tries < 30) {
    setWiFiLed((tries & 1) != 0);
    delay(250);
    Serial.print('.');
    tries++;
  }

  if (WiFi.status() == WL_CONNECTED) {
    setWiFiLed(true);
    Serial.printf("\nWiFi connected, IP=%s\n", WiFi.localIP().toString().c_str());
  } else {
    setWiFiLed(false);
    Serial.println("\nWiFi not connected; continuing offline.");
  }
}

void initSensorInterface() {
  pinMode(FLOW_PULSE_PIN, INPUT);  // external R6 provides pulldown
  attachInterrupt(digitalPinToInterrupt(FLOW_PULSE_PIN), onFlowPulse, RISING);

  pinMode(SENSOR_AUX_GPIO_PIN, OUTPUT);
  digitalWrite(SENSOR_AUX_GPIO_PIN, HIGH);  // available as sensor enable/config line

  SensorSerial.begin(9600, SERIAL_8N1, SENSOR_UART_RX_PIN, SENSOR_UART_TX_PIN);
  Serial.println("Sensor interface initialized: pulse input + optional UART.");
}

bool sendHttpReport(float flowLpm, float totalL) {
  if (WiFi.status() != WL_CONNECTED) return false;

  WiFiClient client;
  if (!client.connect(HTTP_HOST, HTTP_PORT)) {
    Serial.println("HTTP connect failed");
    return false;
  }

  String body = String("{\"flow_lpm\":") + String(flowLpm, 3) +
                String(",\"total_l\":") + String(totalL, 3) + String("}");

  client.printf("POST /flow HTTP/1.1\r\n");
  client.printf("Host: %s\r\n", HTTP_HOST);
  client.printf("Content-Type: application/json\r\n");
  client.printf("Content-Length: %u\r\n", body.length());
  client.printf("Connection: close\r\n\r\n");
  client.print(body);
  client.stop();
  return true;
}

void setup() {
  pinMode(LED_WIFI_PIN, OUTPUT);
  pinMode(LED_FLOW_PIN, OUTPUT);
  setWiFiLed(false);
  setFlowLed(false);

  Serial.begin(115200);
  delay(1000);
  Serial.println("ESP32-S3 ultrasonic water flow meter starting...");

  initSensorInterface();
  connectWiFi();
}

void loop() {
  const unsigned long now = millis();

  if (WiFi.status() != WL_CONNECTED) {
    setWiFiLed(false);
    connectWiFi();
  }

  if (now - lastReportMs >= 1000) {
    noInterrupts();
    uint32_t pulseSnapshot = flowPulseCount;
    interrupts();

    uint32_t deltaPulses = pulseSnapshot - lastPulseSnapshot;
    lastPulseSnapshot = pulseSnapshot;

    float litersThisSecond = deltaPulses / PULSES_PER_LITER;
    totalLiters += litersThisSecond;
    float flowLpm = litersThisSecond * 60.0f;

    setFlowLed(deltaPulses > 0);
    Serial.printf("Pulses=%lu, Flow=%.3f L/min, Total=%.3f L\n",
                  (unsigned long)deltaPulses, flowLpm, totalLiters);

    sendHttpReport(flowLpm, totalLiters);
    lastReportMs = now;
  }
}
Build & Flash

Bash


pio run
pio run -t upload
pio device monitor -b 115200
To enter bootloader/download mode manually, hold BOOT (S2), press/release RESET (S1), then release BOOT.
Sensor Note
The external ultrasonic sensor model is not yet fixed. The schematic supports pulse-output measurement plus optional UART pins; update PULSES_PER_LITER or replace the pulse code with the sensor vendor's serial protocol once a specific sensor module is selected.

    Platform & Toolchain

    Pin Mapping

    `platformio.ini`

    Complete Firmware Source (`src/main.cpp`)

    Build & Flash

    Sensor Note

Documents

    Project Specification

    Design Notes

    Firmware Starter — ESP32-S3-WROOM-1-N16R8

Assets

No assets added.

ESP32 Ultrasonic Flow Meter

ESP32 Ultrasonic Flow Meter thumbnail
USB-C powered ESP32 WiFi water flow meter for an external ultrasonic sensor on 3/4 inch PVC pipe, with protected 5V input, 3.3V regulation, programming header, reset/boot support, and status LEDs.

Properties

Properties describe core aspects of the project.

Pricing & Availability

Distributor

Qty 1

Arrow

$2.72–$3.95

Digi-Key

$6.87–$10.59

HQonline

$1.72–$1.87

LCSC

$8.65–$8.92

Mouser

$13.55

TME

$2.02

Verical

$2.76–$134.92

Controls