wireless electricity meter using ATmega328 micro-controller, PZEM-004 meter, nRF24L01+ transceiver
Go to file
King Kévin fb608a8e86 fix intialisation 2016-08-26 08:51:44 +02:00
arduino_nano fix intialisation 2016-08-26 08:51:44 +02:00
rpi add info message 2015-11-11 10:09:39 +01:00
README.md new features documents: AES, CRC, OTA, influxdb info 2015-11-11 10:47:58 +01:00
pzem-004_probe.rb initial commit. project is working 2015-10-24 20:03:30 +02:00


the spark counter is a custom electricity meter with wireless data logging capability.

on one side I have:

  • peacefair PZEM-004 power meter to measure the electricity consumption
  • ATmega328P micro-controller to read the measurements out
  • nRF24L01+ radio to transmit the values

on the other side:

  • nRF24L01+ radio to receive the values
  • Raspberry Pi single board computer to store the measurements in an influxDB time series database
  • grafana graphical monitoring tool to display the electricity consumption

more information is available in the wiki.


Arduino Nano firmware for the remote power meter side of the spark counter.

the source files are written in C and intended for the Atmel ATmega328P micro-controller. This does not use the Arduino IDE. It requires avrdude and avr-libc. It also includes the AVR-Crypto-Lib library to encrypt the over the air communication.

Connect the peacefair PZEM-004 power meter to the UART port of the Arduino Nano and the nRF24L01+ radio transceiver to the SPI port (detailed information in nrf24.h). The spark counter firmware will periodically read the measurement values from the power meter (voltage, current, power, energy) and send them using the radio transceiver.

The node configuration is hard coded in main.h:

  • arduino node ID for the RPi to identify the source
  • nRF24 source address of the arduino
  • nRF24 destination address of the RPi
  • nRF24 channel for both devices to communicate
  • request period to define how frequent to query the values from the power meter
  • 128 bites key and IV for over the air encryption. /!\ don't forget to change them and not leave the default known values

The source code is interrupt driven when possible (timers, USART, SPI, nRF24 IRQ).

Arduino - nRF24L01+ connection

ATmega328P signal,ATmega328P pin,Arduino Nano pin,nRF24L01+ board pin,nRF24L01+ signal GND,GND,GND,1,GND ,3V3 (add cap.),2,VCC I/O,PB1,D9,3,CE SS,PB2,D10,4,CSN SCK,PB5,D13,5,SCK MOSI,PB3,D11,6,MOSI MISO,PB4,D12,7,MISO INT0,PD2,D2,8,IRQ


Raspberry Pi program for the computer side of the spark counter.

the source file is written in C++ (mostly C except for RF24) and requires the following libraries:

  • RF24 library for the nRF24L01+ radio transceiver
  • libcurl to save the measurement data in the influxdb time series database
  • tiny-AES128-C to decrypt the radio packets (included in source)
  • AVR libc CRC to verify the checksum of the radio packets (included in source)

on the Raspberry Pi the raspian OS is installer and the bcm2835 SPI kernel module is enabled (through rasp-config).

connect to nRF24L01+ to the SPI port of the Raspberry Pi and set up an influxdb database.


to save the values in the InfluxDB database you have to provide the database name, username, and password as arguments when running spark_counter_receiver. fancy or long arguments might not work (due to the very simple implementation).


if you see the following error while compiling the RF24 eamples: error: sleep was not declared in this scope add the folling line to the corresponding source file: #include <unistd.h> error seen in gettingstarted.cpp, gettingstarted_call_response, and transfer.cpp

RPi - nRF24L01+ connection

RPi signal,RPi pin,nRF24L01+ board pin,nRF24L01+ signal GND,P1_20,1,GND +3V3,P1_17,2,VCC GPIO25,P1_22,3,CE GPIO8/CE0#,P1_24,4,CSN GPIO11/SCLK,P1_23,5,SCK GPIO10/MOSI,P1_19,6,MOSI GPIO9/MISO,P1_21,7,MISO GPIO24,P1_18,8,IRQ


the power meter values (voltage, current, power, energy) are transmitted over the air (OTA) using nRF24L01+ modules. the message format is the following:

  • 1 bytes ID to identify the source sender (and thus which AES 128 bits decryption key to use)
  • 4x4 bytes of measurement values, single precision little endian 32 bits IEEE 754 float, AES 128 bits CRC encrypted
  • voltage (V)
  • current (A)
  • power (W)
  • energy (Wh)
  • 1 byte CRC 8 bits Dallas/Maxim/iButton/1-Wire on the plain 16 bytes values (to verify if the right IV has been used for decryption)


a simple script to query measurement values from the peacefair PZEM-004 power meter. connect the power meter UART port using a USB to UART converter.