electricity meter monitoring system (using STM32F103 micro-controller, PZEM-004T meter, SDM120 meter, DDM100TC meter, ESP8266 WiFi module)
Go to file
King Kévin 40d4e3aa19 document SDM120 connection 2017-01-22 16:05:55 +01:00
lib move RE/DE pin to PB1 to fit better board layout 2017-01-21 18:54:05 +01:00
libopencm3@ad5ec6af08 add libopencm3 and STM32duino-bootloader submodules dependencies 2016-01-15 15:36:00 +01:00
.gitignore ignore generated documentation 2016-08-14 19:26:46 +02:00
.gitmodules remove STM32duino-bootloader 2016-08-14 19:03:17 +02:00
Doxyfile update documentation 2016-09-11 22:44:27 +02:00
Makefile switch to blue pill development board 2017-01-19 13:30:03 +01:00
README.md document SDM120 connection 2017-01-22 16:05:55 +01:00
global.c remove memmem 2016-10-04 11:16:13 +02:00
global.h disable debug 2017-01-21 18:55:11 +01:00
main.c move watchdog at start to detext early blocking code 2017-01-21 20:52:26 +01:00


This is the firmware for the spark abacus.



The spark abacus is a system to monitor electricity consumption. A micro-controller collects data from various electricity meters placed at the entry of the 3-phase 4-wire mains electricity distribution installation, and sends it over a local network to a computer storing the values in a database. The measurements can then be visualized. More information is available on the wiki.


The development board used for this project is a blue pill. This offers a STM32F103C8T6 micro-controller.



4 LEDs have been added to show the current activity:

  • power (red): shows if the board is power (the voltage regulator works).
  • heart beat (green): shows if the firmware is running correctly. It starts when all the setup of all peripherals is complete (including connecting to the WiFi network) and toggles every second.
  • query (yellow): goes on when starting to query the measurement values from all electricity meters, and goes off when it received all values.
  • submit (blue): goes on when it start submitting the values to the database (using an HTTP POST on influxDB), and goes off when the submission succeeded.

Note: don't use the onboard LED on PC13 on the blue pill as switching it heavily influences the RTC.

Connections LED (cathode) <-> board (all LED anodes are connected to the +3.3V rail):

  • power; GND
  • heart beat; PA5
  • query; PA6
  • submit; PA7


The onboard Real Time Clock (RTC) is used to track the uptime a periodically start querying all electricity meter for their measurement value. The time interval between the periodic queries is hard coded in main.c. By connecting a (coin cell) battery to VBAT the RTC keeps running, even if the board is not powered anymore.


This 3-phase 4-wire electricity meter provides an S0 interface.

On my model this would output 1600 impulse/kWh, thus each impulse corresponds to a power consumption of 0.625 Wh). This rate is hard coded in main.c. To record these impulses a timer input capture is used. The number of impulses determines the energy used. It is stored in a backup register, keeping the value in memory even when the board is powered down as long as a (coin cell) battery is connected to VBAT. The interval between impulses allow to calculate the current power consumption. The time has a resolution of 0.91 ms (leading to a power calculation error of <1%).

Connections DDM100TC <-> board:

  • S0+, pin 8; +3.3V or +5V
  • S0-, pin 7; PB6, TIM4_CH1 (add pull-down resistor)


This 1-phase 2-wire electricity meter provides a UART interface. For the 3-phase 4-wire power distribution installation I used 3 meters, one per phase.

Because each command includes a device address, they can be connected to the same UART port (one individual addresses have been set). All meters are periodically (see RTC) sequentially queried for their measurements (voltage, current, power, energy). The used addresses are hard coded in main.c A timer is used to guarantee a minimum (undocumented in the specification) time between requests in order to improve the response success.

Connections 3xPZEM-004T <-> board:

  • 5V, 1; +5V (+3.3V is not sufficient)
  • RX, 2; PA2, USART2_TX
  • TX, 3, PA3, USART2_RX
  • GND, 4; ground

Note: when connecting multiple meters one the same UART bus only keep one of the pull-up resistors (across all meters) on the TX pin (on the opto-coupler output), else the low level is not low enough for the micro-controller to correctly decode the signal.


This 1-phase 2-wire electricity meter provides an RS-485 interface using the ModBus RTU protocol. For the 3-phase 4-wire power distribution installation I used 3 meters, one per phase.

They can be connected to the same RS-485 bus once individual addresses have been set. The used meter IDs (aka. slave address) are hard coded in main.c A UART to RS-485 converter is used to be able to communicate with the meters.

The SDM120 ModBus protocol document provide by Eastron specify the commands and registers, but the timing (important) is specified in the SDM630 ModBus protocol document.

Connections 3xSDM120 <-> board:

  • VCC; +5V
  • GND; ground
  • DI; PB10, USART3_TX
  • DE; PB1 (shared with RE since one is active low while the other is active high)
  • RE; PB1 (shared with DE since one is active low while the other is active high)
  • RO; PB11, USART3_RX


The ESP-01 WiFi module (based on the ESP8266 chip) is used to join the local network, connect to an InfluxDB database using HTTP, and store the measurement values gathered from the electricity meters.

AT firmware v0.51 from the espressif NONOS SDK 1.5.0 has been used for this project. Be sure to have configured the module to connect to the right access point beforehand using the following AT commands:

  • set station mode: AT+CWMODE_DEF=1
  • enable DHCP: AT+CWDHCP_DEF=1,1
  • set access point to connect to: AT+CWJAP_DEF="essid","password"

When booting the micro-controller will reset the device and wait until the module connects to the access point and gets an IP.

Once all measurements from all meters have been collected, the firmware will connected to the InfluxDB database to submit the values using and HTTP POST request. The hostname, port, database name, user name, and password are hard coded in main.c.

Connections ESP-01 <-> board:

  • GND, pin 1; ground
  • TX, pin 2; PA10, USART1_RX
  • GPIO2, pin 3; not connected
  • CH_PD, pin 4; pull-up resistor
  • GPIO0, pin 5; not connected
  • RST, pin 6; pull-up resistor
  • RX, pin 7; PA9, USART1_TX
  • VCC, pin 8; +3.3V (add a large capacitor to cope with power spikes)



The source code uses the libopencm3 library. libopencm3 is already a git submodules. To initialize and update it you just need to run once: git submodule init and git submodule update.


To compile the firmware run make.


To generate doxygen documentation run make doc.


The firmware will be flashed using SWD (Serial Wire Debug). For that you need an SWD adapter. The Makefile uses a ST-Link V2 along OpenOCD software (per default), or a Black Magic Probe. To flash using SWD run make flash.


SWD also allows to debug the code running on the micro-controller using GDB. To start the debugging session run make debug.


The firmware offers serial communication over USB (using the CDC ACM device class). This is mainly used to show the activity and help debugging to code. Type help to get a list of additional available actions.

You can also reset the board by setting the serial width to 5 bits over USB. To reset the board run make reset. This only works if USB CDC ACM is running correctly and the micro-controller isn't stuck.