Skip to main content

GAGA-1: Camera Hacking

I decided to spend the weekend doing some work on GAGA-1 and got the camera in fairly good shape.

I'm using a Canon A560 (two, in fact, that I bought off eBay for about £35 each). There are lots of reasons to use this camera: it's lightweight (very important since I need to minimize the payload weight), it's been flown on high-altitude balloon projects before (e.g. by Robert Harrison), it was recommended to me by the CU Spaceflight guys and it's hackable with CHDK.

CHDK is an amazing project that lets you run new firmware on a wide range of Canon cameras that enable full control of the camera. For my purposes I'm using the uBASIC interpreter that's part of CHDK to script automatic photo taking (code below). First, a few notes on getting CHDK loaded on my A560 from a Mac (you should start by reading the Mac FAQ.

1. Get the correct build for the camera from here. I'm using the 'full' version.

2. Unzip the file from the command-line and not from Archive Utility otherwise Mac OS X adds Extended Attributes (specifically, that mess everything up. I just did unzip

3. Use SDMInst to format and upload to the SD Card. You only need to do this once, after that you can mess around with adding scripts in CHDK/SCRIPTS on the SD card directly using the normal Mac file system.

4. Set write protect/lock on the SD card. Put card in camera. You will see a special CHDK splash screen indicating that you are running the firmware from the card and not from the camera. Click the 'direct print' button on the camera and you enter ALT mode.

5. In ALT mode you have access to all of CHDK's functions. Here's what happens when you hit MENU on ALT mode:

Since I'm working with a custom script (called GAGA-1.BAS) I load it from the Scripting parameters menu item. Once loaded the parameters for that script are visible in the menu:

My script has three parameters: a start-up delay that gives me time to do a quick visual check of the camera and insert it into the box before it starts operating, the number of pictures to take in a burst and the delay between bursts. The camera will sleep for five minutes, wake up and take three pictures and then go back to sleeping for another five minutes.

Once back on the main screen the GAGA Camera Control script is mentioned at the bottom of the screen. This indicates that simply hitting the shutter button will start the script.

The 'opt' value top-right is the temperature of the optical parts of the camera. I expect this will drop when GAGA-1 hits the stratosphere. It's possible to get and log these values so I may add a log file to the SD card recording the temperature drop.

And here's what that looks like: start-up of the script, self-check and taking a few shots:

I ran a full test with new Duracell batteries (the ordinary gold-topped ones) today and the camera took 61 photographs at maximum resolution, running continuously for 103 minutes. This is ok, but not good enough. Most balloon flights will be in the 120 to 180 minute range so I need extend the time.

One big problem was that I had the display shut off set at three minutes, with a five minute wake up that meant the LCD was on 3/5 of the time wasting a lot of battery. The next test will be done with the minimum time (20 seconds). The next test also needs to use the right batteries: Energizer Lithium Ultimate.

I fully expect to get to 180 minutes with five minute wake-ups taking 10 pictures at a time with that combination. But, as with everything else in GAGA-1, it'll need testing.

Here's the script itself. The actual photographing code is a tiny loop towards the end which uses the CHDK shoot command to take a picture. Everything else is self-test using the property cases to ensure that I don't mess up. The idea is that the camera is manually configured (and in Manual Mode). The script checks that there's nothing silly going on (like the flash being enabled).

rem GAGA Camera Control Code
rem Copyright (c) 2010 John Graham-Cumming
rem Performs the following steps:
rem Performs a self-check
rem Waits for a predetermined amount of time
rem Enters loop doing the following:
rem Take a number of photographs in succession
rem Wait a predetermined amount of time

@title GAGA Camera Control

@param s Start-up delay (secs)
@default s 10

@param c Pictures per iteration
@default c 10

@param i Iteration delay (secs)
@default i 300

rem The sleep command uses microseconds do the s and i need
rem to be converted


print "GAGA Camera Control"
sleep s

rem Now enter a self-check of the manual mode settings

print "Self-check started"

p=get_prop 49
if p <> -32764 then
print "ERROR: Not in manual mode"
goto "fail"

p=get_prop 5
if p <> 0 then
print "ERROR: AF Assist Beam should be Off"
goto "fail"

p=get_prop 6
if p <> 0 then
print "ERROR: Focus Mode should be Normal"
goto "fail"

p=get_prop 8
if p <> 0 then
print "ERROR: AiAF Mode should be On"
goto "fail"

p=get_prop 21
if p <> 0 then
print "ERROR: Auto Rotate should be Off"
goto "fail"

p=get_prop 29
if p <> 0 then
print "ERROR: Bracket Mode should be None"
goto "fail"

p=get_prop 57
if p <> 0 then
print "ERROR: Picture Mode should be Superfine"
goto "fail"

p=get_prop 66
if p <> 0 then
print "ERROR: Date Stamp should be Off"
goto "fail"

p=get_prop 95
if p <> 0 then
print "ERROR: Digital Zoom should be None"
goto "fail"

p=get_prop 102
if p <> 0 then
print "ERROR: Drive Mode should be Single"
goto "fail"

p=get_prop 133
if p <> 0 then
print "ERROR: Manual Focus Mode should be Off"
goto "fail"

p=get_prop 143
if p <> 2 then
print "ERROR: Flash Mode should be Off"
goto "fail"

p=get_prop 149
if p <> 100 then
print "ERROR: ISO Mode should be 100"
goto "fail"

p=get_prop 218
if p <> 0 then
print "ERROR: Picture Size should be L"
goto "fail"

p=get_prop 268
if p <> 0 then
print "ERROR: White Balance Mode should be Auto"
goto "fail"

if v < 3000 then
print "ERROR: Batteries below 3V"
goto "fail"

print "Self-check complete"
print "Starting picture capture"


for a=1 to c
print "Picture", n, "taken"
next a
sleep i

goto "loop"

print "GAGA Camera Failed"

print "GAGA Camera Done"

Remaining TODOs:

0. Buy larger SD card
1. Rerun Duracell battery test with faster LCD cut off time
2. Run test with Energizer Lithium Ultimate batteries
3. Run freeze test at -18C
4. Make self-check happen before initial delay
5. Figure out whether the display shut off and auto shut down can be self-checked
6. Can we check that RAW mode is off?
7. Is it possible to check that there's space on the SD card? Check that the date/time seems sensible?

UPDATE. Ran test using Energizer Lithium Ultimate batteries. What a difference some lithium makes! Instead of 103m the test ran for 451 minutes (over 7.5 hours). This was taking 3 pictures every 5 minutes. The camera took a total of 264 shots before I stopped it. At that point the battery was running low with the Canon indicator flashing.

The display shut off time was set at 20 seconds and I disabled RAW photo-capture.


Popular posts from this blog

Your last name contains invalid characters

My last name is "Graham-Cumming". But here's a typical form response when I enter it:

Does the web site have any idea how rude it is to claim that my last name contains invalid characters? Clearly not. What they actually meant is: our web site will not accept that hyphen in your last name. But do they say that? No, of course not. They decide to shove in my face the claim that there's something wrong with my name.

There's nothing wrong with my name, just as there's nothing wrong with someone whose first name is Jean-Marie, or someone whose last name is O'Reilly.

What is wrong is that way this is being handled. If the system can't cope with non-letters and spaces it needs to say that. How about the following error message:

Our system is unable to process last names that contain non-letters, please replace them with spaces.

Don't blame me for having a last name that your system doesn't like, whose fault is that? Saying "Your last name …

All the symmetrical watch faces (and code to generate them)

If you ever look at pictures of clocks and watches in advertising they are set to roughly 10:10 which is meant to be the most attractive (smiling!) position for the hands. They are actually set to 10:09.14 if the hands are truly symmetrical. CC BY 2.0image by Shinji
I wanted to know what all the possible symmetrical watch faces are and so I wrote some code using Processing. Here's the output (there's one watch face missing, 00:00 or 12:00, because it's very boring):

The key to writing this is to figure out the relationship between the hour and minute hands when the watch face is symmetrical. In an hour the minute hand moves through 360° and the hour hand moves through 30° (12 hours are shown on the watch face and 360/12 = 30).
The core loop inside the program is this:   for (int h = 0; h <= 12; h++) {
    float m = (360-30*float(h))*2/13;
    int s = round(60*(m-floor(m)));
    int col = h%6;
    int row = floor(h/6);
    draw_clock((r+f)*(2*col+1), (r+f)*(row*2+1), r, h, floor(m…

Importing an existing SSL key/certificate pair into a Java keystore

I'm writing this blog post in case anyone else has to Google that. In Java 6 keytool has been improved so that it now becomes possible to import an existing key and certificate (say one you generated outside of the Java world) into a keystore.

You need: Java 6 and openssl.

1. Suppose you have a certificate and key in PEM format. The key is named host.key and the certificate host.crt.

2. The first step is to convert them into a single PKCS12 file using the command: openssl pkcs12 -export -in host.crt -inkey host.key > host.p12. You will be asked for various passwords (the password to access the key (if set) and then the password for the PKCS12 file being created).

3. Then import the PKCS12 file into a keystore using the command: keytool -importkeystore -srckeystore host.p12 -destkeystore host.jks -srcstoretype pkcs12. You now have a keystore named host.jks containing the certificate/key you need.

For the sake of completeness here's the output of a full session I performe…