My last post covered how I with a logic analyzer successfully (but not in the safest way) sniffed the SPI-transmission on the device and managed to decipher the data. And then how I used an Arduino Nano to do the sniffing for me with an interrupt driven approach. The Arduino translated the bits and bytes to power and voltage values that it continuously printed on the PC's Serial monitor via an USB-cable.
The next obvious step in this project is to get the energy meter to transmit the data wirelessly. Not only would this mean that I could grab data from several energy meters simultaneously, but it also creates a safe way of debugging the device since my previous setup (which I abandoned after reading some of the comments on Hackaday.com) meant connecting the mains neutral to the computers ground (do not try this at home!!!)
Today's post will cover how I managed to get an Arduino pro mini (3.3V) to sniff the energy meters SPI and transmit the data wirelessly with a nRF24L01+ to an Arduino Nano connected to a computer. The neat thing with this setup is that the Arduino pro mini and the nRF fits perfectly within the casing of the energy meter, and are both driven by the internal power that charges the rechargeable battery that you'll find in the meter.
The total cost of components for each energy meter is:
Energy meter £7.97
Arduino Mini 3.3 V £2.58
nRF24L01+ £0.99 (choose the black + version)
A capacitor + cables pretty much free, say £1
which comes to a total of £12.54 per unit!
Plus one computer connected node, or a raspberry pi with a nRF24L01 to receive the transmissions from all the energy meters.
Arduino and RF24.h
As mentioned in previous blog-posts I have worked quite allot with the nRF24L01 and AVR's, writing my own libraries and so on. But since this is my first Arduino-project I wanted to learn how to import and use other peoples libraries. Since I am still a newbie in programming, I always have to learn everything from scratch, and nothing ever works as supposed to when I try to follow a tutorial...
I started out by setting up two Arduino Nanos according to this guide and running the example code at the bottom of that page, and as expected - it didn't work.
Debugging
1. Do I have a working SPI-connection?
I had followed the explanation in the guide i linked to above, on how to install the RF24.h-library and it all seamed to work, I definitely had a working SPI-connection between the Arduino and the nRF since I could print out all the registers, and modifying them also worked...
Took me a while to figure out that I had to download and include the file "printf.h" and call "printf_begin();" to print out data from the nRF to the serial monitor... and why, why, why are they using the "protected" attribute for many of the functions??? For example get_status is a very useful debug-function and should not be protected!
2. Am I using the correct hardware setup?
As always I hadn't used the exact components as the instructions said, in my drawer I could only find one 47 uF 24 V and one 100 uF 16 V capacitors. Well in the guide it sais:
"Connect a .3.3 uF to 10 uF (MicroFarad) capacitor directly on the module from +3.3V to Gnd (Watch + and - !) [Some users say 10 uF or more..]"
And I read 10 uF or more....
Anyways, I thought that this should work, since I have used these capacitors before on the nRF, but not with this library and not with Arduino...
3. I found a working code
Yay, suddenly i found a working code, the "pingpair" example that comes with the NRF.h-library worked with my setup!
4. Why does only Pingpair-code work?
I started stripping the Pingpair-code of its components, and found that my setup was only working when it got into receiving mode in between every transmission... strange, but keeping in mind that I was using bigger capacitors I figured it had something to do with the capacitors not have time enough to recharge/discharge.
I think this is what happened:
When the Arduino calls the "Write" function, the library runs the "startWrite"-function which powers up the nRF and has a predefined delay of 150 us (wait for the nRF to power up) before it starts transmitting the data.
It turned out that this delay was not enough for my setup, so when I changed this to 1000 us (1 ms), the code worked like a charm even without the receiving functions in between! To do this modification, I opened the RF24.cpp-file (in the arduino Sketchbook libraries folder) with notepad, changed the delay, and saved the file.
Arduino Mini
Just as I managed to get a working Arduino code for the nRF, two Arduino Mini 3.3 V landed in my postbox, awesome timing!
Here's a pic of when I have soldered an nRF to the Arduino and uploading code with the USB to COM adapter via a breadboard (out of sight) so the colored cables does not match the pins...
Here you have the wire diagram:
I started off by just uploading a simple transmission code on the Arduino mini, that would send a dummy byte once a second to confirm a working setup. I soldered everything together, plugged the meter into an outlet and kept my fingers crossed as I watched the Arduino-Serial monitor connected to the receiving unit, and.... noting (of course!)
After several hours of debugging, (I thought I had burnt the nRF by hooking it up directly to the power-meters VCC-pin) It turned out had I accidentally uploaded a non-working code to the Arduino Mini.... FAIL!!!
I had cleaned up my working code, and shifted some parts around, it seems like you can't open the writing/reading-pipes on the nRF before you set the datarate/payloadsize/PALevel...
Anyway, the setup I found working is grabbing the power directly from the battery (3.6 V soldered to the underside of the PCB) rather than the VCC-cable (which i think is a bit flaky, and is connected to the RAW-pin on the Arduino, which has a built in 3,3 V regulator. I'm not sure this modification is necessary, but it ensures that the nRF and the Arduino gets 3.3 V. (The pictures above are not connected to RAW, but the Arduino's 3.3 V)
Here's whats transmitted to the computer connected Arduino and printed in the Serial monitor:
I have spent some time looking at ways to store and plot this data in the cloud. One interesting approach is to send the data to a website like http://emoncms.org/ and use there ready to use energy-viewing graphs. With the help of a small python-script I wrote, I can easily send the data from my raspberry pi-server to my account on there website where I have the option of making graphs.
I have also been working in the program called "Processing" which is pretty much the same as Arduino-IDE but for graphing and doing stuff with the data.
I have so far programmed a working graph that shows the data output from up to 6 wireless energy meters, it also logs the data with timestamp to a csv-file. See the processing-code at the bottom.
You might wounder why the red and green line (nr 1) sometimes differ? That's because I have the meter to transmit the average=red and the maximum=green power readings on every third power reading. This interval is easily changed by typing 1:1 or 1:4 to change the interval on meter 1 from to 1 or to 4 readings in between transmissions.
I had a hard time figuring out how to transmit this new interval from the computer nrf to the meter, because if I in between every transmission changed the nRF to a receiver, the power consumption would cause the whole meter to stop working.
This time I had to do some serious thinking, and I ended up using the possibility to alter the autoAck-payload. A function that normally sends an "OK" from the receiving nrf back to the transmitting nRF to confirm the transmission. I found out how to alter this value to send something like a "2" instead, or some other integer that would be a new interval. This was exactly what I needed, See the code at the bottom!
Her's the working Arduino code, first for the Energy Meter then for the computer connected receiver-Arduino. At the very bottom you have the processing code:
Here's the code for the receiving Arduino (connected to computer via USB)
And finally the Processing code that can be used to read and write to the computer connected Arduino through its serial connection (over USB)