No description
| docs | ||
| include | ||
| lib | ||
| src | ||
| test | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| .python-version | ||
| platformio.ini | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
ESP32 Voltage Measurement
Serial voltage measurement system using ESP32 with JSON-based communication protocol.
Features
- 🔌 JSON-based serial communication protocol
- 📊 Voltage measurement via ADC (0-30V with voltage divider)
- 🔄 Request-response architecture (no streaming)
- 📝 Auto-generated protocol documentation
- ✅ Pre-commit hooks for code quality
- 📈 Multi-sample averaging for stability
- 💾 Flash-based configuration storage
- 🔧 Configurable ADC parameters
Hardware
- Board: AZ-Delivery DevKit v4 (ESP32)
- Communication: Serial over USB (115200 baud)
- ADC Pin: GPIO34 (ADC1_CH6)
- Voltage Range: 0-30V (requires voltage divider: R1=82kΩ, R2=10kΩ)
For detailed hardware setup and voltage divider circuit, see docs/HARDWARE.md.
Protocol
The device uses a JSON-based protocol over serial. See docs/PROTOCOL.md for complete documentation.
Quick Example
import serial
import json
def read_json_response(ser):
"""Read and parse only valid JSON lines (filters out bootloader messages)."""
while True:
line = ser.readline().decode().strip()
if not line:
continue
try:
return json.loads(line)
except json.JSONDecodeError:
# Ignore bootloader and other non-JSON output
continue
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=2)
# Wait for ready message (automatically skips bootloader output)
ready = read_json_response(ser)
print(ready)
# {"type": "ready", "status": "ok", "version": "1.0",
# "max_voltage": 25.74, "config": {...}}
# Request voltage reading
ser.write(b'{"cmd": "read"}\n')
response = read_json_response(ser)
print(response) # {"type": "voltage", "value": 23.47, "unit": "V", "status": "ok"}
# Get current configuration
ser.write(b'{"cmd": "config", "action": "get"}\n')
config = read_json_response(ser)
print(config) # {"type": "config", "config": {...}, "status": "ok"}
# Set voltage divider resistors (persists to flash)
ser.write(b'{"cmd": "config", "action": "set", "param": "r1_ohms", "value": 82000}\n')
response = read_json_response(ser)
print(response) # Returns updated config with new R1 value
Setup
PlatformIO (ESP32)
# Build and upload to ESP32
pio run --target upload
# Monitor serial output
pio device monitor
Python (Documentation Only)
Python and uv are only used for documentation generation, not for the main firmware.
# Install dependencies
uv sync
# Install pre-commit hooks
uv run pre-commit install
# Generate protocol documentation
uv run python docs/generate_protocol_docs.py
Development
Pre-commit Hooks
This project uses pre-commit hooks to maintain code quality:
- Ruff - Python linting and formatting
- Protocol docs - Auto-generates
docs/PROTOCOL.mdwhenprotocol.yamlchanges - Standard checks - Trailing whitespace, file endings, YAML/JSON validation
Install hooks:
uv run pre-commit install
Run manually:
uv run pre-commit run --all-files
Protocol Updates
When updating the communication protocol:
- Edit
docs/protocol.yamlwith new commands/fields - Update
src/main.cppwith implementation - Run
uv run python docs/generate_protocol_docs.py(or let pre-commit do it) - Commit changes - the hook will ensure docs are up to date
Project Structure
esp32 Voltage Measurement/
├── src/
│ └── main.cpp # ESP32 firmware (C++)
├── include/
│ └── config.h # Configuration struct and constants
├── lib/ # Libraries
├── test/ # Unit tests
├── docs/
│ ├── protocol.yaml # Protocol definition (source of truth)
│ ├── generate_protocol_docs.py # Documentation generator (Python)
│ ├── PROTOCOL.md # Auto-generated protocol documentation
│ ├── HARDWARE.md # Hardware setup guide
│ └── CONFIGURATION.md # Configuration system guide
├── platformio.ini # PlatformIO configuration
├── pyproject.toml # Python/uv configuration (docs only)
└── .pre-commit-config.yaml # Pre-commit hooks
Future Enhancements
- Real ADC voltage measurement
- Multi-sample averaging
- Flash-based configuration storage
- Runtime configuration commands (set samples, divider ratio, etc.)
- Voltage calibration command
- Multiple channel support
- Advanced filtering (moving average, median filter)
- Continuous monitoring mode
License
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later).
See the GNU GPL v3 license text for details.