High Altitude Ballooning on a budget!

Almost exactly a year ago, I finally set out on a journey to realise my dream of taking photos from the edge of the world. A video of the whole adventure is up on Youtube here. Here’s how I did it (with a little help from my friends too!)

This photo was taken right at the top of the flightpath

Things you will need (the total cost as launched was 199CHF, excluding helium):

  • A balloon
  • A parachute
  • An android phone
  • A single use handwarmer
  • Transparent plastic box (for waterproofing)
  • A polystyrene box (for insulation)
  • Some helium
  • String + sellotape
  • A tarpaulin
  • Friends (who are as crazy as you are)

How to get started:

Hardware

Buy the things you need, I purchased my balloons from Random Solutions and the parachute from Spherachutes in the USA. For the android phone I purchased a Samsung Galaxy Mini GT-S5570 on prepay from my local mobile phone store. Obviously the phone you use should have a camera and a GPS, a reasonable battery life is also a good idea. I picked up the handwarmers from a local sports shop, they were in a box by the counter.

Software

The Galaxy Mini runs Android 2.3.4 with some Samsung ‘stuff’ on the top. I first rooted the phone using Superuser, then configured it to have the lowest screen brightness (maximise battery life), turned off the wifi, bluetooth and anything else non-critical that will eat precious power. Next install SL4A to allow the use of scripting languages such as Python, don’t forget that you will also need to install the scripting package for your chosen language, which if you want to use Python you can find here.

Once you have installed the SL4A environment and Python, you can run a script to do what you need for the High Altitude Balloon Payload:

  • Take Pictures at a regular interval (I chose 7 seconds)
  • Log the GPS coordinates of the phone’s current position
  • Log all the extra data that Android makes available (battery life, magnetometer readings, accelerometer readings etc.)
  • Send you text messages at regular intervals with the GPS position so that you can find the phone on landing!

The source code for the script is at the end of this blog post.

Practice:

Before the launch day it’s a good idea to do a test-assembly run of the payload package. Put the android phone (best to test it) and the handwarmer (no need to activate it until the real thing) inside the transparent plastic box, sellotape the edges of the box to make sure no water will get in. Then mount the box inside the polystyrene outer box – this is a good opportunity to check that the camera can see clearly. I did a battery test by putting the whole lot in my freezer (remember it’s -50C in the stratosphere so temperature performance is an issue) to see how long it will run for (about 5 hours in my case). Doing a test also gives a good indication that the script is working correctly.

Pre-assembly and testing is highly recommended to make sure the camera gets a good view

Prediction:

In the week leading up to your planned launch it’s a good idea to run a number of simulations using the fantastic CUSF Landing Predictor tool. I did a number of simulations with various assumptions for gas fill, take-off time (because as I’m usually late) and launch position for each planned launch day. Remember to archive the KML of your predictions if you want to compare them with the actual performance! It’s also a good idea to keep a close eye on the weather. For the launch day you want a clear dry day with low surface winds.

Make sure that the flight time doesn’t exceed the expected battery life of the phone and remember to keep a margin of safety as the script will only send a text message every 20 minutes – so if you land with only 19 minutes of battery life remaining you may never get it back!

On launch day:

When the launch day comes, start early (we got up at 5am), drive to your chosen launch site and start filling the balloon. Spread the tarpaulin out on the ground, folded in half. Unroll the balloon between the folds of the tarp and start to fill it very slowly. Trying to fill the balloon too fast will cause the helium to cool significantly, as I discovered to my cost with two failed launch attempts. On the final, successful attempt we used a string tied round the balloon inflation nozzle on the helium canister to stabilise the volume of gas going into the balloon, such that the fill time was about 1 hour for about 2m3 of helium. Keeping the balloon folded inside the tarp during inflation will make sure it doesn’t blow away.

The balloon fully filled with 1.4m3 of helium

Whilst the balloon is filling, assemble the payload package, activate the handwarmer and start the script. Unmodified, the script will send a text message with the location approximately every 20 minutes, so it’s a good idea to wait until you have the first message received before letting go of the balloon. Also be sure to open the handwarmer, otherwise the phone will freeze and you will never get it back! Just in case something does go wrong, it’s a good idea to film your final assembly so that you can check it was done correctly. Once the payload box is correctly assembled, securely attach the parachute (a landscape orientation is best if you want to make a movie out of the photos later). Finally attach a 2m length of string to the top of the parachute and use this to connect it to the balloon. This string needs to be reasonably long (and well secured at each end) as it prevents the balloon from getting tangled up in the parachute.

Ioannis, Morag, Manohar and me!

Ready for take off:

Once the balloon is filled, close the neck using a cable tie. On our first attempt I tied the neck of the balloon in the same way you would tie a party balloon, with the payload attached on a string through the knot. This didn’t work and the balloon came undone at about 3000m, hence the use of cable ties. After the first cable tie is secure, form the remainder of the balloon neck into a U shape, tie the payload on to bottom of the U and close it with another cable tie. Make sure that everything is correctly and securely attached, otherwise the flight might end prematurely!

Make sure that everything if firmly attached before letting go!

Take off!

Once everything is attached to the filled balloon, cross your fingers and let go.

Letting go of the balloon!

A great shot from the top 1/3rd of the flight.

Recovery.

The re-entry was very rapid.

Assuming everything has worked correctly, you should get a text message from your balloon after 3-4 hours with the coordinates of the landing spot. For collection it’s a good idea to have your hiking gear, and a walking GPS. Load the coordinates into the hiking GPS and go! Be careful not to follow it blindly into anywhere dangerous!

The payload landed face down in the grass half way up a mountain!

Download

The best bit. If your phone still has any battery remaining you will be able to see the photos immediately.  Google Picassa is great for composing time-lapse photos.

Legal Stuff

You should have insurance in case the balloon causes damage when it lands (as the prediction isn’t an exact science), you should also have permission from the land-owner for the place where you launch, and from where you recover (if it isn’t a public right of way). We launched in Switzerland, where the following rules apply and we complied with them.

Source code – use at your own risk!

import os
import time
import android

phoneNumber=”123456″ #Insert your phone number here, complete with international code 00
period = 5 # seconds
gpsperiod = 1 #take a gps position every 5 seconds
sensorperiod = 1 #take a sensor snap every second
picperiod = 2 #take a photo every 20 seconds
smsperiod = 190 #text me every 20 minutes

# FOR TESTING
runcontinuous = True #run in a loop
gpsflag = True #take gps data
sensorflag = True #record the sensor values
smsflag = True #text the cell number
picflag = True #take photos
logmode = ‘a’ # write mode FOR TESTING (for reply use ‘a’)
bufsize = 0

droid = android.Android()
droid.startSensingTimed(1, 5000)
droid.wakeLockAcquirePartial()
droid.startLocating(5000) # period ms, dist
droid.batteryStartMonitoring()

sensorlog = open(‘/sdcard/balloon/devicelog.txt’, logmode, bufsize)
picdir = ‘/sdcard/balloon/pics/’
pictemp = picdir + ‘%05i.jpg’
lastloc = ”
droid.wakeLockPartial()
tick = 0
piccount = 1

#send an initial text with the position of the phone
#time.sleep(300)
#r = droid.readLocation()
#loc = r.result

#packet = loc[‘gps’]
#al = packet.get(‘altitude’,0.0)
#lo = packet.get(‘longitude’,0.0)
#ti = packet.get(‘time’,0)
#la = packet.get(‘latitude’,0.0)
#sp = packet.get(‘speed’,0)
#ac = packet.get(‘accuracy’,0)
#lastloc = “Payload online: 1, %i, http://maps.google.com/maps?q=%.5f,+%.5f,hl=en,t=h, %.5f, %.5f, %i” % (ti, la, lo, al, sp, ac)
batlevel = droid.batteryGetLevel()
droid.smsSend(phoneNumber, “Payload online. Battery level %i” % batlevel.result)

#time.sleep(900)
#batlevel = droid.batteryGetLevel()
#droid.smsSend(phoneNumber, “Houston we are go for launch. Battery level %i” % batlevel.result)

while (runcontinuous == True ):
logline = “”
if ((tick % sensorperiod) == 0) and sensorflag:

# Prepare the log linelogline=””
available_sensors=””

# Log magnetometer *ONLY* if the read values are valid
# (Otherwise we are probably missing a magnitometer or it’s in a weird state)
magr = droid.sensorsReadMagnetometer()
mag = magr.result
if (not (mag is None)) and (type(mag) is list) and (len(mag) == 3) and (not (mag[0] is None)):
available_sensors += “M”
logline += “, %.5f, %.5f, %.5f” % (mag[0], mag[1], mag[2])
else:
logline += “,,,”

# Log accelerometer *ONLY* if the read values are valid
# (Otherwise we are probably missing an accelerometer or it’s in a weird state)

accr = droid.sensorsReadAccelerometer()
acc = accr.result
if (not (acc is None)) and (type(acc) is list) and (len(acc) == 3) and (not (acc[0] is None)):
available_sensors += “A”
logline += “, %.5f, %.5f, %.5f” % (acc[0], acc[1], acc[2])
else:
logline += “,,,”

# Log orientation *ONLY* if the read values are valid
# (Otherwise we are probably missing the sensor or it’s in a weird state)
orir = droid.sensorsReadOrientation()
ori = orir.result
if (not (ori is None)) and (type(ori) is list) and (len(ori) == 3) and (not (ori[0] is None)):
available_sensors += “O”
logline += “, %.5f, %.5f, %.5f” % (ori[0], ori[1], ori[2])
else:
logline += “,,,”

# Log battery *ONLY* if the read values are valid
# (Otherwise we are probably missing the sensor or it’s in a weird state)
bathealth = droid.batteryGetHealth()
batlevel = droid.batteryGetLevel()
battemp = droid.batteryGetTemperature()
if ((not (bathealth is None)) and (not (batlevel is None)) and (not (battemp is None))):
available_sensors += “B”
logline += “, %i, %i, %i” % (bathealth.result, batlevel.result, battemp.result)
else:
logline += “,,,”

# Write down the line
sensorlog.write(“SENSORS, %i, %s, %s\n” % ( time.time(), available_sensors, logline ))

if ((tick % picperiod) == 0) and picflag:
#droid.webcamAdjustQuality(3, 20)
#droid.cameraStartPreview(5000,100,picdir)
#droid.cameraStart(5000,100,picdir)
#time.sleep(1)
#droid.cameraStop()
droid.cameraCapturePicture(pictemp % piccount, True)
piccount += 1
if ((tick % gpsperiod) == 0) and gpsflag:
r = droid.readLocation()
loc = r.result
#print “LOC:”, loc
if ‘gps’ in loc:
if not (loc[‘gps’] is None):
packet = loc[‘gps’]
al = packet.get(‘altitude’,0.0)
lo = packet.get(‘longitude’,0.0)
ti = packet.get(‘time’,0)
la = packet.get(‘latitude’,0.0)
sp = packet.get(‘speed’,0)
ac = packet.get(‘accuracy’,0)
lastloc = “1, %i, http://maps.google.com/maps?q=%.5f,+%.5f, %.5f, %.5f, %i” % (ti, la, lo, al, sp, ac)
sensorlog.write(“GPS, %i, 1, %.5f, %.5f, %.5f, %.5f, %i\n” % (ti, la, lo, al, sp, ac))
elif ‘network’ in loc:
if not (loc[‘network’] is None):
packet = loc[‘network’]
al = packet.get(‘altitude’,0.0)
lo = packet.get(‘longitude’,0.0)
ti = packet.get(‘time’,0)
la = packet.get(‘latitude’,0.0)
sp = packet.get(‘speed’,0)
ac = packet.get(‘accuracy’,0)
lastloc = “0, %i, http://maps.google.com/maps?q=%.5f,+%.5f, %.5f, %.5f, %i” % (ti, la, lo, al, sp, ac)
sensorlog.write(“GPS, %i, 0, %.5f, %.5f, %.5f, %.5f, %i\n” % (ti, la, lo, al, sp, ac))
if ((tick % smsperiod) == 0) and smsflag:
#print “SMS:”, lastloc
if lastloc != “”:
try:
droid.smsSend(phoneNumber, lastloc)
sensorlog.write(“SMS-OK, %i, \”%s\”\n” % ( time.time(), lastloc ))
except:
sensorlog.write(“SMS-FAIL, %i, \”%s\”\n” % ( time.time(), lastloc ))
time.sleep(period)
tick += 1

Advertisements
Tagged , , , , , , , , , , , , , , , ,

6 thoughts on “High Altitude Ballooning on a budget!

  1. Cathy says:

    ummm ur a balloon! just kidding…have u been in a hot air balloon? as for me, i don’t remember! 😛

  2. […] 一个好消息是,除了绝热外壳和加热器,我们发现其他全部的功能单元在我们的手机上就都有啦!感谢乔布斯和移动互联网时代。总而言之,用好一款手机上提供的资源,我们就不需要太多额外的硬件开发了。比方说像James Devine同学所做的这样,他使用了一部 Samsung Galaxy Mini GT-S5570 手机,利用SL4A平台配合Python脚本实现了记录手机传感器的数据,用摄像头每间隔7s拍摄照片,降落到地面后通过蜂窝网络用短信发送这些GPS位置,帮助我们找到落点。啊,这简直太美好了,不过万一像很多气球的制作者一样,放飞之后弄丢了的话…. […]

  3. Salvatore says:

    Very very informative post Thank you! Salvatore from CERN 😉

  4. r2d2 says:

    wouaw ! great adventure ! do you know what was the altitude of the balloon ? thanx for your answer

  5. Kirk Smith says:

    Did the phone’s GPS work at maximum altitude? Most commercial GPS stop at 18,000km

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: