September 2013


Wireless SSDV images from a canon camera using RTTY on CHDK

CHDK (canon hackers development kit) is a temporary firmware hack that allows you to run custom code and commands on canon compact digital cameras. It is often used on high altitude balloon flights to run an intervalometer to take a photo every x number of seconds. The scripts are written in LUA or uBasic, with LUA seeming to be the preferred language. You can take this one step further and use CHDK it to log data such as CCD temperature like Mark Ireland (S_Mark) from Stratodean.


Now the above is pretty neat, but up until starting this project I really underestimated the power of a camera running CHDK! In the article below I will be using a Canon PowerShot A530 to broadcast photographs over a Radiometrix NTX2 FSK radio module, in a similar way Dave Akerman does on his Raspbbery Pi payloads.


SSDV (Slow Scan Digital Video) is a packetised digital form of SSTV (Slow Scan TeleVision). It can be used to transmit small images along with the regular telemetry transmitted by a payload during flight. Any digital mode that can carry text or data can be used, although the current implementation is limited to 8-bit RTTY (Radio TeleTYpe).

This is a vast improvement over simply sending the JPEG data as it supports forward error correction in the (likley) event that some bits are scrambled in the receiving process. It also supports integration into the UKHAS distributed listener platform, a group of enthusiasts who tune their HAM radios and SDR’s into balloons and upload the data to a central server.


RTTY was originally used on teleprinters in the form of Baudot (5 bit). An RTTY transmitter broadcasts a continuous carrier which shifts up and down in frequency depending on the bit being sent. This produces the MARK (upper) and SPACE (lower) tones. You can see these two tones in the waterfall above). This is known as FSK (frequency shift keying). In this case we will not be using Baudot, instead we will be using 8 bit ASCII with one start and one stop bit to send a byte of SSDV data at a time.

On the CHDK wiki I started to read up on how toggling one of the cameras LEDs can be used to dump the firmware of a camera over serial. So I started off trying to produce RTTY by toggling an LED on and off. Whilst the code behind this worked, the timing was very inconsistent and I struggled to get anything above 33 bits per second. Not ideal for sending images! I figured there must be an alternative.

The camera has an ARM processor and runs VxWorks as an operating system, A popular OS for embedded devices ranging from mobile phones to the Mars Curiosity Rover. Using the cameras UART connections it is possible to access the VxWorks event shell and issue basic commands to the camera. The UART connections on the A530 are located under the display and require some fiddly soldering to the unpopulated chip footprint to connect! (Red wire below is the Tx) The UART’s default settings are 115200 baud 8N1.

Image from CHDK wiki

Upon experimenting with the UART connected to PuTTY running on my PC, using a USB to TTL converter. I found that the Printf command seemed suitable for writing text to the port. The Printf command is a native call and must be registered by callingSystemEventInit in the VxWorks shell before using it.

To call a native VxWorks function from LUA you must enable native calls in the CHDK menu (ALT, menu, misc, enable lua native calls [check]). Commands can then be executed using event_proc as below.


call_event_proc(‘Printf’,’Script Started’)

To make the UART suitable for RTTY the baud rate will need to be dropped to something a little more sensible, in my testing both 50 baud and 600 baud worked well, however 300 baud seemed to drop characters. Reyalp on the CHDK wiki helped me out by showing me how ioctl() can be used to change the UART settings, and finding the memory addressesfor it along with the function codes for some of the commands from VxWorks.

fd=call_func_ptr(0xffec8b34,”/tyCo/0″,0,0) –fptr_open (Opens the UART on fd)
print(“fd:”,fd) –fd>0 if the UART was opened successfuly
status=call_func_ptr(0xffec8630,fd,4,600) –fptr_ioctl(4=FIOBAUDRATE,600=baud)
status=call_func_ptr(0xffec8630,fd,3,0) –FIOSETOPTIONS,3=OPT_RAW,0=OFF (Stops VxWorks messing with null bytes and line returns)
print(“status:”,status) –0 probably means success
call_func_ptr(0xffec84f0,fd) –Closes down fd

The 0xffec8630 function address points to ioctl on the a530, this will probably vary from camera to camera and can be found in stubs_entry.s for your camera in the CHDK source. The function codes for the various icotl commands in VxWorks can then be looked up here.

Initially I had a lot of trouble with VxWorks messing with some bytes I was sending to the UART, such as 0×00, and 0x0D being automatically followed by a 0x0A (need to check this). This can be overcome by setting the OPT_RAW option in  FIOSETOPTIONS as above.

I found that printing a whole binary file in one go as a single string did not work, so I use a for loop to print each byte in a string to the UART, rtty being the string name to print below. (note in LUA strings start at character position 1)

for d=1,string.len(rtty),1 do

Now from this point I could encode a JPEG image to SSDV using Phil Heron’s [fsphil] C based encoder running on a Linux PC. Copyy the files to the SD card,and then read them out to the UART and have dl-fldigi decode them perfectly. The next step is where the real fun started, compiling the C based SSDV encoder into the source of CHDK…


With some more advice from Reyalp at CHDK, Phil and I had a go at setting up the environment required to build CHDK, with myself working on Windows and Phil working on Linux. After a couple of days of Phil installing various bits of Linux software such as GCC, and myself trying to download one of the thousands of CHDK source trunks that would actually build, we managed to succeed at about the same time (For some reason the windows GUI decided to auto-update and started working from that point…). Phil had a go at implementing the C code from his SSDV encoder into the source and we had a semi-working encoder after just one evening! It took a few more revisions of the firmware as we tested different ways of calling the functions and addressing memory.

CHDK build with SSDV for a530 ONLY!

NOTE: I have built the firmware for every platform supported so to download a binary, scroll down…

You can use CHDK-Shell GUI under windows to compile the patched trunk for your camera. Or if you are a Linux super genius you can build it using GCC. For windows head to the page linked above. Read it ALL! Download the latest FULL program, run it, enable online mode, let it update, restart. Keep doing the above and eventually you will be up to date enough for it to automatically download the most up to date trunk for you to use.

Change the trunk in CHDK_Shell GUI to the trunk we just patched:selectingtrunk


CHDK_Shell should restart and you can tick off your cameras firmware on the list then click “compile selected”select camera and build

Unzip the binaries found in chdk\trunk\trunk3040_PATCHED\trunk\bin (or wherever) to your SD card and boot CHDK, its that easy!

I have had a go at building for every platform available so if you are feeling lazy, give one of these a go. TRUNK3039_SSDV BINARIES DOWNLOAD (Thanks to Dom for hosting the files!)

The first step to encode a JPEG image from LUA is to open the file and read it into memory (JPEG string).“A/DCIM/101CANON/filename.jpg”)

We now have to create a new encoder object which we can feed the JPEG file into (specifying the callsign as CALL and imageID as 0).

s =“CALL”, 0)

Now we feed the JPEG file (held in the variable we set earlier) into our SSDV encoder object above.


Now we need to enter a loop to make the object encode each packet, checking if the encoding is complete each time so we can jump out of the loop.

i=1 –packet encoder counter
rtty = “” –initialize output string
repeat –start loop
print(“Packet “,i,” encoding”)

–print encoder status message to screen
r, packet =

–Read the output packet from the encoder, r being encoder status and packet being 1 SSDV packet.
if r == SSDV_OK then
–If we have data, then do something with it
rtty = rtty .. packet –concatenate new packet onto the end of output stream
i=i+1 –increment packet counter
until r ~= SSDV_OK –keep trying to get new packets until the encoder reaches EOF
ssdvenc.close(s) –Close the encoder

So now we have SSDV data in the rtty string. All we have to do is loop through each byte in the string and print it out the the UART

for d=1,string.len(rtty),1 do –loop through each byte

–print byte to UART as a byte

You *should* now have 600 baud SSDV flowing out of your hardware uart and into your ntx2. With a suitable voltage divider you can set the shift to 600Hz and have this decoding in dl-fldigi and uploading to the web!

Whilst Phil was compiling the new source, I worked on integrating the transmitter into the camera. The battery bay worked out to be the perfect size, with space for an SMA connector in the battery door!

The now out of action battery bay is not a problem, as I wanted to build a 4 cell battery holder to power the camera anyway. This will probably be a 3d printed addition to snap on to the back of the camera or on to the side. As I wanted to demo this at the UKHAS 2013 conference I have added 2 AA holders to the side of the camera just with hot glue for power.


Demo video of the camera in testing.

People have showed a lot of interest in the project and with a few more tweaks to the code I will be ready to launch it in the next couple of months!

The only thing preventing the camera becoming an entire self contained tracker is the lack of positioning data. I am hoping to be able to get hold of a new canon camera with GPS for geo tagging and send back position reports. I very much doubt canon will have used any specialist GPS chips in the camera to allow it to work above 12km (to comply with US regulations that prevent you using a commercial GPS to build your own cruise missile). I guess the only way to find out is to rip one open! Chances are that whatever GPS module they have used will output serial NMEA data, so a uBlox chip (works to 50km) could quite easily be patched in.

May 2012 Photographing an eclipse


We launched a weather balloon into the path of the annular eclipse.  This is my favorite of the zillions of pictures.  It was taken shortly after the maximum eclipse. 
We launched at 5:33pm on May 20, 2012 from Westwood in Northern California.  The balloon went to roughly 90000′.   We got really lucky with the winds and picked it up only about 38 miles away.
There is a solar filter on the right side of the image so that the sun is not so over-exposed.
The attitude control system described below managed to stop the capsule from spinning but ran out of gas before it could point the box well.
The Box
Inside the Styrofoam box was:
  1. A SPOT gps device that texts its position every ten minutes if it’s below 20000′ and if it’s not in a forest (trees block both the gps signal and the text signal).  This was on a one-axis gimbal consisting of a taut string going across the inside of the box, and a ziptie around the SPOT.  Thus, if the box landed on its two biggest sides, the SPOT would be hanging vertically.
  2. A GoPro II wide angle HD video camera.  Waterproof.  (Condensation formed droplets on the descent and fog near the ground).
  3. A Canon SD870 still/video camera that had a Baader photographic solar filter across the right half of the view.  It was running a script using the Stereo Data Maker version of the Canon Hacker’s Development Kit (“hab5.bas” included below).
  4. The puffer system described below to orient the camera during the eclipse.
  5. A walkie-talkie that was broadcasting a tone for 15 seconds every two minutes.
  6. AA Lithium non-rechargeable batteries.
Balloon and Descent
We used a Kaymont 1kg balloon with around 150 cubic feet of helium for the ascent.  Roughly 5m/s ascent rate?
We used a rocketman 3′ parachute which seems like it was probably too small.  The ziptie of the SPOT broke, and the radio batteries came loose so that the radio didn’t transmit.
The Trajectory
The final trajectory was unknown, only a handful of ground points (no altitude) are known, sent by the SPOT.   Ignore the first point.  The 2nd point is the launch site in Westwood.
FAA was notified 2 days ahead.  I set up a notice to airmen (how sexist!) by calling  877-487-6867

Spoke with KW

High ball balloon

11 mi ENE of Rogers airport (code O05)

0030 Zulu (5:30 pm) launch, for 2.5 hours. East bound. To 90000’.

The final trajectory prediction from 24 hours before launch looked like this, with the final point also plotted:
To estimate where the path might be, I used data from the atmospheric balloon soundings that have been done from Reno for the last 17 years.  They are published here:
Mark helped me glom them all into a tab spaced file and I crunched them in excel and converted them to google earth format and plotted them.

The Adventure

We set out to find the capsule at around 7pm after enjoying the eclipse from the ground and packing up our picnic.  We staged our 6 year old and his mom and the minivan at the start of the dirt road and set out on the dirt road and parked near Biscar Reservior.  The hike was 1.5 miles as the crow flies but it felt much farther because we started in the dark.  I used my phone and followed the numbers till they got pretty close and Emily and I saw it nearly simultaneously.  It stood out in the starlight among the sage and rocks.  The sky was super dark with tons of stars.  My 11 year old was way past his bedtime!
The camera had broken off its mount, the puffer had broken off its mount (both hot-glued to the styrafoam), the battery was loose and the SPOT had broken free.   The GoPro had a vacuum inside and some serious force was needed to open it.  The balloon was spaghetti.  

1 thought on “Photography

  1. Pingback: Wireless SSDV images from a canon camera using RTTY on CHDK | Balloon News

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s