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 it's 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 it's a switching supply, and only pulls power during the peak of the voltage curve.

A laptop plugged in, switching power supply

Now let's try plugging in a 40W incandescent light bulb. You'll notice that unlike the switching supply, the current follows the voltage almost perfectly. That's because a lightbulb is just a resistor!

40W lightbulb

Finally, let's 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, it's 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

Install python & friends

The software that talks to the XBee is written in python. I used python because it's 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 it's 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.

  1. Download and install python 2.5 from 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.
  2. Download and install pyserial from the package repository (this will let us talk to the XBee thru the serial port).
  3. If you're running windows download and install win32file for python 2.5 (this will add file support).
  4. 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 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.

Basic configure

We'll have to do a little bit of setup to start, open up the 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 it's some COMx port, under linux and mac it's something like /dev/cu.usbserial-xxxx check the /dev/ directory and/or dmesg.

Save the script with the new serial port name.

Test it out

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 it's Terminal, under windows, it's 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
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, it's time to tweak it. For example, it's 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 -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 it's 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 it's off there is a 'DC offset' to the Amp readings, as this graph shows:

See how the Amp line (green) is steady but it's not at zero, it's at 0.4 amps? There is a 'DC offset' of 0.4 amps.

OK, open up the 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 it's not 0W is that, first off, there's a little noise that we're reading in the A/D lines, secondly there's power draw by the Kill-a-Watt itself and finally, 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.

Logging data

It's nice to have this data but it would be even nicer if we could store it for use. Well, that's automatically done for you! You can set the name of the log file in the 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 script and set:

# Twitter username & password
twitterusername = "username"
twitterpassword = "password"

to your username and password on twitter. You can make an account on if you don't have one.

Then run the script as usual. Every 8 hours (midnight, 8am and 4pm) the script will send a tweet using the Twitter API.

Then check it out at your account:
Last updated on 2015-11-20 at 05.06.53 PM Published on 2014-12-03 at 02.21.00 PM