Now that the hardware is complete, we come to the exciting part: running the software that retrieves the data from our receiver XBee and saves it to our computer or uploads it to a database or updates our twitter feed or....whatever you'd like!
Here is how it works, the XBee inside the Kill-a-Watt is hooked up to two analog signals. One is the voltage signal which indicates the AC voltage read. In general this is a sine wave that is 120VAC. One tricky thing to remember is that 120V is the 'RMS' voltage, and the 'true voltage' is +-170VDC. (You can read more about RMS voltage at wikipedia basically its a way to indicate how much 'average' voltage there is.) The second reading is the AC current read. This is how much current is being drawn through the Kill-a-Watt. If you multiply the current by the voltage, you'll get the power (in Watts) used!
The XBee's Analog/Digital converter is set up to take a 'snapshot' of one sine-cycle at a time. Each double-sample (voltage and current) is taken 1ms apart and it takes 17 of them. That translates to a 17ms long train of samples. One cycle of power-usage is 1/60Hz long which is 16.6ms. So it works pretty well!
Lets look at some examples of voltage and current waveforms as the XBee sees them.
For example this first graph is of a laptop plugged in. You'll see that its a switching supply, and only pulls power during the peak of the voltage curve.
A laptop plugged in, switching power supply
Now lets try plugging in a 40W incandescent light bulb. You'll notice that unlike the switching supply, the current follows the voltage almost perfectly. Thats because a lightbulb is just a resistor!
Finally, lets try sticking the meter on a dimmable switch. You'll see that the voltage is 'chopped' up, no longer sinusoidal. And although the current follows the voltage, its still matching pretty well.
Light bulb on dimmer switch
The XBee sends the raw data to the computer which, in a python script, figures out what the (calibrated) voltage and amperage is at each sample and multiplies each point together to get the Watts used in that cycle. Since there's almost no device that changes the power-usages from cycle-to-cycle, the snapshot is a good indicator of the overall power usage that second. Then once every 2 seconds, a single snapshot is sent to the receiver XBee
The software that talks to the XBee is written in python. I used python because its quick to develop in, has multi-OS support and is pretty popular with software and hardware hackers. The XBees talk over the serial port so literally any programming language can/could be used here. If you're a software geek and want to use perl, C, C#, tcl/tk, processing, java, etc. go for it! You'll have to read the serial data and parse out the packet but its not particularly hard.
However, most people just want to get on with it and so for you we'll go through the process of installing python and the libraries we need.
- Download and install python 2.5 from http://www.python.org/download/ I suggest 2.5 because that seems to be stable and well supported at this time. If you use another version there may be issues
- Download and install pyserial from the package repository (this will let us talk to the XBee thru the serial port)
- If you're running windows download and install win32file for python 2.5 (this will add file support)
- Download and install the simplejson python library (this is how the twitter api likes to be spoken to) you'll need to uncompress the tar.gz file and then run the command "python setup.py install" to install
Now you can finally download the Wattcher script we will demonstrate here! We're going to download it into the C:\wattcher directory, for other OS's you can of course change this directory
We'll have to do a little bit of setup to start, open up the wattcher.py script with a text editor and find the line
SERIALPORT = "COM4" # the com/serial port the XBee is connected to
change COM4 into whatever the serial port you will be connecting to the XBee with is called. Under windows its some COMx port, under linux and mac its something like /dev/cu.usbserial-xxxx check the /dev/ directory and/or dmesg
Save the script with the new serial port name
Once you have installed python and extracted the scripts to your working directory, start up a terminal (under linux this is just rxvt or xterm, under mac its Terminal, under windows, its a cmd window)
I'm going to assume you're running windows from now on, it shouldn't be tough to adapt the instructions to linux/mac once the terminal window is open.
Run the command cd C:\wattcher to get to the place where you uncompressed the files. By running the dir command you can see that you have the files in the directory
Make sure your transmitter (Kill-a-Watt + Xbee) is plugged in, and blinking once every 2 seconds. Remember it takes a while for the transmitter to charge up power and start transmitting. The LCD display should be clear, not fuzzy. Make sure that there's nothing plugged into the Kill-a-Watt, too. The RSSI (red) LED on the receiver connected to the computer should be lit indicating data is being received. Don't continue until that is all good to go!
Now run python by running the command C:\python25\python.exe wattcher.py
You should get a steady print out of data. The first number is the XBee address from which it received data, following is the estimated current draw, wattage used and the Watt-hours consumed since the last data came in. Hooray! We have wireless data!
Now that we have good data being received, its time to tweak it. For example, its very likely that even without an appliance or light plugged into the Kill-a-Watt, the script thinks that there is power being used. We need to calibrate the sensor so that we know where 'zero' is. In the Kill-a-Watt there is an autocalibration system but unfortunately the XBee is not smart enough to do it on its own. So, we do it in the python script. Quit the script by typing in Control-C and run it again this time as C:\python25\python.exe wattcher.py -d note the -d which tells the script to print out debugging information
Now you can see the script printing out a whole mess of data. The first chunk with lots of -1's in it is the raw packet. While its interesting we want to look at the line that starts with ampdata:
ampdata: [498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 497, 498, 498, 498]
Note: If you're getting -1's instead of nice ~500 numbers, check the XBee is set up right and has the correct wires going to the correct A/D pins. If you're getting 1024's that probably means you forgot to tie VREF to VCC in the last step. Remove the Kill-a-Watt from power and go back to repair it
Now you'll notice that the numbers are pretty much all the same. That's because there's nothing plugged into the tweetawatt and so each 1/60 Hz cycle has a flat line at 'zero'. The A/D in the XBee is 10 bits, and will return values between 0 and 1023. So, in theory, if the system is perfect the value at 'zero' should be 512. However, there are a bunch of little things that make the system imperfect and so zero is only close to 512. In this case the 'zero' calibration point is really 498. When its off there is a 'DC offset' to the Amp readings, as this graph shows:
See how the Amp line (green) is steady but its not at zero, its at 0.4 amps? There is a 'DC offset' of 0.4 amps
OK, open up the wattcher.py script in a text editor.
vrefcalibration = [492, # Calibration for sensor #0 492, # Calibration for sensor #1 489, # Calibration for sensor #2 492, # Calibration for sensor #3 501, # Calibration for sensor #4 493] # etc... approx ((2.4v * (10Ko/14.7Ko)) / 3
See the line that says # Calibration for sensor #1? Change that to 498
vrefcalibration = [492, # Calibration for sensor #0 498, # Calibration for sensor #1 489, # Calibration for sensor #2 492, # Calibration for sensor #3 501, # Calibration for sensor #4 493] # etc... approx ((2.4v * (10Ko/14.7Ko)) / 3
Save the file and start up the script again, this time without the -d
Now you'll see that the Watt draw is 2W or less, instead of 40W (which was way off!) The reason its not 0W is that, first off, there's a little noise that we're reading in the A/D lines, secondly theres power draw by the Kill-a-Watt itself and fianlly, the XBee doesn't have a lot of samples to work with. However <2W is pretty good considering that the full sensing range is 0-1500W
Here is the graph with the calibrated sensor:
See how the Amps line is now at 0 steady, there is no DC offset
Its nice to have this data but it would be even nicer if we could store it for use. Well, thats automatically done for you! You can set the name of the log file in the wattcher.py script. By default it's powerdatalog.csv. The script collects data and every 5 minutes writes a single line in the format Year Month Day, Time, Sensor#, Watts for each sensor.As you can see, this is an example of a 40W incandescent lightbulb plugged in for a few hours. Because of the low sample rate, you'll see some minor variations in the Watts recorded. This data can be easily imported directly into any spreadsheet program
Finally we get to the tweeting part of the tweet-a-watt. First open up the wattcher.py script and set
# Twitter username & password
twitterusername = "username"
twitterpassword = "password"
to your username and password on twitter. You can make an account on twitter.com if you dont have one.
Then run the script as usual. Every 8 hours (midnight, 8am and 4pm) the script will sent a twitter using the Twitter API
Then check it out at your account: