This is an old revision of the document!
The spark counter is a custom electricity meter with wireless data logging capability.
On one side I have:
On the other side:
The peacefair PZEM-004 is a simple power meter. It:
The voltage measurement is done over the power input port. The current measurement is done using a coil. Pass the wire on which you would like to measure the current through the coil, and connect the coil to the power meter. A drawing on the back of the device will describe how to connect the wires.
The meter also provides a UART port to query the measured values. Two opto-couplers isolate the main power meter circuits from the TX and RX UART ports.
The manual provides the corresponding commands, but lacks some information. The UART configurations is 9600 bps 8N1. Before querying the measurements, you have to set an address to the device. Else it won't reply to the other commands. The manual uses an IP as address (192.168.1.1 = C0 A8 01 01). No idea why you would set an IP for a UART address.
The commands use the following 7 bytes message format:
“%u.%u”,bytes[1]«8+bytes[2],bytes[3]
V/A/W“%lu”,bytes[1]«16+bytes[2]«8+bytes[3]
Have a look at the manual for examples. Each command triggers a very loud buzzer beep (same a for the alarm). I removed the pizeo-element to prevent this annoying sound.
The power meter uses a single chip solution, the SDIC microelectronics SD3004 (datasheet). This chip does all the necessary work: measure voltage and current, drive the 7-segments LED displays, communicate over UART. There is only an additional external I²C EEPROM to store the global energy consumption.
To read out the measurements from the power meter and send them over radio I used an Atmel ATmega328P micro-controller. Because the development board costs less than the chip itself I simply used a cheap Arduino Nano clone.
USART to query the power meter, SPI to communicate with the nRF24L01+, and the nRF24L01+ protocol are implemented in C (using a lot of interrupts). The source code is available in this git. I prefer directly writing in the registers as described in the datasheet rather than using an abstract IDE and libraries. This way I learn how it works in details.
Arduino - nRF24L01+ connection:
ATmega328P signal | ATmega328P pin | Arduino Nano pin | nRF24L01+ board pin | nRF24L01+ signal |
---|---|---|---|---|
GND | GND | GND | 1 | GND |
3V (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 |
To transmit the measurements from the ATmega328P to the RPi I used nordic nRF24L01+ RF transceivers. There are very inexpensive, require low power, provide enough bandwidth for such application, are easy to control, and because I always wanted to try them out.
On the micro-controller side I implemented the complete SPI-based protocol using the datasheet. The source code is available in this git.
On the computer side I use the RF24 library. The documentation is straight forward and saved me some time re-implementing the protocol a second time.
To store the measurements I use a Raspberry Pi Model B1 (rev 0002). It's a tiny single board computer which was laying around for quite some time now.
To receive the measurements I used a nRF24L01+ transceiver with the RF24 library. The source code is available in this git.
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 values are then simply stored in an InfluxDB time series database for visualisation in grafana.