Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

STM32-Based-Energy-Monitor

A bare-metal STM32 firmware project that reads real-time electrical parameters from a PZEM-004T v3.0 energy monitoring sensor and logs them to an SD card, built on STM32CubeIDE with HAL and FatFs.

This started as a port of a working ESP32/Arduino implementation, rebuilt from the ground up in C for a bare-metal STM32 target — partly as a learning exercise in CubeIDE, partly as the foundation for a standalone energy-logging device.

Hardware

  • MCU: STM32F103C8T6 ("Blue Pill"), 64KB Flash / 20KB RAM
  • Sensor: PZEM-004T v3.0 (Modbus-RTU over UART, 9600 baud, 8N1)
  • Storage: microSD card via SPI, FAT filesystem (FatFs)

Wiring

Signal MCU Pin Peripheral
PZEM TX/RX PA9 (TX) / PA10 (RX) USART1
SD Card SPI (CS/MOSI/MISO/SCK per your config) SPI1 (or as configured)

Features

  • Modular driver design — sensor and storage logic are fully decoupled, each behind a small, focused API:
    • pzem.c / pzem.h — PZEM-004T v3.0 driver (Modbus-RTU frame construction, CRC16 validation, register parsing)
    • storage.c / storage.h — SD card mount and append-only logging via FatFs
  • Interrupt-driven UART RX for PZEM communication — the CPU isn't blocked polling the UART peripheral; incoming bytes are captured via HAL_UART_RxCpltCallback into a ring buffer
  • CRC16-Modbus validation on every received frame, rejecting corrupted reads
  • Cached sensor readings, rate-limited internally to avoid over-polling the sensor
  • Append-based SD card logging using FatFs (f_open / f_write / f_close)

Measured Parameters

Each log entry captures, per read cycle:

  • Voltage (V)
  • Current (A)
  • Active Power (W)
  • Energy (kWh, cumulative since last reset)
  • Frequency (Hz)
  • Power Factor

Project Structure

Core/
├── Inc/
│   ├── pzem.h        # PZEM-004T driver interface
│   └── storage.h      # SD card storage interface
└── Src/
    ├── pzem.c          # PZEM-004T driver implementation
    ├── storage.c       # SD card storage implementation
    └── main.c           # Initialization + main polling loop

How It Works

  1. storage_init() mounts the SD card filesystem via FatFs.
  2. pzem_init() configures the driver with the USART1 handle and arms the first interrupt-driven UART read.
  3. In the main loop, pzem_update() requests a register read from the sensor (rate-limited to once every 200ms internally), waits for the response via the interrupt-filled ring buffer, and validates it with CRC16.
  4. On a successful read, the cached values are formatted into a line and appended to the SD card via storage_write_data().

Building

  1. Open the project in STM32CubeIDE.
  2. Ensure USART1 (PA9/PA10) is configured for 9600 baud, 8N1, with the USART1 global interrupt enabled in NVIC.
  3. Ensure your SPI/SD card peripheral and FatFs middleware are configured per your wiring.
  4. Project Properties → C/C++ Build → Settings → MCU Settings — enable -u _printf_float if using printf/snprintf with floating-point values (required for logging sensor readings, since newlib-nano strips float support from printf by default).
  5. Build and flash.

Known Limitations

  • pzem_reset_energy() currently mirrors a return-logic quirk present in the original Arduino library it was ported from; this has not yet been corrected pending hardware verification.
  • Logging currently writes to a single fixed filename rather than a per-session file.
  • No file header / column labels are written on first file creation.

Roadmap

This project is being actively developed toward a more capable, RTOS-based architecture:

  • Migrate to FreeRTOS (CMSIS-V2) — move sensor polling and SD logging into separate tasks, decoupled via queues, to support multiple independent timing domains as more peripherals are added
  • RTC module integration — timestamp each log entry with real date/time
  • LCD display support — live readout of current sensor values
  • Per-session log file naming
  • CSV header row on first file write
  • Re-evaluate and fix pzem_reset_energy() return logic

Acknowledgements

The PZEM-004T communication protocol implementation is a C port of the PZEM-004T-v30 Arduino library by Jakub Mandula (MIT License), adapted from C++/Arduino Stream-based I/O to bare-metal C using STM32 HAL and interrupt-driven UART.

License

MIT — see LICENSE for details (note: includes attribution requirements stemming from the original PZEM-004T-v30 library license).

About

STM32F103 (Blue Pill) firmware for logging real-time voltage, current, and power from a PZEM-004T sensor to an SD card via FatFs, with interrupt-driven UART and CRC-validated Modbus reads.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages