Mission Possible

As balloonists we have a number of general-purpose tools to track a flight, of which the main ones are the live map and live imagery page. Sometimes though it’s nice to have a custom dashboard showing these items, the telemetry and anything else of interest.

A small number of flights have had these dashboards, including some of mine. Mostly I used the now defunct thdash.com site to design and host them, and for my Telnet flight I built one in Delphi using the rather old Intraweb framework. Now though, for Delphi programmers, there’s a new kid on the block in the form of TMS Web Core. Whereas Intraweb built a server executable or module, TMS Web Core creates a web app consisting of HTML and JavaScript. For those like me with extensive Delphi experience and pretty much zero JavaScript experience, it makes the creation of web apps a fairly familiar experience. I use TMS software extensively in my day job, so I know it’s all high quality stuff.

Mission Control

One of my next planned flights will be of an Apollo 11 CSM/LM combination, to commemorate the first manned moon landing 50 years ago next month. With the payload ready I started to consider what else I could do for the flight, and soon thought of creating a virtual replica mission control console. I started with the image that I created for that Telnet flight, and made some modifications to produce this background image:

Next job was to place a few display controls on it, and write some code that automatically resizes the image, and resizes and re-positions the controls, according to the browser window size.

Live Data

For the telemetry, I wanted to have live data displayed promptly after reception from the payload. For this and other reasons I recently built a web server application that accepts telemetry and other HAB-related data, and makes it available to web clients. Here’s the structure showing the data flow:

The LoRa gateway uses a UDP port to broadcast any telemetry that it receives, and this is then received by a separate Web Feeder application (run locally) that bounces the message up to the web server (running in an AWS instance). The Web App connects to a web socket on the server, tells the server what payload ID(s) it is interested in, and thereafter will receive any new telemetry for any of those payloads. The latency here is measured in milliseconds, so is a lot quicker than for example the standard map polling the habhub server every 10 seconds.

The web feeder also uploads other data (e.g. from my weather station). Rather than ask other HAB listeners to install it, I will make the LoRa gateway upload directly to the server, so there will be a new version of that soon.

Main Window

As well as the telemetry, I wanted my dashboard to provide some other functions:

  • Launch / Chase Video Stream
  • Live SSDV Images
  • Map with payload, landing position and chase car
  • 3D visualisation
  • Raw Telemetry Data

The video stream is trivial to add – drop a TMS YouTube component on the screen and fill in the VideoID. The only code is to make the YouTube component visible when the Video button is pressed, fill in the VideoID and let it play. Job jobbed. For the source I’ll use a Raspberry Pi running ffmpeg which, I’ve no doubt, has a greyscale mode for that authentic 1960’s look! Meanwhile I’m testing with a familiar video …

SSDV is just a simple, this time using a TMS Web Browser component and filling in the URL. Again, I wanted it in greyscale so I set up my Raspberry Pi balloon tracker to take greyscale photos.


For the map, I started by embedding the standard spacenear.us map, however that map keeps hitting the Google API limits. Also, the icons are fixed and I wanted a bit more flexibility, so I used the TMS Google Maps control. Putting the map on the screen was a simple drag-and-drop job, plus obtaining a Google API key for the project and filling that in. After that, I created markers for the balloon etc., added those, and woohoo a map with balloon on it. All just like when I’ve used the equivalent TMS control in VCL (Delphi Windows library) or FMX (Delphi cross-platform library, which I primarily use for Android).

However, the next step of moving the balloon marker around the map wasn’t so simple. Unlike under VCL and FMX, no methods are provided to move the marker. Under VCL/FMX, AddMarker() returns a marker which I can then move with Marker.Latitude := … etc.; for Web Core I was stuck with no option in the current library other than to remove all the markers then add them all back. Not a pretty solution for the code or the user.

All was not lost though; TMS provide the source code to the libraries, so I grabbed the file containing the Google Maps class, copied just that class to a fresh unit in my project, renamed it (cleverly as TMyGoogleMap), saved as MyMap.pas (you can tell how expert I am at naming things …), and replaced use of the TMS map with “my” map. So far so easy.

Next job was to have AddMarker return a reference to the marker that it has added, so the code can refer to that later when moving the marker. The way that TMS Web Core works is that the Delphi source code is “compiled” not into machine code but into JavaScript, and where the library needs to include JavaScript directly it does that inside of an “asm” block (yes, short for assembler, as the older Delphi programmers may remember from where we used to embed assembler code when we tried to get a bit more performance out of our code). The Delphi to JS compiler just leaves the contents of the asm block as there are when emitting JS. This is used in the AddMarker procedure where it accesses the Google Maps JS object. To see how this works, here’s my modified version of the AddMarker procedure:

function TMyGoogleMaps.AddMarker(Lat, Lon: double; Title: string): TJSElement;
  map: TJSHTMLElement;
  map := GetMap;
    var myLatLng = {lat: Lat, lng: Lon};
    var marker = new google.maps.Marker({
          position: myLatLng,
          map: map,
          title: Title
    Result = marker;

All I did was change it from a procedure to a function returning a TSJElement, then had it return the created marker. Not hard at all, even for a JS neophyte like me.

There are several overloaded AddMarker procedures so I made the same change to all of them. I also added a MoveMarker procedure (this isn’t how the VCL/FMX maps do it, but it was expedient):

procedure TMyGoogleMaps.MoveMarker(Marker: TJSElement; Lat,Lon: double);
        Marker.setPosition(new google.maps.LatLng(Lat, Lon));

So with those changes, I had a working live map. I’ve sent TMS a feature request asking them to make markers work the same as in their other Google Map products, and to add poly-lines so I can draw the balloon path on the map, but the changes I’ve made will do for now.

The last step was to get the map running in greyscale, so it doesn’t look out of place in my Apollo console. Once I understood how styles are set in a TMS Web Core app this was trivial: add the style to the form’s HTML file:

        .gmap_grey {
            webkit-filter: grayscale(100%);
            filter: grayscale(100%);

and reference that style from the map control. So easy.

3D Visualisation

Before I started this project, I looked into building a dashboard with an embedded Google Earth visualisation. A quick search for ideas on how to do that led me to the CesiumJS site where have an extensive API for visualising the globe in 3D in a web browser, complete with plenty of examples with source code. I created an account and obtained an API key, and soon had something working.

So I took that initial test project, copied the Cesium module I’d written over to my new dashboard project, and set it to open up CesiumJS in the Apollo console’s window. After that it’s as simple as telling the Cesium camera to fly to each telemetry position as it comes in.

Except … Cesium draws lovely visualisations in colour; I want grey only! I searched the API (which is as poorly organised as it is extensive) for a “grayscale” or “mono” setting or function, but found nothing. So then I scrolled through the examples till I found something that was in greyscale, and then checked the source and found … that I should have been searching for “BlackAndWhite” instead! I simply needed to add this code:

        var stages = viewer.scene.postProcessStages;
        var blackAndWhite = stages.add(Cesium.PostProcessStageLibrary.createBlackAndWhiteStage());
        blackAndWhite.uniforms.gradations = 256.0;

Even the “256.0” was an effort to find; the default is 5 grey scales which looks awful, and putting in “256” made no difference; it has to be a float! With that, it worked very well indeed.

Finally, I added some fun tricks like switch clunks when pressing the buttons, analogue TV “lost signal” lines when changing screens, and Apollo Quindar tones. If you want to view the dashboard, you can see it online here, though I might not be uploading telemetry when you visit.

Posted in Weather Balloon | 3 Comments

Next Flight

I’m hoping to send a flight across the Irish Sea to land in Northern Ireland. Launch time approx 10am this coming Thursday.

The wind conditions are unusual with the lower winds southerly and the upper winds easterly.  I will be aiming the balloon over towards Northern Ireland where Philip Heron will be waiting to chase it.  The flight profile is tricky with about 1.2m/s ascent rate. It may or may not achieve a float before the balloon is cut away at a longitude of -6.5.

Here’s the current prediction:

Flight Details

TitleN.I. DROP
DescriptionSlow ascent / float Ross to Northern Ireland
LocationRoss On Wye
Target Launch Time10am, 6th June 2019
Launch Window9am -noon, 6th/7th June
PayloadAVR tracker, AA, with Talon cutdown from PP3
Flight Profile1.3ms/s ascent, 40km float, -6.5 longitude cutdown, 5m/s landing
Flight PathNorth through England then west across Irish Sea
NotesCutdown status: 0=OFF, 1=Enabled, 3=Triggered
Payload Weight120g
Parachute18” spherachute, 24g
Balloon1600g Hwoyee
Neck LiftTotal weight + 50g

Tracker Details

Payload IDFrequencySettings
DROP434.450MHzLoRa Mode 1

433.60MHzLoRa Calling Mode
DROP434.400MHzRTTY 300 baud 8 N 2 488Hz
Posted in Weather Balloon | Leave a comment

Introduction To High Altitude Ballooning

It’s that time of year again where a young man or woman’s fancies turn to … launching a big lump of latex skyward, and I start to get emails asking for advice, which you get get by reading my article “High Altitude Ballooning, From The Ground Up (and back again)”.

Posted in Weather Balloon | Leave a comment

LoRa Repeater

Sometimes it’s handy to have a repeater to extend the range of a radio transmission. The particular usage I have in mind is to be able to receive telemetry from a landed payload that is too far away (or hidden by buildings or geography) to receive directly, but could possibly be received via a repeater up on a mast or flying on a drone. LoRa makes it easy to make a repeater, so that’s what I’ve done here. And to make it more generally useful, the repeater is programmable for frequency etc. via a Windows program, with the configuration stored in the repeater’s EEPROM.


One of these can be made in about an hour if you’re handy with a soldering iron, using these parts:

  • Arduino Mini Pro
  • LoRa module
  • Small 3.7V LiPo battery
  • USB LiPo charger
  • LiPo –> 5V step-up converter

I used a long/slim LiPo but you can use whatever you like. If like me this is just for lifting up on a drone, something small and light is ideal. Even a tiny LiPo will have plenty of capacity for this use.

I connected the charger and step-up converter one side of the LiPo, with the -ve terminals soldered together and to the LiPo. On the +ve side, I placed a 2-pin header between the modules to work as a simple power switch, or you could use a small slide switch. The LiPo +ve wire then goes to the charger +ve terminal. Finally, the +5V output terminals have red/black wires that go down to the Arduino on the other side of the sandwich.

First job on the Arduino Mini Pro is to solder on a programming header. Then connect the +5V from the step-up converter to the Raw pin, and 0V to GND. The Arduino then connects to the LoRa using these connections:

  • GND – GND
  • Vcc – Vcc
  • 4 – RESET
  • 7 – DIO0
  • 8 – NSS
  • 11 – MOSI
  • 12 – MISO
  • 13 – SCK

Finally, solder a suitable length (164mm for 434MHz) wire to the LoRa ANT terminal.


The firmware is Arduino source so you will need an Arduino IDE installed. No extra libraries are used. Get the source from github. Connect the assembled repeater to a suitable programmer and program it.


The configuration program is for Windows only at present. Download the executable from my dropbox.

Connect the repeater to your PC via a USB-serial programmer, then run the configuration program. Select the appropriate COM port in the drop-down box at the top, and the program will automatically connect and display the current (default) configuration:

If you know the PPM offset for your LoRa device, then enter it in the PPM box. What I do to determine this is to set up a LoRa tracker accurately using a precision RF frequency counter, then set up the repeater to the same frequency, note the frequency error and then calculate the PPM figure from that. Once set, it means that you can set your repeater frequencies without having to calculate offsets manually.

“Enable Repeater” does what it says; when checked then the repeater will immediately repeat any telemetry packets that it receives. At present only such packets are repeated (ones beginning with a “$”).

Rx/Tx Settings

The receiver and transmitter are be configured separately so there is no need for them to have the same settings. Generally you just need to set the frequency and mode (pre-determined standard modes that most trackers use); the mode is selected from a drop-down box which has the effect of automatically filling in all of the other settings.

Settings are sent to to the repeater immediately, so you can see their effect immediately in the status section at the bottom, and any received packets on the right. Normally you would do this in the presence of the tracker you wish to repeat, so you can confirm that the tracker is being received OK and ideally with a frequency error less than 1kHz (adjust frequency or PPM till it is).

When everything is OK, click the “Save In EEPROM” button; all settings will then be stored in the Arduino processor’s internal EEPROM memory. You can now disconnect the repeater, and next time it is powered up it will automatically recall the saved settings.

Posted in Weather Balloon | 10 Comments

HAB Explora – Chase App

This post has been replaced by a permanent page so please see that.

Posted in Weather Balloon | 3 Comments

HAB Relay Chat

My next flight (depending on wind predictions) will be to try to relay a chat session between 2 remote locations (one in Northern Ireland the other in England) via 2 balloons one launched at each location, with all communications via LoRa transceivers, something that is impossible without relaying because of lack of line-of-sight:

LoRa Possibilities

I’ve previously used LoRa to repeat telemetry between balloons, but all (3) balloons were fairly close to each other having been launched at the same location albeit with 30-60 minute gaps. I’ve also used it to provide a bidirectional data link with a Telnet-like terminal program on the ground and a Telnet server at the balloon. So this flight extends these ideas, greatly increasing the distances involved and having data from the ground relay via both balloons and down to a remote ground location.


As with both of those flights, all trackers and gateways will use the same frequency, taking turns to transmit. For my Telnet flight I used the gateway uplink to tell the tracker when it coulld transmit, but with 2 gateways and 2 trackers that’s not the best plan, so instead (and like the 3-balloon repeating flight) I used Time Division Multiplexing with the trackers using their GPS receiver for timing. Time slots are static and written into the code for each tracker; during non-Tx periods, each tracker listens for packets from other trackers and from the gateways.

I set the frame time to 6 seconds, which conveniently divides exactly into 1 minute and gives an acceptable total transmission time from one gateway to the other and back again, making the system responsive enough for use. The slot allocation is as follows:

  1. Tracker 1 sends short sync packet; gateway 1 responds with uplink
  2. Tracker 1 normal transmission (including uplinked chat text if present)
  3. Tracker 2 repeats Tracker 1 transmission
  4. Tracker 2 sends short sync packet; gateway 2 responds with uplink
  5. Tracker 2 normal transmission (including uplinked chat text if present)
  6. Tracker 1 repeats Tracker 2 transmission

Here’s the system shown in an SDR waterfall:

The yellow packets (lower power) are from my gateways which currently have no aerials connected.

As you can see, the channel utilisation is quite high, and of course it gets higher when chat messages are being sent. The available time slots limit each chat message to 40 characters before signals start to overlap; I’ve set a max of 32 characters for this flight.

Comms Protocol

Messages entered at the terminal program are queued within the program, and then passed to the gateway when it is ready (i.e. when it knows that the previous message has been received at the remote location). The gateway then sends the message to its own balloon, which includes the message in its regular transmission, which is then received and repeated by the remote tracker and then received by the remote gateway. Messages are acknowledged when they have made the full journey, and this acknowledgement than follows the reverse route.

The system copes with any missed packets, retrying until acknowledgement is received.

Chatty Man

Each chat terminal queues up its own messages (marked with a “-” when queued, “*” when in transit), and shows messages received from the other side:

Each gateway broadcasts transmitted and received messages on its local network, where they are received by a “web feeder” program which forwards them to a server program. This web feeder is generic, receiving UDP packets from several ports and forwarding them to the web server. As you can see, that includes packets from my weather station so that I can show local weather data on launch dashboards (for furture flights, not this one):

The server is a small Delphi program running under Ubuntu in an Amazon EC2 instance (I can’t run a server from home as I don’t currently have a public IP address because we’re now using a NATted 4G connection). That web server then feeds the data to browsers running a web dashboard, which looks like this:

You can see a short video of the web app in operation here; note the green/blue highlights showing when normal/repeated transmissions have been received from the trackers, and when the gateways are uplinking:

Note: The web app has changed design since the testing.

Here’s a video showing how the chat works in real time:

Posted in Weather Balloon | Leave a comment

Adding A Strobe Or Buzzer To A Payload

It can sometimes be tricky to find a payload even if you know the co-ordinates – if it’s landed in dense vegetation or high in a tree for example, and of course there are some rare circumstances where you won’t know the exact co-ordinates. For these reasons I’ve added software support for piezo buzzers and LED strobes to my Pi In The Sky software.

Piezo Buzzer

A piezo buzzer is a great way of locating a payload that you cannot see. I used this model from RS Components:

First we need to connect it to the Pi. I suggest that you use a “stacking header” on the Pi so that the pins go through the PITS board and you can then put a solderable pin header on top. To choose appropriate pins to connect the buzzer, refer to the PITS pin allocation table. I chose pin 16 (Wiring Pi pin 4) and pin 14 (0V) as those are free unless you are using an APRS board, which I am not. I used a dual-row right-angle header for a firm connection. Solder the buzzer to the header, fit the header to the Pi (when powered off, unless you’re feeling brave), then test to see it’s working using these commands:

$ gpio mode 4 out
$ gpio write 4 1
$ gpio write 4 0

The buzzer should sound after entering the second line, and then stop after the last line.

Now we can configure the software. Open the configuration file /boot/pisky.txt in the editor of your choice, and add the following lines:


The first line specifies which pin (Wiring Pi numbering scheme) is connected to the buzzer; the second line tells the software to sound the buzzer after descending below the specified altitude. You can omit that second line in which has the altitude will be taken from the existing “high=…” line used for image sizing.

When you start the tracker program you should then see a line like this:

Enabled Piezo Buzzer on pin 4 after descending below 500 metres

Strobe LED

The payload can also announce its position visually, using an LED strobe light as used on R/C aircraft; specifically the Strobon devices such as this one:


This the V1 model; we have tested with this and the V2 model. Both use PWM signal control rather than a simple on/off signal, as they are intended for use in R/C models where spare PWM channels are common. Both devices are incredibly bright and the makers say can be seen from up to 3 miles away at night; I don’t doubt it.

To connect to the Pi, you need to connect the control line, 0V and 5V; I used pin 12 (BCM pin 1) for the control. Note that this time we need to use BCM pin numbers since the PWM signal is controlled by a different I/O library and not WiringPi.

To configure the software, add these lines to /boot/pisky.txt:


When starting the tracker program you should then see a line like this:

Enabled PCM Strobe Light on pin 1 after descending below 2000 metres

The V2 (round) version of the Strobon has slightly different behaviour to the V1 model shown here, as it starts flashing on power-up until it sees a PWM signal, so you will see it flashing until the tracker starts; if it doesn’t stop then check that you specified the correct pin number.

Posted in Weather Balloon | Leave a comment

Double Trouble

For this flight I joined forces with Steve Randall – one of the earliest HAB hobbyists in the UK, and the most prolific launcher; between us we’ve flown well over 200 weather balloons. But experience doesn’t mean that things always go to plan, as we shall see …


The aim of the flight was to try out one of the new range of balloons from Hwoyee, and see how high they can go. They are relatively large balloons, and are double-skinned: to make them fit within standard size filling rooms they have an outer “auxillary” balloon to maintain a spherical shape when inflated, with the main balloon inside of that, joined to a filling valve at a double neck. For this size of balloon, the outer one bursts at around 12km allowing the inner balloon to take over for the rest of the flight.


These balloons are claimed to get as high as 50km, if conditions are right, which is 5km higher than the current amateur record (held by Steve). We didn’t think that altitude was likely this time, nevertheless for my tracker I used a GPS that, unlike the one usually used for HAB, works above 50km. I connected that to a Pi Zero, LoRa radio, Pi camera and 3 AAAs via a boost converter. Steve’s tracker was a new lightweight design of his, with a software mod so that it during advent it sends the highest recent position to transmit.


Filling these large balloons is a challenging affair. First, that’s a lot of hydrogen – around 11 cubic metres – so Steve wore fireproof clothing and we had fire extinguishers and buckets of water to hand. It took 3 cylinders so we had 2 changes during the fill. Finally, that large a balloon makes a big sail, so we erected a tall custom windbreak first.


To make the launch a bit easier, we used a relatively short payload line. That proved to be a mistake. As soon as the balloon was launched, the weight of the inner balloon pulled one side downwards leaving the filling neck, with payloads attached, halfway up one side. Further, the fact that both payloads together only weighed 130g, meant that the balloon had little to persuade it to remain upright. Evidence of the precarious arrangement is clearly seen on some of the live images …


This was my first flight testing my new Android HAB app, which I had running on a new headunit installed in my chase car (lower device here; upper one is my old Pi-based LCARS unit tucked into a storage compartment).

One of the app functions is to speak interesting events over the car stereo, so we had a funny moment when it announced “Flight P T E 1 had been launched” at high volume, shortly after it had been!

Problem 1 – Steve’s Tracker

Everything aside from the alarming turbulence was going swimmingly well – even the ascent rate which was high enough to prevent a sea landing – when the first problem happened – Steve’s tracker stopped updating its altitude, and started to send incorrect latitude and longitude values. We felt this might correct itself during descent, and besides we had a second tracker, so we weren’t overly concerned.

Meanwhile the live images often included the large balloon – both a novelty and a worry as we don’t want the payloads colliding with the balloon as either could get damaged.

Problem 2 – My Tracker

Then my tracker stopped transmitting. Our assumption is that something broke physically due to the turbulence and short payload line, as that tracker has flown before with no issues. So we now had no updates on the flight position. Not good.  Here’s the last position we knew, with a prediction based on the balloon bursting at that point:

Never Give Up, Never Surrender

We did though have one tracker sending something. You can glean a lot just from the radio signal, so I tuned my radio to Steve’s tracker and just listened to the signal. The burst of a balloon is usual easy enough to hear as the payload the to spin during free fall; the radio signal isn’t omnidirectional so the spinning is clearly heard through a radio speaker. I sat listening and waiting, and wrote down the time when I first heard the payload spinning. Woo, a data point!

Record ?

I also had the (errant) telemetry visible on my Android head unit, and I watched that hoping for the error to fix itself. Well, it almost did – the tracker suddenly transmitted the maximum altitude that it had registered during the flight so far. Woo, another data point!

Also woo – it beats Steve’s record!  However, with no corroborating data – i.e. no GPS history of the flight to that point – it’s not one I think we can claim.


We always use the excellent CUSF flight predictor before a flight, to decide what day (and sometimes what time) is best to fly, and then to decide on the best flight path (something which can be adjusted by changing the balloon size, parachute size and gas fill). It has another use too – to help locate otherwise lost flights. To do this, I entered the last position that I knew (from my tracker at around 36km), and the maximum altitude which X2 transmitted. For the ascent rate I started with the average that I saw early, and then adjusted that till the timings matched when I heard the burst. So those data points accurately (I hoped!) profiled the ascent.

Now for the descent. I waited till I lost audio from the tracker, and checked the #highaltitude chat room for when others lost it too.  Mine seemed to be the last anyway, so I used that time. Back on the predictor, I adjusted the landing speed till, at 7.5m/s, the landing time was shortly after the last time I could hear anything. So I now had a prediction to work from, and Julie and I drove there (over 80 miles, and around 100 minutes away) while Steve got on with another launch.  Here’s the final prediction that I made before setting off:


The landing area was west of the A12, so for convenience we aimed for that road then drive North to take us within 500m of the predicted landing point. I fully expected to spend an hour or so drinking round all they local roads on search of a signal, but amazingly we picked up a loud signal as soon as we got near the prediction! We pulled over into a layby and waited for a decode. Unfortunately that was still showing the wrong position. So…


It’s an old technique from when it wasn’t so easy to encode telemetry on a radio signal. All you have to do is use a directional aerial to get a direction to the radio transmitter, then do the same from another location. We did that, and got a position at the far end of the field we parked next to.

Brambles 1

Walking along the side of the field, radio and aerial in hand, I could tell that the signal was coming from somewhere inside dense woodland. Filled with brambles. I ventured in but couldn’t get a definite position, couldn’t see the payload, and was get scratched at every turn. It seemed that the signal was coming from somewhere close to where the trees stopped next to a railway line, so I retreated and tried in the field the other side of the line. Again, triangulation was showing the payload to be near the edge of the trees, but we still couldn’t see it. With skin and clothes torn, and the light fading, we called Steve and decided to wait till the next day.

Prediction Accuracy

Checking on the map at the hotel, I saw that the payload was a mere 250m from the prediction. Let that sink in.  A 250m error, from a point 36km up in the sky, for a flight that reached 45km and travelled 50km horizontally after the last position till it landed. Stunning accuracy (within 0.5%) from the CUSF predictor!

Brambles 2

Steve got to the area at first light, went through pretty much the same process that I did, and with the same results. We may go back when leaves have fallen and it’s potentially easier to see through the dense undergrowth, but for now the payloads are lost. So close yet so far!

Posted in Weather Balloon | 2 Comments

The Compleat Chase Car

Chasing balloons is often the best part of the entire process, but can be challenging if you don’t have the right kit, or it isn’t accessible.  It’s particularly difficult if, as with many of my flights, you’re chasing alone; a laptop isn’t much use when you’re driving!

My previous car was an old Shogun, which served me well but the list of faults was getting rather long so I traded it in for a Hyundai Santa Fe – a bit smaller and not quite as capable off road, but for HAB use with the odd muddy field it will do just fine.  I chose the 5-seat model as it has a huge under-floor compartment in the boot (where the extra row of seats would have been); I use that to store aerials and other equipment:

Here I have:

  • Chase rucksack with tape, ties, knife, hooks, waterproof bag for phone.
  • Yagi aerials for 434 and 868MHz
  • Torches
  • Wellies
  • Spare magmount aerials
  • Saws
  • SLA 12V battery
  • Raspberry Pi LoRa gateway

The LoRa gateway uses a Pi 3 with 434 and 868MHz modules, and connects to the internet via a 4G MyFi device in the cabin.

The gateway aerial cables run underneath the boot, up through the door trim and out at the roof to magmount aerials which attach to washers inside the car when not in use:

Power for the gateway comes from a 37Ah 12V SLA via a 12 –> 5V adapter.  Power to the adapter is switched via a panel mounted in the side of the boot:

The panel includes a voltmeter and dual USB socket, both switched via the first switch in the panel.  The 3rd switch connects power to a 240VAC inverter via a relay next to the SLA.  All supplies are fused, and for convenience the SLA powers 12V cigar lighter sockets in the boot and cabin.

With all this kit in the underfloor compartment, the boot floor is clear and I wanted to keep it that way, so I mounted the various poles (for removing payloads from trees) to the seat backs, using Velcro straps held by metal plates screwed to the seats:

Up front, I fixed my Yaesu 817 radio to the side of the centre console, using adhesive Velcro tape.  The 817 is kept charged from the car 12V supply.  Other connections include the aerial (another magmount), audio via a transformer to prevent earth loop noise, and a USB power adapter:

Now onto the dashboard.  On top is my old Pi-based LCARS device, and below is a Pumpkin double-DIN head unit running Android 7.1.

The Pi device runs a Python application that I wrote a while ago, emulating the Star Trek LCARS displays.  Here it’s streaming video to YouTube:

As for the head unit,  these are essentially Android tablets with WiFi and GPS, FM radio, amplifier, front panel volume control and some handy buttons, SD card slots, and front and rear USB sockets.  This model also has video in (for a rear-view camera and DVD player for example), video out (for seat-back displays), audio in and a steering wheel audio control input.  Buying last year’s model saved a fair amount of money, but didn’t lose any functionality and it’s plenty quick enough in use.  Here’s a short video showing it in use:

I installed apps for offline navigation and OS mapping, plus my own HAB chase app which I intend to release soon.

That app receives data from the LoRa gateway in the boot so it knows where the balloon is, and uses that plus the head unit’s GPS to provide navigation to the balloon once it lands.  I’ll cover the app in more depth in a separate post.

Posted in Weather Balloon | Leave a comment

RTTY Through LoRa Module

Although the current Pi In The Sky boards include an FM transmitter for use with RTTY, there are some reasons for wanting to transmit RTTY through a LoRa module:

  • You can use 1 aerial for RTTY and LoRa, instead of 2, which makes payload design a lot easier
  • Extra RTTY bandwidth
  • You’re making your own tracker and want to avoid the expense of 2 radio transmitters

This article is about using the latest Pi In The Sky software to achieve this.


To transmit RTTY we need to be able to frequency modulate the carrier at a specific rate (e.g. every 20ms for 50 baud).  This timing needs to be accurate.  We could …

  1. Switch the LoRa chip into a mode where it just generates a carrier, and use the RTTY bit stream to set the frequency to one of 2 values every 20ms.
  2. Switch the LoRa chip into a mode where it transmits one of 2 frequencies, with the selection controlled by a DIO pin, and then send the RTTY stream to this pin.
  3. Switch the LoRa chip into FSK (Frequency Shift Keying) mode, with preamble and checksum etc. disabled, and have it send data from a buffer where that data is the RTTY bitstream.

(1) requires accurate timing, which is not so easy with a non-real-time operating system.  I did try this option with a small test program written in Python, and it worked tolerably well at 50 baud, but really isn’t a good option as the timing varies depending on the processor’s workload.

(2) requires an accurately timed bitstream applied to the DIO pin.  This is possible on the Pi using the serial port, but we use that anyway for the standard RTTY radio.  It’s also possible using a software serial port and the Pigpio driver which uses the DMA hardware for timing, but this increases our reliance on a particular external driver and besides, on our LoRa boards the appropriate DIO pin is not connected.

Which leaves us with (3).  There is a difficulty here, which is that the buffer used for FSK is small (64 bytes) and we need to oversample (store the same bit several times) to get the lower baud rates needed for decent range on HAB, but these are just coding challenges.  So this is the option I chose.

Essentially, the code does the following:

  1. Puts the LoRa chip in FSK mode at the desired frequency
  2. Sets the bit rate to a suitable value for the desired baud rate (50 and 300 supported currently).  “Suitable” means a low bit rate (reduces CPU workload refilling the buffer) for which 1 bit in the data results in 1 or more bytes in the FSK buffer (so we don’t need to mess around with individual bits in the buffer, which complicates the code).
  3. Set a buffer warning level so we can quickly sense when to refill the FSK buffer
  4. Tell the chip to transmit
  5. Fill the FSK buffer
  6. Monitor the buffer level and refill as necessary
  7. At the end of the RTTY sentence/packet, allow the buffer to empty

I am indebted to Matt Brejza for the idea, and for providing the code he used to implement this in his tracker, which I then incorporated/mangled to work with the existing PITS software.


First, you need the new version of the Pi In The Sky software (released 26th September 2018), or later versions.

To understand the settings, first take note that PITS has a concept of “radio channels” where a channel is a particular radio transmitter not mode (RTTY or LoRa).  We are using one of the LoRa devices (channels) to transmit RTTY.  So our settings are associated with the particular LoRa module (in CE0 or CE1 position).  Essentially we are overriding the normal LoRa functionality by telling the software to transmitt RTTY as well as or instead of the LoRa packets.

These are the new settings (shown for channel 0)

  • LORA_RTTY_Frequency_0=<RTTY Frequency>.  Without this, RTTY will use the same frequency as LoRa.  I recommend that you keep the frequencies apart so that your RTTY receiving software does not try to track the LoRa trransmissions.
  • LORA_RTTY_Baud_0=<baud rate>.  Choose 50 (better range) or 300 (faster, allows for SSDV, easier for dl-fldigi to lock to).
  • LORA_RTTY_Shift_0=<carrier shift in Hz>.  The carrier shift must be numerically greater than the baud rate.  Note that the LoRa chip steps in multiples of 30.5Hz.
  • LORA_RTTY_Count_0=<count>.  This is how many RTTY packets are sent one after the other before transmitting any LoRa packets.  2 is recommended in case the RTTY decoder misses the start of the first packet.
  • LORA_RTTY_Every_0=<count>.  This is how many LoRa packets are sent one after the other before transmitting any RTTY packets.  Set to zero to disable LoRa (and only send RTTY).
  • LORA_RTTY_Preamble_0=<bits>.  Sets the length of preamble (constant carrier) before sending RTTY data.  Default is 8 and seems to be plenty.





  • Only 50 baud and 300 baud are currently supported.  This may change in future releases.
  • If you choose to interleave RTTY and LoRa, then any SSDV packets are only sent out over LoRa.
  • If you want to transmit SSDV over RTTY, then you need to disable LoRa transmissions on that module, and use 300 baud.
  • You cannot have separate payload IDs for RTTY and LoRa on the same module.


Posted in Weather Balloon | 4 Comments