Penelope++

I’m still working on Penelope in the background, primary on her physical frame legs and body – subtle but better in my opinion; lighter yet longer legs combined with a longer overlapping frame makes her lighter and yet more stable in flight and a better protection of winter weather conditions.

There are some refined code changes here too here.

With regard to the on-board camera to be added to her, currently this is stalled due to both servo accuracy and video live streaming to another RPi screen, specifically displaying the video live.  Until boredom overtakes frustration, progress will be slow!

 

IMU + Servo

The IMU Gyro now controls the Servo motion. The aim is it compensates for vibration and drift in flight so the attached camera always points stably at the target.  Ultimately, the RPi0W will be attached to the servo with servo movement reversed to achieve this.

The problem at the moment is I can’t find a video player app on a seconds RPI to display the stability of the video output during piDrone instability flight.

Remote video feed

The RPi0W is now attached to the servo and rotating, while its camera runs a live video over to an RPi3 over WiFi, played via vlc. The result is rubbish, and I think this is due to vlc processong. Not sure what to do about this yet.

import socket
import time
import picamera

# Connect a client socket to my_server:8000 (change my_server to the
# hostname of your server)
client_socket = socket.socket()
client_socket.connect(('192.168.1.211', 8000))

# Make a file-like object out of the connection
connection = client_socket.makefile('wb')
try:
    camera = picamera.PiCamera()
    camera.resolution = (640, 480)
    camera.framerate = 24
    camera.rotation = 90

    # Start a preview and let the camera warm up for 2 seconds
    camera.start_preview()
    time.sleep(2)
    # Start recording, sending the output to the connection for 60
    # seconds, then stop
    camera.start_recording(connection, format='h264')
    camera.wait_recording(60)
    camera.stop_recording()
finally:
    connection.close()
    client_socket.close()

2D Servo

First part of the new forward-facing camera for the piDrones is a two-dimensional servo pair for left/right and up/down movement, in it’s basic test as a circle sweep:

from __future__ import division

import math
import time

from RPIO import PWM

RPIO_DMA_CHANNEL = 1

#-------------------------------------------------------------------------------------------
# Set up the globally shared single PWM channel
#-------------------------------------------------------------------------------------------
PWM.set_loglevel(PWM.LOG_LEVEL_ERRORS)
PWM.setup(1)                                    # 1us resolution pulses
PWM.init_channel(RPIO_DMA_CHANNEL, 20000)       # pulse every 20ms


####################################################################################################
#
#  Class for managing each serve via PWM.  Range is 1-2ms every 20ms though specified in micro seconds
#
####################################################################################################
class SERVO:

    def __init__(self, pin):
        #-------------------------------------------------------------------------------------------
        # The GPIO BCM numbered pin providing PWM signal for this ESC
        #-------------------------------------------------------------------------------------------
        self.bcm_pin = pin

        #-------------------------------------------------------------------------------------------
        # Initialize the RPIO DMA PWM for this ESC.
        #-------------------------------------------------------------------------------------------
        self.set(1500)

    def set(self, pulse_width):
        pulse_width = pulse_width if pulse_width >= 1000 else 1000
        pulse_width = pulse_width if pulse_width <= 2000 else 1999

        self.pulse_width = pulse_width

        PWM.add_channel_pulse(RPIO_DMA_CHANNEL, self.bcm_pin, 0, pulse_width)


lr = SERVO(18)
ud = SERVO(23)

try:
    lr.set(1500)
    ud.set(1500)

    while True:
        # Left / Right = 180o Up / Down = 150o
        # Servo is 1000us to 2000us ever 20ms, with 1500us in the middle
        # Ultimately accurate time comes from the IMU
        for ii in range(-100, 101):
            lr.set(1500 + int(round(500 * math.sin(ii / 100 * math.pi))))
            ud.set(1500 + int(round(410 * math.cos(ii / 100 * math.pi))))
            time.sleep(0.02)

except:
    lr.set(1500)
    ud.set(1500)

    del lr
    del ud

    PWM.cleanup()

The only problem to fix was the lower servo that needed dismantling and rebuilding so the centre point of the PWM signal matched the servo physical centre point, not 45 degrees or so out. Check out the difference between my and the supplier’s videos above.

Penelope, Percy and Pat.

When I was at the latest Cotswold Jam, one of the regulars suggested adding a camera to one of my piDrones to video its flight firsthand; that planted a seed which blossomed overnight:

  • Set up a live video stream from a RPi0W attached to one of my piDrones, the output of which is sent over WiFi to a RPi3+ RC touch-screen and display the video on a screen app there
  • Add on-screen pseudo-buttons to the RPi3+ RC touch-screen and use those to record the video to disk if specified
  • Add 2 on-screen pseudo-joysticks on the RPI3+ touch-screen RC, sending it to the piDrone, much like the physical joysticks do now
  • Finally, add IMU / servos hardware / software to keep the camera stable when it’s attached to a flying piDrone – trivial compared to the items above.

I’m completely ignorant how to implement all but the last item, much like the challenge to build the piDrones 6 years ago and hence that’s a fab challenge!  And in comparison to the piDrone itself, it’ll be cheap:  the parts either I already own, or are cheap to buy.  And I like the fact it gives a unique role for Penelope – currently she’s just Hermione without the object avoidance.

First job though is to name the Raspberry Pi’s:

 

Blog stats and a new project?

Just a couple of stats about my blog history.

First, the bandwidth of my web site over the last 6 years.

Blog hits

Blog hits

Points worth mentioning….

There’s the video hits when the RPi post was made:

Raspberry Pi Video Stats

Raspberry Pi Video Stats

  • On Saturday 1st September, I sent my sample blog post to the RPi team
  • It was tweaked and polished during Saturday and Sunday ready for posting on…
  • Monday 3rd September: the vimeo videos were hit by 1373 watching that day!
  • The hits dropped steadily until it dropped from the raspberrypi.org front page on Friday 7th, but it was compensated by the weekly RPi news e-mail on the same day running over the weekend.
  • Thereafter a slow descend to normality of <10 hits per day by the end of September.

Although I said the project is done, a colleague at the Cotswold Jam suggested I added a forward-facing camera; I’m considering this: with 2 servos and a gyrometer for stability, photos and video on an RPi0W would be interesting and challenging, especially feeding a video live to the remote control!  I’m investigating this right now!

 

Flight of the Bumblebee

The hedgehogs are long gone, now able to feed on other than the cat food we left out, but I spotted a bumblebee coming in and out of one of our stone walls: time to deploy hogcam.  I swapped the camera for the IR-filtered one, and set it up facing the hole and left it running for a while:

Incoming

Incoming

Landing gear down

Landing gear down

Landed safely

Landed safely

Into the hangar

Into the hangar

I’ve had to crop them and highlight the bees.  These photos were taken minutes apart; hundreds of blank wall shots were produced.  I’ve also edited these to increase the contrast in general, along with cropping off some junk at the bottom.

Conclusion: I’ll stick with Hedgehogs!

And in other news…

the hedgehogs are back in our garden:

Welcome back!

Welcome back!

This is a combination of the PiNoIR camera (v.1) along with this IR motion detector (the sensor is expensive because it’s digital), and some near-IR LEDs.  Below is a picture of the older model – the newer one runs on an A+ (for size and power reasons) and has been updated to Jessie, and now the LEDs are switchable by GPIO via a mosfet to provide lighting for the camera only when needed.  The upgrade to Jessie means she boots without WiFi at night, and the next morning, I can add the WiFi dongle to connect and check the results.

HogCam

HogCam

Code

#!/usr/bin/env python
# NiteLite - a python daemon process started at system boot, and stopped on shutdown
#          - the default LED pattern is twinkling but if motion is detected, one of 4
#            different patterns are chosen and these are used for 10s after motion detection
#
# Please see our GitHub repository for more information: https://github.com/pistuffing/nitelite/piglow
#

import signal
import time
import RPi.GPIO as GPIO
import os
from datetime import datetime
import subprocess

#------------------------------------------------------------
# Set up the PIR movement detection
#------------------------------------------------------------
GPIO_PIR = 18
GPIO_IR_LED = 12
GPIO.setmode(GPIO.BOARD)
GPIO.setup(GPIO_PIR, GPIO.IN, GPIO.PUD_DOWN)
GPIO.setup(GPIO_IR_LED, GPIO.OUT)
GPIO.output(GPIO_IR_LED, GPIO.LOW)

#------------------------------------------------------------
# Final steps of setup
#------------------------------------------------------------
keep_looping = True

def Daemonize():
	os.setpgrp()

#------------------------------------------------------------
# Once booted, give the user a couple of minutes to place the camera
#------------------------------------------------------------
time.sleep(2 * 60.0)

try:
    while keep_looping:
        #----------------------------------------------------
        # Block waiting for motion detection
        #----------------------------------------------------
        GPIO.wait_for_edge(GPIO_PIR, GPIO.RISING)

        #----------------------------------------------------
        # Turn on the IR LED
        #----------------------------------------------------
        GPIO.output(GPIO_IR_LED, GPIO.HIGH)

        #----------------------------------------------------
        # Take a snap
        #----------------------------------------------------
	now = datetime.now()
	now_string = now.strftime("%y%m%d-%H%M%S")
	camera = subprocess.Popen(["raspistill", "-rot", "180", "-o", "/home/pi/Pictures/img_" + now_string + ".jpg", "-n", "-ISO", "800", "-ex", "night", "-ifx", "none"], preexec_fn =  Daemonize)

        #----------------------------------------------------
        # Turn off the IR LED after 5s
        #----------------------------------------------------
        time.sleep(5)
        GPIO.output(GPIO_IR_LED, GPIO.LOW)

        #----------------------------------------------------
        # Wait 30s before checking for motion again
        #----------------------------------------------------
        time.sleep(30.0)
except KeyboardInterrupt, e:
        pass

GPIO.cleanup()

Save it as /home/pi/hogcam.py and make it executable:

chmod 775 /home/pi/hogcam.py

Load on boot

Raspian uses systemd for running on boot.  In /etc/systemd/system, create a new file called hogcam.service:

[Unit]
Description=HogCam

[Service]
ExecStart=/home/pi/hogcam.py

[Install]
WantedBy=multi-user.target

Save it off.  You can then enable, start and stop it thus.  It will also start on boot.

sudo systemctl enable hogcam.service
sudo systemctl start hogcam.service
sudo systemctl stop hogcam.service

Tyranosaurus

Tyranosaurus

Tyranosaurus

Another walk up the side of the house, but then walking a square as best I could, finishing where I started, and as you can see, the camera tracked this amazingly well – I’m particularly delighted the start and end points of the square are so close.  Units are pretty accurate too.

I’m now very keen for Hermione’s parts to arrive, as I suspect this is going to work like a dream, both stabilising long term hover, and also allowing accurate traced flight plans with horizontal movement.  Very, very excited!

Shame about the trip to DisneyLand Paris next week – I’m not going to get everything done before then, which means Disney is going to be more of a frustrating, annoying waste of my time than usual!