Thursday 23 June 2016

Pi Zero CCTV with ZeroView

One of the first things I used a raspberry Pi for was to build a simple CCTV system. In fact that original model B is still up and running and today.  It is a nice compact, self contained system.

However the addition of a camera capability to the Pi Zero opened up the possibilities for even smaller photography ideas.

Those rambunctious pirates at Pimoroni were quick off the mark with their dinky Little Bro kit. This is a smart CCTV sign that has a  hole for the camera and comes with a mounting bracket for the Pi Zero which also allows you to fix the whole thing to a wall.    When I wanted to make a timelapse of some garden work that was happening I simply used some string to hang the Little Bro from the window handle. This worked fine although it was a bit wobbly (especially when the window as opened) and when I had to adjust something I didn't manage to put it back up without altering the field of view slightly (you can see that the picture jumps slightly at about 00:10). It was also difficult to get the camera as close to the glass to keep reflections to a minimum.


Then The PiHut launched the excellent ZeroView, designed for exactly this sort of thing. It uses two sucker pads to stick to a window thus keep the camera as close to the glass as possible. Because the frame can be removed from the suckers while leaving them attached to the window, it also allows for easy adjustment and replacement without altering the field of view.


Initial tests confirmed that this was genius!




 Remixing my original CCTV build (which uses Motion to detect movement and then uploads the resulting movie to Dropbox) was easy. On the first night of testing I managed to catch this wily fox sneaking through my garden at dawn.



However there were a couple of issues about making this a permanent installation that I wanted to address:

1) My experience of headless Pis and wifi is that sometimes the computer drops off the network. Although the power management for dongles seems to be much improved now, I wanted an easy way of seeing that the Zero was still connected.
2) Suckers are effective but not always reliable, especially in a window which might experience big changes in temperature.

So as a combined solution to both of these, I used a ProtoZero board, an accelerometer and an RGB LED.


Some simple python checks the accelerometer and looks for abrupt changes in the values reported, to detect if the Pi falls off the window. In this event it uploads a picture of Humpty Dumpty to DropBox. The same code also periodically checks that it is still connected to the Internet (by pinging Google) and changes the colour of the RGB LED from green to red.  There are a few other visual cues too: the LED flashes blue when the baseline accelerometer readings are being measured at start-up and also flashes green when a ping test is underway. This is run at startup via /etc/rc.local.

#!/usr/bin/python3
from gpiozero import RGBLED
from adxl345 import ADXL345
import time, numpy
from datetime import datetime
import dropbox
import urllib3.contrib.pyopenssl
urllib3.contrib.pyopenssl.inject_into_urllib3()
import os,sys,logging

logfile = "/home/pi/cctv-"+str(datetime.now().strftime("%Y%m%d-%H%M"))+".csv"
logging.basicConfig(filename=logfile, level=logging.DEBUG,
    format='%(asctime)s %(message)s',
    datefmt='%Y-%m-%d, %H:%M:%S,')

led = RGBLED(26,13,6)
eggfile='/home/pi/Humpty-Dumpty.gif'
adxl345 = ADXL345()
client = dropbox.client.DropboxClient('<ENTER YOUR DROPBOX KEY HERE>')
#print('linked account: ', client.account_info())
logging.info('linked account: ', client.account_info())
    
axes = adxl345.getAxes(True)
#print("ADXL345 on address 0x%x:" % (adxl345.address))
logging.info("ADXL345 on address 0x%x:" % (adxl345.address))
t = 0
x_av = 0
y_av = 0
x_values = []
y_values = []
#print('Calibrating....')
logging.info('Calibrating....')
led.blink(on_time=0.1,off_time=0.1,on_color=(0,0,1), n=50,background=True)
while t < 100:
    axes = adxl345.getAxes(True)
    x = axes['x']
    y = axes['y']
#    print(x)
    x_values.append(x) 
    y_values.append(y) 
    time.sleep(0.1)
    t+=1
x_av = numpy.mean(x_values) 
y_av = numpy.mean(y_values) 
x_range = numpy.max(x_values) - numpy.min(x_values)
y_range = numpy.max(y_values) - numpy.min(y_values)
logging.info('Set mean x: ' + str(x_av))
logging.info('Set range x: ' + str(x_range))
logging.info('Set mean y: ' + str(y_av))
logging.info('Set range y: ' + str(y_range))
led.color = (0,0.2,0)
counter = 0
jiggle = 5
while True:
    axes = adxl345.getAxes(True)
    x = axes['x']
    y = axes['y']
    if ((x > (x_av + (jiggle*x_range))) or (x < (x_av - (jiggle*x_range)))) and  ((y > (y_av + (jiggle*y_range))) or (y < (y_av - (jiggle*y_range)))):
        #print('Humpty')
        logging.info('Humpty')
        led.color = (1,0,0)
        f = open(eggfile, 'rb')
        response = client.put_file(eggfile,f)
        f.close()
        time.sleep(1)
    time.sleep(0.1)
    counter +=1
    if counter > 6000:
        #print('Checking network comms...')
        logging.info('Checking network comms...')
        counter = 0
        response = os.system("ping -c 3 8.8.8.8")
        if response == 0:
            logging.info('I pinged Google successfully')
            led.blink(on_time=0.1, off_time=0.1, on_color=(0,0.5,0), n=3, background=False)
            led.color = (0,0.2,0)
        else:
            logging.info('Comms Down :-(')
            led.blink(on_time=0.1, off_time=0.1, on_color=(1,0,0), background=True)


Notes:


1) I used numpy to calculate the means and ranges which is really lazy - especially as numpy takes ages to compile on a Pi Zero.

2) I started from a fresh instal of jessie-lite. In addition to the Python libraries at the top of the code, you'll also  need to install the following Raspbian packages:

   python3-dev
   libffi-dev
   libssl-dev
   requests[security]
   git

3) You''l also need to enable the camera and the i2C interface through raspi-config

Thursday 9 June 2016

Finally... A High Altitude Balloon flight with Raspberry Pi



It had been a long journey from last year's Skycademy to get to this launch. Being situated just a few miles from Heathrow was always going to mean that launching from school would be tricky unless it involved everybody getting up a silly-o'clock (before flights started) and chasing through rush hour.

So finding a launch site close enough to be practical but far enough outside the LondonControl Zone (which defines the busy airspace around London) to gain CAA approval took a several months and a few applications and phone calls.

But now I had one I thought was suitable;. Even then, our launch permission comes with wind restrictions: the balloon must drift South or South West (i.e. away from London). This isn't as bad as it sounds because, realistically, you wouldn't want to chase a balloon heading in any other direction.

Thursday's flight was to be the first, long-awaited test from this site. Wind conditions over Easter were rubbish and we'd already aborted a planned launch on Tuesday because of bad weather (heavy ran and wind). Although conditions had improved and it was a dry day, it remained overcast and gusty (30mph) during the morning. Although things looked like improving even further by the weekend, Nick wouldn't be able to make it then so I decided to press ahead with the launch. Despite the blowy ground winds, the balloon wasn't due to travel too far and the predicted landing site was in the South Downs National Park. Tweaking the launch parameters to avoid coming down in Petersfield meant the burst altitude was lower than we'd like at just(!) 27km, but as this was really a test of the launch site conditions, we didn't mind too much.



We arrived at the site at about 10:30 and set about finding a sheltered area. When I'd reconnoitred a couple of days earlier I'd found a ridge that seemed to provide a block for the wind. Although it was deficiently calmer there, it was still pretty gusty and an ordinary balloon staked out on the ground sheet was being constantly blown at about a 45 degree angle. However the sun was started to break up the clouds and with a long, clear area free from obstructions in the balloon's direction of travel, we decided to go ahead, over-filling if necessary.

Apart from getting slightly lost on the way back to the car to retrieve all the kit, pre-flight prep went smoothly. We'd tested everything in the days before the flight and our payload appeared on the HabHub map a minute after we booted up the Raspberry Pi A+. We were lucky enough to have two RTTY receivers (with an SDR dongle as back-up) and a LORA receiver with us (plus another one connected to a roof aerial back at my house) so we were fairly confident of our ability to track the balloon.


We attached the parachute to the payload and got ready to fill the balloon. As soon as it began to inflate it was clear that adding enough helium for the correct neck lift was going to be tricky to estimate: the balloon was being buffeted by the wind and required all four of us to hold steady. Rather than under-filling, (we think) we put in more helium than required. Certainly the balloon was pulling away quite fiercely by the end of the process.


Now to launch. The chirping from the RTTY receiver told us that the radios were still working and after a quick check to see that images were being uploaded, we were ready to go.

Picture by @duck_star

Ozzy held the balloon while Jasper had the parachute and I had the payload. The balloon was released and Oz gently played out the line until it reached the parachute. Jasper repeated the procedure until the cord started to tug on the payload and then I let go. Smooth!



Everything soared up into the sky, rapidly gaining height within a few seconds. By the time we'd picked up cameras to take photos, it was nearly out of site.

The Pi's eye view just after launching

A quick but thorough pack-up and we headed back to the car park (managing to go the long way round again). Mag-mount aerials deployed on the roof of the car and we were off. The original predictions had the balloon coming down just west of Petersfield, but the in-flight prediction was now showing a touch-down nearer to Winchester so we headed there.

Pi's eye view 15 minutes into the flight

My roof-mounted aerial back at home picked up the LORA transmissions from about 700m altitude which was impressive and we soon saw several other RTTY trackers uploading data to the website too.

By the time we arrived in Winchester, the balloon seemed to have been caught in a mini-tornado, spiralling round on itself over Liphook and never quite managing to break free and head off towards us despite steadily gaining altitude. Parking up on the roof of a multi-story car park we had lunch and decided that the balloon was never going to make it this far west before bursting: because we reckoned we'd added more helium than required, we were expecting the burst to come earlier than at the 27km we'd initially been aiming for.



As we headed back East the balloon finally escaped its looping trajectory and started heading west, gaining altitude even more rapidly. This also caused the predicted landing area to shift towards Alresford, so we drove there and found a nice pub with a beer garden to wait and see what happened. By this point the altitude was approaching 26km so we were expecting a burst at any time. But the altitude kept increasing until we we approaching 30km. Surely it must burst now?

Pi's eye view from 34km up

We continued to watch and fiddle with our receivers (Ozzy somehow managed to tune his Yupiteru into a music station), chasers of all ages becoming increasingly excited. The altitude continued to rise: 31km...32km...33km...34km… until at nearly 35K – and with much shouting and excitement from the younger team members – the HabHub icon changed from a balloon to a parachute and the altitude dropped rapidly.



Although the landing zone predictions were fluctuating, they seemed to be staying in roughly the same area so we made for Cheriton. 3/4G connectivity was quite patchy in this region so we kept loosing web access – and our ability to upload telemetry from our receivers. Getting confused (and slightly lost) we pulled up in a handy lay-by in a country lane where we had a strong 4G signal. We looked at where we were and where the payload was predicted to land and were pleased to discover that the two locations were almost the same. Surrounded by open fields this seemed like an perfect spot and we got out the binoculars and stood around in the sunshine hoping that we'd actually be able to see the payload drift in on its parachute.



It was not to be.

Suddenly at about 1km up, the predicted landing spot suddenly changed. Maybe the gusty winds just blew it off course but the new touchdown spot was a couple of miles away, right in the centre of (the excellently named) Itchen Abbas. This was less than ideal. Plenty of trees, roofs, private gardens and even a river to potentially foil our safe recovery plans.


We parked up at the village hall and checked our data. Annoyingly, despite having has 5 bars of 4G in a remote field two miles away, here among the houses and pubs of a fairly large village we had almost no signal on any network. The good news was that we were still getting telemetry from the payload and it appeared to stationary and on the ground. Typing the latitude and longitude into Google Maps and managing to find a scrap of 3G, we set off on foot.

Pi's eye view on the way down

After a few minutes of heading in the wrong directions we got ourselves oriented and started to close the gap between us and the payload. As we rounded a corner and looked at the tablet I realised that the coordinates put the landing site in the churchyard. We rushed in and there is was, sitting peacefully amongst the weathered gravestones. It had landed with the GPS facing upwards and with no signs of damage. There was very little of the balloon left, suggesting that it had been a violent burst when it eventually happened.



After some respectful celebrations (we were in a churchyard after all) and the obligatory recovery photos, we switched off the Pi and headed back to the car for the journey home.


On reflection, the flight was a great success. After the launch itself I was just happy that we'd managed to sort out all the logistics and permissions, and actually get a balloon off the ground. But having a successful chase and recovery, coupled with the amazing altitude our payload achieved, it was a really great day. All the tech worked and the only mishap was me forgetting to turn off the valve on the helium canister before removing the flexi-filler attachment thus wasting a load of gas.

We even got back home in time for tea.

Take-aways from me:


The boys really enjoyed the day. Some of the questions they asked demonstrated that (a) they hadn't really been listening when I'd explained some aspects of the flight and science as we prepared in the days prior to launch, and (b) actually being involved in physical filling of the balloon, the technical tracking and watching the live telemetry really captivated them and got them thinking and asking questions in a way that simply being told about stuff never will.

This is really a team sport. Four people seemed the minimum needed to make things run smoothly. Any less and we'd have had to make multiple trips from the car to the launch site and would have really struggled with the filling in the windy conditions. Multiple eyes on multiple screens also made tracking and navigating easier.

Having a fixed position LORA receiver with a reliable Internet connection is a good idea. It means that you have telemetry being uploaded even when you have no reception in the chase car, or are unable to upload yourself due to no local 3G/4G.

Altitude telemetry from LORA
A checklist including pictures of how to fill and tie off the balloon is really useful. Diagrams and printouts of calculations save you having to remember stuff when you're busy.

You can never have too many receivers and Internet uplinks (preferably on different networks) with you.

Picture by @duck_star
Don't rush into a launch if conditions aren't suitable. But equally, don't be put off if absolutely everything isn't ideal. It probably never will be, and predictions will never be perfectly accurate either.