## Thursday, December 15, 2011

### LED killed the fairy light

I noticed something while visiting my local hardware store today: they had no incandescent fairy lights this year. None at all. All LED. It's sad to see such an old technology die.

The "fairy light" is 129 years old this year. Its etymology comes from the Gilbert and Sullivan operetta Iolanthe which opened on 25 November 1882. The story is about fairies and someone had the bright idea of festooning some of the principle fairies with miniature light bulbs powered by a small battery. Apparently it caused quite a sensation and the term "fairy light" came into common use ever since.

### Installing Cadsoft Eagle 6 on Ubuntu 10.4

Update (5 Mar 2012): I've just been informed that libpng-1.4.8 has been replaced by libpng-1.4.9 and removed from ftp.simplesystems.org. I'll update the script in the next few days. In the mean time, please edit the script to change the version of libpng.

The recently released Eagle 6 from Cadsoft has a dependency on libpng 1.4, libjpeg 8, libcrypt 1.0, libssl 1.0. My Ubuntu 10.4 distribution has older versions of these libraries which Eagle 6 does not like.

There are a few posts on how to fix this, eg this one. However it relies on some helpful person's pre-built binaries. While I'm sure it's perfectly good, I'm just a little too paranoid to copy and execute code from an unknown source. So I set about downloading and building these libraries from source. I've written up the procedure as a bash script in case someone as paranoid as myself would like to do the same.

This script will build these libraries from source, and copy them to a directory specifically for use with Eagle.

This is the procedure:
1. First create an empty directory. Copy this script into it. Next open the script with an editor.
2. Set EAGLE_DEPS_DIR to a location where you want the libraries to be copied to after building (eg /home/joe/libeagle in my case)
3. I recommend that you verify the download locations of the library sources before you run this script. This is security best practice: it's generally not a good idea to download and execute code from an untrusted source. Once you are happy with the download URLs, then set I_HAVE_VERIFIED_DOWNLOAD_LOCATIONS=true
4. Save and run the script. If it's your first time running it, it will download the sources. Subsequent runs wont waste bandwidth if they are already there. Building the libraries will take a few minutes.
5. Verify the contents of the directory defined in EAGLE_DEPS_DIR. It should have the following files:
• libcrypto.so.1.0.0
• libjpeg.so.8.3.0
• libpng14.so.14.8.0
• libssl.so.1.0.0
• libjpeg.so.8 -> /home/joe/libeagle/libjpeg.so.8.3.0
• libpng14.so.14 -> /home/joe/libeagle/libpng14.so.14.8.0
6. Before running the Eagle installer or the Eagle software set environment variable LD_LIBRARY_PATH to include this directory (eg export LD_LIBRARY_PATH=/home/joe/libeagle )
Enjoy!

Update (30 Jan 2012): I received some improvements to the script from Leandro (wisleca@gmail.com).  Revision 2 is here.

## Tuesday, December 13, 2011

### Time tagging data streams using a short bash script

I've often had to write Arduino sketches and small PIC programs to read data from sensors for transmission to a PC over the serial link. This is mostly for testing and evaluating sensors in the lab – so I don't want to waste any more time than I have to writing software.

A common requirement is to have each sensor record time tagged. However implementing a real time clock on a Arduino, PIC etc can be a lot of hassle. It makes more sense to tag the record on the PC as it comes in.

Here is a short bash shell script that runs on a Linux PC which reads data from an input stream (usually the serial port) line by line and prefixes each line with the unix epoch time (seconds since 1 Jan 1970):

#!/bin/bash
while read line ; do
echo date +%s $line done  So, for example, right now I have an Arduino sketch polling a SHT75 temperature humidity sensor. The Arduino is writing a record (about 1 every second) with the current temperature and humidity. The data looks like this: 19.70 49.22 19.70 49.38 19.68 49.38 19.66 49.22  This is coming in on /dev/ttyUSB2 in this case. The above script is in file timetag.sh. On the PC I do: cat /dev/ttyUSB2 | bash timetag.sh > sensor.log sensor.log looks like this: 1323808719 19.70 49.22 1323808720 19.70 49.38 1323808721 19.68 49.38 1323808723 19.66 49.22  The data can now be plotted with the insanely useful gnuplot utility like this: $ gnuplot

set title "Temperature and Relative Humidity from SHT75 sensor"
set grid
set xlabel "Time"
set ylabel "Temperature (C) / Relative Humidity (%)"
set xdata time          # X axis is time
set timefmt "%s"     # Input file time format is unix epoc time
set format x "%R"   # Display time in 24 hour notation on the X axis
plot 'sensor.log' using 1:2 title 'T', 'sensor.log' using 1:3 title 'RH'


If you don't like the unix time notation, you can use alternative notations. See the manual page for the unix date command to get alternative time formats. You'll need to match the date format with the gnuplot 'set timefmt' command (help timefmt inside gnuplot will display available formats). For plots spanning more than one day you'll need to adjust time labeling with 'set format x' command (help set format time_specifier will provide information on this).

## Footnotes and references

[1] TMP006 Users Guide (SBOU107), page 2.

[2] Discussion on TMP006 at TI forums
http://e2e.ti.com/support/other_analog/temperature_sensors/f/243/t/117229.aspx

[3] TMP006 Users Guide (SBOU107),  Layout Guidelines,  page 6.

Diagram on principles of operation taken from TI promotional material.

## Tuesday, June 21, 2011

### The day GPS Selective Availability (SA) was switched off

I was going through some old archived projects recently and came across an interesting GPS track log I recorded on 2 May 2000.

For us GPS early adopters, this was a remarkable day: the day GPS became truly useful for terrestrial applications. I had left my Garmin GPS35 logging to capture the event, and here it is:

It may seem that the GPS was violently oscillating about the place and then stopped half way through the period of time recorded on the chart. Believe it or not it was completely stationary for the entire duration! So what happened?

First a little GPS history. GPS was conceived by the US military as an exclusively military navigation aid in the early 1970s.

In September 1983, Korean Airline Flight 007 was mistaken for a hostile military aircraft by the Soviets when it accidently strayed into their airspace. It was shot down with the loss of 269 lives. Following that disaster it was decided that GPS would be made available for civilian use to prevent such tragedies from happening again.

Naturally the military were concerned that the super accurate navigation provided by GPS could be abused. To address these concerns two signals were transmitted: one for military receivers with the full 10m accuracy, and a separate signal for civilian receivers with about 100m accuracy. 100m was considered adequate for aviation and marine applications at the time (but not accurate enough to allow a missile to hit a target). This degraded signal was known a Selected Availability (SA).

During the 1990s with the end of the cold war and an increasing civilian use of GPS the thinking at the US government was that the economic and safety benefit of removing SA far outweighed the risks.

So on 1 May 2000, the White House issued a press release announcing the end of SA with the following quote attributed to President Bill Clinton:
"The decision to discontinue Selective Availability is the latest measure in an ongoing effort to make GPS more responsive to civil and commercial users worldwide…This increase in accuracy will allow new GPS applications to emerge and continue to enhance the lives of people around the world."
Right on cue, on 2 May 2000 the SA was disabled and that moment was caught here. Only longitude is displayed for clarity, but latitude and altitude would have been oscillating with a similar amplitude. And a big difference it made, opening up a mass market for consumer GPS devices.

[Aside: SA was temporarily removed at some point [can't find a date] during the first Persian Gulf War in 1991 because of a shortage of military GPS receivers. Instead civilian units were used. These were just as accurate with SA switched off. SA was restored again on 1 July 1991.]

References:
http://ngs.woc.noaa.gov/FGCS/info/sans_SA/docs/statement.html

27 Dec 2018: I thought I had lost the original data file, but found it a few days ago on an old archive CD-ROM while cleaning for Christmas. I created a better chart showing both east-west deviation and also a north/south deviation as function of time.    Data and Gnuplot source files are available here: https://github.com/jdesbonnet/GPS_SA_switch_off

## Tuesday, May 24, 2011

### Arduino to Android IO on the cheap (aka Poor Man's NFC)

Summary: This article describes how to implement a very low bandwidth one way communication channel between an Arduino (or any other microcontroller) and an Android device using nothing more than about a meter of magnet wire, a resistor and diode. Links to a software sketch for the Arduino and the Android source code is included.

A cheap and simple way of communication between a microcontroller (eg Arduino) and an Android device is surprisingly difficult to achieve. The most practical means of accomplishing this is to use a Bluetooth or WiFi module adding significantly to the cost of a project (in the order of $30 -$60).

This is a little hack that allows very low bandwidth communications in one direction for practically no cost. It's not practical for most applications, but I thought the idea was sufficiently interesting to explore and write up in a blog post.

You'll need the following:
• An Android phone or device which features a magnetometer (electronic compass). I'm not aware of any device without one.
• An Arduino or other microcontroller (my examples are for the Arduino)
• About 1 meter of  enameled copper wire (magnet wire), although any thin insulated wire will do.
• The Android 'Tricorder' app (available free from the Android app store)
• A 120 ohm resistor
• A diode (optional)
Make a coil by wrapping the 1 meter of magnet wire around something cylindrical  (eg AAA cell) with a diameter about 1cm. You should get about 30 turns from 1 meter. The diameter or number of turns is not important as long as they are in that ball park. Wrap a light thread around the coil to help keep its shape.

Connect the coil as illustrated in the schematic above. The 120 ohm resistor limits current draw to about 40mA which is the maximum allowed [1]. The purpose of the diode is to protect the Arduino from an EMF kick when pin 13 is driven low. This is known as a  flyback diode. With only 30 turns and an air core, you'll probably get away without using it. But it's good practice to include it.

 Tricorder app displaying magnetic field. For theHTC Desire the signal is strongest at the bottomleft of the LCD where the magnetometer is located This is likely to vary from device to device.
Now to locate the magnetometer. It's location will vary from device to device. This is where the tricorder comes in handy. First load this sketch on the Arduino before you connect the coil.

/**
* Generate 1Hz square wave on pin 13
*/
void setup() {
pinMode(13,OUTPUT);
}

void loop() {
digitalWrite(13,1);
delay(500);
digitalWrite(13,0);
delay(500);
}


When the coil is disconnected you should see the Arduino's LED blink. Now connect the coil. The LED should stop blinking at this point because the coil shorts the LED -- this is expected. Start the Tricorder app and switch to MAG mode and start scanning. Methodically scan the coil across the surface of the Android phone until you start seeing a strong square wave. Where the amplitude of this signal peaks is where the magnetometer is located. You should see a similar square wave if you position the coil at the same location on the bottom surface of the device. Use some tape to keep it positioned there.

Now we have a way of signalling the Android. The temptation at this point is to connect the coil to the Arduino UART and to start firing data at 9600bps. Unfortunately this isn't going to happen for a few reasons:

We are limited by the magnetometer sampling rate available to us by the Android OS. Here is a histogram of time-between-samples from a HTC Desire running Froyo (Anrdoi 2.2) at maximum sampling speed:

We can see here that almost all the samples come in at between 18ms and 25ms. There are a few outliers going all the way up to 45ms but there numbers are so few we can ignore them. This means we are limited to a maximum of a 40Hz sampling rate. If we drive the coil with a digital IO line that immediately caps our maximum bandwidth at 40bps.

But does the magnetometer respond quickly enough?

This Arduino sketch energizes the coil with a square wave of starting at 500Hz and decreases to about 1Hz over a few seconds.

int i;
int d = 1;
void setup() {
pinMode(13,OUTPUT);
}

void loop() {
for (i = 1; i < 500; i+=d) {

// Increase increment as frequency decreases
d = (i>>6) + 1;

digitalWrite(13,1);
delay(i);
digitalWrite(13,0);
delay(i);
}
}



Here is the magnetometer data:

As expected high frequencies (on the left) are not be detected. It seems that we only get good pickup when the frequency drops to about 6Hz!

For encoding I'm going to use NRZ (non return to zero) similar to that used in RS232 with a bit period of 140ms (about 7 bps). The Arduino's UART lower limit is 300bps, so I can't use it to generate the signal.  So I'm going to 'bit bang' the signal in software. Likewise, on the Android I'm going to have to decode in software also.

#define BIT_DELAY 140

int i;
char *text = "Hello World! ";

void setup() {
pinMode(13,OUTPUT);
}

void loop() {

char *s;
s = text;
while (*s != 0) {
transmitByte(*s++);
}

delay (BIT_DELAY*10);
}
/**
* Bit bang a byte
*/
void transmitByte (byte c) {

// Start bit
digitalWrite (13,1);
delay(BIT_DELAY);

// Data bits
for (i = 0; i < 8; i++) {
digitalWrite (13, ( (c&0x80)!=0 ? 1 : 0) );
delay(BIT_DELAY);
c <<= 1;
}

// Stop bit
digitalWrite (13, 0);
delay(BIT_DELAY);
}


Here it is in action:

The Android source is available here.

## Potential improvements

My simple example uses a digital IO line to drive the coil. The Android magnetometers typically have at least 8 bits of resolution per channel [2]. It may be possible to squeeze another few bits per symbol by driving the coil with a DAC [3]. For example, 4 power levels can be used to encode 2 bits per symbol. The odd bit error  can be corrected using forward error correction.

Also the magnetometer has three channels (X,Y and Z). It may be possible to construct a set of coils that excite the X,Y and Z channels independently … multiplying bandwidth by a further x3. Another thought: I've only discussed digital communication with the Android. Some applications might only require an analog signal.

These ideas are left as an exercise for the reader, but I’d love to hear how you get on if you try it.

## Footnotes

[1] Googleing "Arduino pin 13", one is lead to believe there is a current limiting resistor in series with the MCU pin. However looking at the schematics, the tap for the pin 13 header comes *before* the resistor: so the resistor does not limit current. I only discovered this at the end of the experiment while proofing this post. Omitting the resistor did me no harm, but would advise to include the resistor to be safe. We need as much current as possible (more current means more magnetic flux in the coil). The Arduino Duemilanove datasheet specifies a maximum draw of 40mA on a IO pin, so 120 to 150 ohms should do the trick. If you need more current you'll need to use a transistor.

[2] The HTC Desire uses a AKM Semiconductor AK8973 3-axis magnetometer which uses a combination of a 8 bit ADC and a 8 bit offset DAC to yield up to 12 bits of equivalent resolution spanning +/- 2000µT of magnetic flux.

[3] The Arduino does not have a true DAC, however DAC functionality can be achieved by passing the PWM output through a low pass filter.

## Thursday, May 19, 2011

### Changing Mimetex fonts

 An example of Mimetex in action
Mimetex is a handy little add-on for web applications that will render math expressions in TeX/LaTeX syntax and convert them directly to GIF images. It's just one binary executable file which is normally deposited into the "/cgi-bin" directory of the web server. Everything is compiled into the executable, including the fonts. Which is nice: no configuration... no font directories... Simple!

The mimetex distribution comes with the default Computer Modern fonts built in. I was recently asked to change these fonts to a sans-serif font. In case anyone else needs to do something similar I'm documenting what I did in this post.

I'm assuming a Ubuntu Linux distibution (although it should work with other Linux/BSD distros) and you'll need a full TeX/LaTeX distribution installed.

Then download this script. It's good practice to review it first before running it.

The script will:

2) Render the sans-serif version of Computer Modern to a format that can be used by mimetex
3) Patch mimetex.h to use the sans-serif fonts instead of the default Computer Modern font
4) Compile a new mimetex binary executable file

The results?

Before:

After:

What's going on under the hood?

The starting point is a Metafont description of the new font. Fortunately there is a sans-serif variant of computer modern available in Metafont format (cmss and cmssi) included in the TeX distribution.

The process of adding new fonts involves rendering the Metafont file into a bitmaps (.gf) files. Those binary .gf files are then converted into a ASCII printable format using "gftype -i" and then the gfuntype utility (shipped with Mimetex) will convert that to a C header (.h) file. The fonts are run off at various sizes and all the resulting .h files are concatenated together to form 'texfonts.h' which is compiled into the executable.

Is it possible to compile in Type1?

As far as I can tell, there is no easy way to use fonts in formats other than Metafont. And I can't find any way to convert Type1 and other formats to either Metafont or the intermediate .gf bitmap files. I'd be delighted to hear about any suggestions if this is possible.

Also it should be pointed out, there are probably better alternatives to Mimetex available nowadays, eg Mathtex and Mathjax.

## Saturday, April 16, 2011

### 'Smart' electricity meter based on Efergy Elite monitor, part 2

Summary: In part 1, I documented the Efergy Elite’s radio protocol and wrote a PIC program that ran in a tight loop decoding the data and sending it to a serial port. This post improves upon the decoding technique used allowing for other applications (eg temperature monitoring) to multi-task on the same PIC. A simple control loop multitasking framework using interrupts to capture time critical events is explained.

The ultimate goal of this project is a electricity consumption monitor that provides real time feed back and also logs historical power use for analysis and report generation. For the moment my focus is feeding the data to a PC/laptop. In reality a more power efficient logging device will be needed. But that's for a future post.

Recently I wanted to update this receiver to include data from temperature sensors and output data from both the Efergy Elite and the temperature sensors to a single serial port.

However the tight timing loops which are continuously running make it near impossible to perform any other task. Fortunately the PIC has lots of useful hardware that can be brought to bear on this problem. Timing pulses with a loop is rather clumsy, inaccurate and wasteful of system resources. Almost all PICs have timers and interrupts which can be used for this task.

By using this peripheral hardware a lot of the decoding grunt work can be happen silently in the background, freeing up the CPU for other stuff.

## Simple Multitasking with a PIC

Although not a proper multitasking processor such as a Pentium, a very simple form of multitasking can be easily achieved with a PIC. This comprises a master loop which calls application service routines for each application in turn. This is often called “simple control loop multitasking”.

The application service routines check to see if there is any work to be done. If not it immediately exits and the control loop then pass control the the next application service routine. If there is work to be done, the application service routine attempts to tackle as much as can be achieved in it’s allocated time. If all the work cannot be completed in time, it must relinquish control prematurely and continue the task on the next call.

void main (void) {

// Initialize apps
initAppA();
initAppB();
initAppC();
initAppD();

// Main loop
while (1) {
appA();
appB();
appC();
appD();

// Clear watchdog timer
CLRWTD();
}
}


 Architecture diagram of simple control loop multitasking with interrupts used to capture time critical events.

In order to be responsive the main loop must iterate many times a second. The iteration frequency will depend on the nature of the application(s). 1kHz is a common choice. At 1kHz the entire loop must complete in 1ms and each app service routine must take no more than 250µs (assuming there are 4 applications requiring equal CPU time).

These routines must be written so as not to use more than their allocated time slice. If a task cannot be accomplished in that time frame it must be broken into smaller work units.

Unlike a modern preemptive multitasking operating system such as Linux these constraints are not enforced. A badly written service routine will affect the performance of the entire system. For example a deadlock in one application will cause the entire system to fail. One safeguard against rogue applications is to enable the Watchdog Timer and clear it on each iteration of the loop. Should one application lock up the system will reset.

Interrupts can be used to capture time critical events. The ISR (Interrupt Service Routine) is called (almost) the instant the event occurs. Its job is to store the event for the attention of the application service routine whenever it gets control of the processor. It’s often a good idea to buffer these events in case more than one arrives before the service routine gets its turn to run.

## Efergy Elite decoding

A quick recap on the Efergy Elite setup. A sensor mounted in the utility meter box transmits by 433MHz radio a power reading to the display unit every 6, 12 or 18s (configurable). On the display unit PCB I tapped into the radio base band output and connected this to a low cost PIC MCU. It does the job of decoding the signal and sending a nicely formatted record to the PC via serial IO.

Bits are encoded on the base band signal using digital FSK (Frequency Shift Keying). Three square wave cycles of 2ms duration in total (ie 1500Hz) is a logic 0 and 4 square wave cycles of 2ms duration (ie 2000Hz) is a logic 1.

Each packet is prefixed by a synchronization header of 0xAB 0xAB and 0x2D. This is followed by 8 octets (bytes) of data and one octet checksum. See previous post [link] for details.

The decoding process starts with the radio hardware which outputs the base band signal. Using pulse width measurements the symbols (bits) are decoded. First the bits are are shoved onto a 16 bit shift register until the end sync header is identified (ie the contents of the shift register will read 0xAB2D). Then 8 octets of data is read followed by one checksum octet (the checksum is the arithmetic sum of the 8 data octets).

The choice of what to implement in the ISR and what to implement in the application service routines is sometimes not clear. The rule of thumb is to keep the ISR as small and fast as possible. I had originally considered using the ISR to time pulses and send pulse durations to the application layer. As there can be as little as 250µs between pulses the entire main loop would have to execute in under that time. That’s only 250 instructions on a 4MHz clocked PIC. Not enough!

For just a few more instructions the pulse to symbol decoding can happen in the ISR thus allowing for up to 2000µs between application service routine calls.

To improve matters further, instead of storing one symbol at a time, I push the decoded symbols into a buffer (implemented as a 8 bit shift register) allowing for up to 16000µs between calls.

For the first attempt I connected the radio base band signal to the INT pin (RB0), traped INT interrupts and used Timer1 to measure the pulse widths. Timer1 is a 16 bit timer which can be clocked using the system clock divided by 4. If you’re using the 4MHz internal clock that’s a convenient 1µs per clock tick.

There are a few gotchas when using interrupts. For example: variables shared between the ISR and main program must be declared with the “volatile” modifier. When accessing state information which can be manipulated by the ISR, it is often necessary to briefly disable the interrupt while reading to ensure that an interrupt does not case the state to appear corrupted.

 Measuring pulse width with INT interrupt.
The PIC can be programmed to trigger INT on a rising edge or falling edge. But not both at the same time. To measure pulse widths I’ll need both. The work around is to alternate the triggering mode.

I’m measuring inverse pulses (ie the duration of time when the signal is at low voltage). So when waiting for a pulse to arrive, set to trigger on a falling edge. In the ISR, record the clock and set trigger mode to rising edge. The next invocation of the ISR will occur at the end of the pulse. Subtract the clock from the previously recorded value -- that is the pulse width. Now reset INT to trigger on a falling edge again for the next pulse.

## An alternative implementation using Capture/Compare

Microchip PICs have so much peripheral hardware that there is often several ways of solving the same problem. The Capture/Compare module is probably better suited for this problem. The INT approach does have one advantage though: if there is nothing else to do the device can be put in low power mode with the SLEEP instruction. Activity on INT will automatically wake the device up. I’ll post that implementation in a separate blog post.

## The main control loop

My main loop looks like this:

// Main control loop.
while (1) {

// AppA: Decode Efergy Elite signal.
if (efergy_elite_interrupt_decode()) {

// Have a complete record

// Extract single phase power reading (12 bits)
power = ((ee_buf[3]&0x0f) << 8) | ee_buf[4];

// Display full record on the serial port
for (i = 0; i < 8; i++) {
writeHex(ee_buf[i]);
putch (' ');
}
crlf();
}

// AppB: Blink LED if power use above threshold
if (power > POWER_THRESHOLD) {

// Cause LED to blink every 4096 iterations
if ( (t&0x0fff) == 0) {
DEBUG_PIN = !DEBUG_PIN;
}
} else {
// LED off if below threshold
DEBUG_PIN=0;
}

// Increment iteration counter
t++;

// Clear watchdog timer
CLRWDT();
}
}


This has just two simultaneously running tasks:
• One to decode telemetry from the Efergy Elite and write the data to the serial port
• One to blink a LED if power levels are above some threshold
Instead of putting each application into a separate service function as in the template above, I've got blocks of code in the main loop as the code is short and simple.

The LED blinker (AppB) illustrates how to write these application service routines. A simplistic approach would be to compare power consumption against the threshold then turn on the LED, execute a delay loop for 0.5s, turn the LED off and delay again for another 0.5s. That will work, but violates the principle that the code should execute as quickly as possible (taking a whole second to complete a blink).

A smarter approach is implement LED blinking with a timer. I added an iteration counter to the main loop which acts as a low accuracy timer (it seemed easier than using the PICs built in timers). This way the code only takes a few instructions to execute.

The code which writes the record data to the serial port could be optimized in a similar way, writing just one character to the serial port per iteration. But that's an exercise for another day.

## The Hardware

You will need the following:
• Efergy Elite electricity monitor (obviously)
• A PIC 16F627A or 16F628A (or any other PIC, but you may need to modify the code a little).
• 1 LED
• 1 resistor
• A suitable PIC programmer. I use a PICKit2 from Microchip (about $30) • Breadboard (or other prototyping system) • Logic level Serial IO to PC interface (see text below) This hack requires that you solder a wire to the base band pin or test pad of the Efergy Elite receiver unit. See my previous blog post on how to do this. You will also need a wire for the battery ground. Beware that this will void your warranty -- so only proceed if you know what you are doing.  Schematic of Efergy Elite decoder using a PIC 16F627A or 16F628A (or equivalent). Once upon a time interfacing a serial IO port to a PC was a straightforward if somewhat laborious task. PCs had a RS232 port which used +/- 13V levels which was not compatible with logic levels (usually 0 and 5V). You needed a level converter. A MAX232 chip + associated capacitors being one of the most popular solutions. Fortunately, nowadays the RS232 is very rarely found on modern equipment. So how do you interface serial IO at logic levels to a PC? There are many options available, and sadly may require that you purchase some hardware. But the good news is that all of these options are useful tools which can be repurposed for other projects. Here are some options: • FTDI cable available from SparkFun.com (DEV-09718), CoolComponents.co.uk and many others. Cost about$18.
• The Dangerous Prototypes Bus Pirate available from SeeedStudio.com (\$30 -- but you get a whole load of extra functionality with that. Well worth it.)
• An old Nokia phone cable
• Any development board that features a USB/Serial IO chip can probably be easily hacked for this purpose, including the Arduino, TI MSP LaunchPad etc. (Although you'd probably want to ask yourself if you are better off using the MCU on the development board instead of a separate PIC. If you want to see this decoder implemented for other MCUs leave a comment at the end of the blog post and I'll see what I can do.)

 Annotated photograph of setup required to decode telemetry from a Efergy Elite electricity monitor and relay to PC.

A note on powering the PIC: as this is currently very much a prototype I haven't considered how I might power this device. Right now I'm using the PICKit2 to supply power via the ICSP (3.3 - 5V should work). Practical options are to pull the battery positive terminal out of the Efergy Elite display unit and use that to power the device. If connected to a PC via a FTDI cable, these cables usually have a +5V line which will deliver plenty of current. Or use a separate battery or wallwart power supply.

If running successfully this program will output to the serial port each record from the power sensor as it arrives (every 6, 12 or 18s). The output looks something like this:

EM 0.2.0
00 0D 5A 40 6E 00 01 00
00 0D 5A 40 6E 00 01 00
00 0D 5A 40 73 00 01 00
00 0D 5A 40 6E 00 01 00
00 0D 5A 40 6E 00 01 00
00 0D 5A 41 BF 00 01 00
00 0D 5A 41 BE 00 01 00


As for implementing the temperature sensors I mentioned at the start -- that's for another day. So right now it’s not a terribly exciting application, but could form the basis of something more useful.

The code can be downloaded here. It’s written for the HI-TECH PICC compiler, and has been tested on PICs 16F627A and 16F628A. It should be easy to adapt to other PIC compilers and PIC devices, or indeed other MCU families.