Showing posts with label Raspberry Pi. Show all posts
Showing posts with label Raspberry Pi. Show all posts

You now have fifteen minutes to reach minimum safe distance

We have just run a sci-fi LARP where we wanted to have the classic trope of a computer with a sad voice telling the players bad news like MU|TH|UR in Aliens, GERTY from Moon, HAL in 2001 etc. etc. It's a very common part of the aesthetic of a certain kind of sci-fi.

Our game was set in the Aliens universe so we wanted to emulate the female voice from MU|TH|UR. None of the GMs are voice actors (or female) so I made a text to speech device for this.

I got quite far down the rabbit hole of power saving and solar charging on a Raspberry Pi 3A+ then somebody offered to bring a massive lead-acid battery to the game for me so I abandoned worrying about all that because brute force won out. I will come back to it though as I want to make a nice portable outdoor Pi to provide 'infrastructure' at future events. Having infrastructure I can deploy easily in a field with no power has been a constant thing I've been nibbling at the edges of for years mostly with ESP32s and mesh networking.

I put the Raspberry Pi 3A+ into a waterproof box I had and powered it off that big battery all weekend. I even forgot to shut it down on Saturday night and it jut kept going.

The Raspberry Pi communicated with the Internet over 4G using a dongle I had kicking around which conveniently has a tiny NAT router in and presents as a USB ethernet so 'just works' with zero configuration on the Pi, or pretty much anything else. I'll probably try find another dongle the same, it's handy for these reasons.

I then made a 'bot' in the popular messaging app Telegram using their example Python script and used the Microsoft Azure AI voice engine to generate a very convincing voice. This was not a very sophisticated script, really just Telegram's example bot script, their recipe for restricting access to certain Telegram IDs and Microsoft's example text-to-speech script all smushed together with my rudimentary understand of Python as I'm normally an Arduino/ESP32 C++ person.

None of this needs much processing power: an original Pi could probably do it, except the Microsoft library expects a 64-bit OS so the Raspberry Pi 3A+ was a good fit. It's the lowliest, most power efficient 64-bit Pi that also has an analogue audio out and I had one in my stash of dormant SBCs.

The end result was we could type a message on our phone into a Telegram group chat and it would then ring out across the game using walkie-talkies to broadcast it over a large area. There was a little bit of impedence/level matching needed for the line out from the Pi to go into the headset input of the walkie-talkie. I used voice activation in lieu of 'push-to-talk' but that too worked great once I added a preamble 'bong' and little gap before the talking. I may go back and investigate triggering the push-to-talk through the headset connector using one of the Pi GPIOs as it's more predictable and the headset has the feature: I was just bashing the thing together quickly for the game.

"You now have fifteen minutes to reach minimum safe distance"

If players wanted to talk to MU|TH|UR they would just talk on the same walkie-talkie channel and we were listening. We had some quite long player conversations back and forth with MU|TH|UR like this and it worked brilliantly. We'll be using this setup again.

Chindōgu - part 3

I've been tempted for some time to do my planned updates to the Chindōgu, adding sound and more importantly, trying to throw together some code that avoids using Ekiga in the graphical desktop. The Pi Zero really struggles running the desktop and graphical applications but is fine when throwing stuff straight at the framebuffer.

Some research suggests it's possible to spin up OMX player wrapped in such a way it'll play a network stream straight from a camera and I'm going to try and use that for the video at least.

Coincidentally, there's currently a Hackaday retro competition and I think this could make an acceptable entry, if I get the software together and have several all talking to each other. I've accumulated multiple Sony Watchmen and Pi Zero Ws to do the build with.

To get started I've pinned out the main components on a board as it's otherwise hard to work on. One thing I want to do is get the image as decent as it can be and these horizontal gun CRTs were always dodgy.

Lacking a service manual I've worked out the function of the trimmers by trial and error.

  • RV501 - Vertical size
  • RV502 - Horizontal hold
  • RV503 - Keystone adjustment
  • RV504 - Horizontal size
Tweaking the framebuffer settings on the Pi Zero and tweaking these has made the display almost usable. With is set to 320x240 you can actually read the command line.

Breaking out of the Espressif/Arduino rut

I have been noodling around with ESP8266/8285/32 microcontrollers almost exclusively now for a couple of years. 

The absolutely excellent price/feature/performance combo of these Espressif MCUs means I simply don't see any reason to change. There  have been a couple of things I built using AVR based Arduinos for very specific reasons to do with high I/O pin count or generating IR Lasertag signals with hardware timers, but that's it.

I've also mostly given up on Raspberry Pi based things because once an MCU has Wi-Fi and >64KB of RAM you can do most single-purpose things apart from a complicated GUI and I've been working on a workaround for the latter.

Likewise, much as people sneer at the Arduino IDE it is terribly easy to set up and use, broadly supported and just C++ (with an odd/incomplete selection of standard libraries) under the hood.

I have however been tempted by the new Raspberry Pi Pico. It's cheap (for now), dual core, has native USB, plenty of I/O and a massive push behind it comparable to the Adafruit Feather ecosystem. So I tacked a Pico and interesting carrier board onto an order from Pimoroni to have a play with one.

This could be my gateway to MicroPython, although I can see myself also having a go with C++ as this board is actually a good candidate for porting my serial terminal UI library, given it has no wireless connectivity.

OctoPrint PSU control

I've been using my Creality printers with OctoPrint running on Raspberry Pis for a little while now and it's made them really seamless to drive. One last thing has been bugging me, I want the printers to switch off at the end of a long print. A very quick look online shows there's a plug-in for this so I ordered a couple of cheap SSRs and today spent a little while setting this up.


The plug-in can be configured with a GPIO pin it then uses to turn power on/off and I selected pin 8. This meant I could solder up a very simple straight three pin header with 5V, GND and pin 8 next to each other.

There is a tiny gotcha with this choice in that pin 8 is GPIO14 which is used for the serial console on the Pi by default. So you have to use raspi-config and disable both the console and serial hardware in the 'Interfacing options' menu.

With that done, it was simple to configure the pin in PSU control and check it would turn the SSR on/off. This worked immediately but I found that the action was 'inverted' and the plug-in has a convenient tick-box that fixes that.

To manage the printer power I took the existing IEC mains lead and carefully stripped the outer sheath, exposing the individual wires. That made it easy to break the live connection and have it switched by the SSR without having joins in the earth and neutral.

So this was safe to have floating around on my bench, I designed a 3D printable enclosure and have published it on Thingiverse. This enclosure will obviously work for any use of these little SSRs and I'm tempted to buy a few more to have in stock for future projects. The cable channel is the right diameter for typical IEC leads and grips it when you tighten the cover down.






Things you don't normally need to worry about

Something we almost never think about nowadays with tech is 'how do I switch it on?', or vice-versa.

Decades of product design and familiarity means we 'just know' how things are supposed to turn on and off.

Except it's a big personal annoyance of mine that the Raspberry Pi has no on/off switch. I know why they've done this, it's all about saving a tiny bit on the cost and keeping the price down as low as possible.

So you're either plugging and unplugging the USB lead, switching it off at a wall socket or maybe you've bought a specific USB lead with an inline switch.

All of which is frankly rubbish. Modern computers aren't meant to be unceremoniously shut off and doing so can corrupt files and in the worst case break the file system badly enough they won't boot. It's unlikely but it does happen. So since the mid-1990s, we've expected computers to have 'smart' power switches that allow for a clean startup and shutdown process. If you shut a Raspberry Pi down, it still sits there consuming power, albeit lots less, until such time as you manually remove power.

I hate this and for anything where you expect a Pi, especially in a portable device, to be used by everyday people it needs an on/off switch that conforms to consumer norms.

I'm not the only person to think like this and there have been a few products over the years catering to this. If you want an off the shelf solution, the Pimoroni on/off shim looks good, but it doesn't fit my need to control power of differing voltages to other things.

So I've used a more generic smart power switch and made my own solution.

When you break it down, the accepted norm of a power button is now something like this.


  • If you push it and the device is turned off, it will turn on
  • If you push it and the device is turned on, it will turn off in a prompt but orderly fashion
  • (optional) If you push and hold some kind of reset/setup process may occur

The module I've gone with is the Pololu "Mini Pushbutton Power Switch with Reverse Voltage Protection, LV", which ticked my boxes. It has a very low current draw in the 'off' state and can be controlled by supplying signals on different pins. I've previously made myself little arrangements with MOSFETs for this but an off the shelf module keeps things compact.

Switching things on with the module is simple. Connect the incoming power supply to VIN & GND, feed that out to the Pi (and anything else) from VOUT & GND. Use a momentary switch to connect pin 'A' to ground and the power comes on. Pushing it again does nothing as the module latches in the on state.

Switching off is a bit more complicated as it has to be driven by the Raspberry Pi.

What I've done to achieve this is use a DPST button with the second 'pole' connecting a Pi GPIO pin to ground. So when you push the button the Pi knows you are asking it to shut down. Which needs a script. A script that needs to always run at startup.

I've opted to use a very basic systemd service for this, which is a very common way to shut down the Pi with a button, there are multiple how-tos around.

First create a file called 'gpioshutdown.sh' somewhere you put your own scripts, I put this in '/home/pi/scripts/' and used GPIO pin 17 but you can change that easily.

#!/bin/bash
gpioShutdownPin="17"

# export GPIO pin and set to input with pull-up
if [ ! -e /sys/class/gpio/gpio$gpioShutdownPin/ ]
then
 echo $gpioShutdownPin > /sys/class/gpio/export
 echo "in" > /sys/class/gpio/gpio$gpioShutdownPin/direction
 echo "high" > /sys/class/gpio/gpio$gpioShutdownPin/direction
fi

while [ true ]
do
if [ "$(cat /sys/class/gpio/gpio$gpioShutdownPin/value)" == '0' ]
then
 echo "$gpioShutdownPin low, Raspberry Pi Shutting Down!"
 sleep 1
 sudo /bin/systemctl poweroff
 exit 0
fi
sleep 1
done
Now make the script executable.
sudo chmod +x /home/pi/scripts/gpioshutdown.sh
You should test this works nicely by running it manually and checking that when you push the power button it shuts the Pi down. Don't do the next step until you've debugged this as you might find your Pi immediately shuts down every time you power it up.

Once this is working reliably, you need to make a systemd service pointing at this script to make sure it starts when the Pi boots up.

Create the file /lib/systemd/system/gpioshutdown.service
 [Unit]
 Description=GPIO driven shutdown service
 After=multi-user.target
 [Service]
 Type=idle
 ExecStart=/home/pi/scripts/gpioshutdown.sh
 [Install]
 WantedBy=multi-user.target
Then enable it with the following
sudo systemctl daemon-reload
sudo systemctl enable gpioshutdown.service
Reboot the Pi, check the status of this new service with..
sudo service gpioshutdown status
..which should show it as running and make sure pushing the button shuts the Pi down.

So far so good and there are a ton of examples like this out there. However it doesn't fully power the Pi off and most how-tos don't cover this.

For that you need another connection to the Pololu module and another script.

The Pololu module has an 'OFF' connection and if you drive this high it will shut off power completely. I have connected this to GPIO pin 27.

To make this go high once the Pi has finished shutting down, create the file /lib/systemd/system-shutdown/gpiopoweroff.sh
#!/bin/sh

gpioPowerOffPin="27"

if [ "$1" = "poweroff" ]; then
 /bin/echo $gpioPowerOffPin > /sys/class/gpio/export
 /bin/echo out > /sys/class/gpio/gpio$gpioPowerOffPin/direction
 /bin/echo 1 > /sys/class/gpio/gpio$gpioPowerOffPin/value
fi

Make it executable
sudo chmod +x /lib/systemd/system-shutdown/gpiopoweroff.sh
Any scripts in this directory get run when the system has reached the final stage of shutting down and has remounted the file system read-only, so is safe to power off.

So now you have made the Pi behave like people expect a normal device to work, safely.

For extra credit it would be possible to make the shutdown script change/replace some files before shutting down if you do a 'long press' for a 'factory reset' but I haven't needed this yet.

Chindōgu - Raspberry Pint presentation

I did a presentation about my Raspberry Pi powered Sony Watchman project at Raspberry Pint, a London Raspberry Pi meetup.



Chindōgu - part 2

This weekend I spent a chunk of time building a second Watchman based device.

The initial plan was to add more resource by fitting a Raspberry Pi 3A+ giving it a big performance increase but after desoldering some of the headers from the board and poking around I just couldn't fit it in the case. It might be possible with extreme measures like removing the camera header and soldering the ribbon cable directly to the board but this feels like it would be a failure anyway.

I ended up doing the simple incremental change of fitting a camera and sticking with the Raspberry Pi Zero W and it can just about handle video calling with Ekiga.

As standard the Pi Zero camera comes with too short a cable for this to work at all and there's no way a full size Pi camera will fit in the space under the CRT. You can't buy Zero camera extension cables but you can convert them to a full size ribbon and back again so this is what I ended up doing. Three cables and two joints but it still works just fine. It's routed all the way round the left hand side of the case and emerges back on the right side. This is so it's possible to maintain the original slide on/off switch and volume control.

The tuner wheel has been converted to a 'rocker' type switch with a couple of tactile switches, epoxy and luck. I also made a better job of the power switch, fitting an actual slide switch rather than a momentary one and relying on a long cruddy lever to push it. This all works much better than my first prototype and I may go back and rework it in this style. I'll need to buy more camera cables/joints though.

I'm still yet to do anything about audio. I dug out a little USB microphone dongle and may see if I can slim it down and hardwire it to a USB cable plugged into the port on the Zero. I'm not keen on desoldering the USB port, just in case.

For audio output I need to test the PWM output method and build a suitable filter.

Oh and then there's all the software I need to tweak, while Ekiga works there's no realistic way to control it so I'm dialling in from a laptop to test.

Chindōgu - part 1


A friend called this a Chindōgu and I had to look the term up. He called it dead right.

For some time I've been meaning to fit a Raspberry Pi inside a vintage Sony CRT portable TV, making the chunkiest most impractical yet still portable Raspberry Pi. I've been spending all my time coding my mesh network and last weekend needed a break so this practical project called out to me.

Squeezing the Pi inside was comparatively easy. Bigger than the more common 'oblong' models, this FD-250B has a rounded case, offering a bit of space round the edges, bigger screen and an AV in socket on the side making connecting the Pi trivial. No hacking into the tuning circuit, I just desoldered the AV socket and connected the Pi composite output up.

I'm using a Raspberry Pi Zero W, which has no sound output by default so at the moment this is silent, but there's a way to generate sound by re-allocating some PWM pins and feeding it through a low-pass filter. I may get back to this later but need to be clear if I'm sticking with the Zero or upgrading to a 3A+ with the sockets desoldered, which would give me audio.

I'm trying to keep this externally as original looking as I can so it's still running off the four AA batteries and uses the original slide on/off switch, but repurposed to trigger a smart power switch so the Pi can shut down gracefully when you switch off.

At the moment the tuning wheel is completely removed and I plan to turn it into a rocker switch for scrolling up/down, selecting things etc.

You can just about use the GUI with a paired Bluetooth keyboard and mouse. Web browsing sucks, not just because of the screen size and distortion, but also because the Zero doesn't really have enough horsepower. Here's a little video of it in use.



After this I tried playing a couple of 4:3 video clips and it excels at this. Which is right and proper given its original intended purpose. Right now you have to start omxplayer manually from the command line, but I can see how a simple file browsing GUI, probably written in Pygame, could turn this into a decent super-retro media player.



I have plans beyond this though, I want to squeeze one of the tiny Pi cameras inside, perhaps where the tuning pointer was, and it's occurred to me I might be able to fit a resistive touchscreen if I replaced the round bezel. Which I would like to do anyway if I fit the camera. This is to remove all trace of the tuning pointer.

Using a different tool for each job and linking them together with MQTT - part 4

Something needs to happen on the screen when you push the buttons you can see here. Except the buttons are connected to an Arduino not the Raspberry Pi that is connected to the screen.

The sequence goes something like this:




  1. Push the green button and the little trapdoor opens.
  2. Put a container in the revealed space and push the button again.
  3. It is drawn inside the machine.
  4. The trapdoor closes behind it.
  5. An 'analysis' of the contents of the container begins.


I did a little video while I was testing the mechanism. The mechanism is printed in natural translucent PLA and there are some Neopixels glued on the outside so that it can indicate the 'status' of the process. If you put in a container that has already been analysed it spits it out again while glowing red.


Going back to the start though, the Raspberry Pi needs to know you've pushed the green button. We've already established in parts 1 & 2 that the Arduino is plugged in to the Raspberry Pi over USB and that a small Python script looks for serial output from the Arduino, pushing anything it gets into an MQTT topic 'arduino/out/'. Push the green button and it sends 'openLid'.

The user interface is running as a set of web pages in Chrome browser. Unless something makes them they'll set there stoically until the user clicks on a link. What's great is that Paho have made a simple Javascript MQTT client library available and this can be used to automate interaction with these pages. The library uses Websockets to connect rather than a direct MQTT connection but we've already made sure the server supports this.


Using a different tool for each job and linking them together with MQTT - part 3

Things you have to think about when putting a Raspberry Pi inside a prop include things you don't normally have to worry about like graceful startup and shutdown. Also, getting enough power out of a battery for a Pi 3 and a 5" display is not totally inconsequential.

I'll deal with the latter first. I luckily had a 5V/3A Turnigy branded battery eliminator (BEC) kicking around in a parts drawer. These are designed for RC vehicles and nicely self-contained in a shrink-wrapped module with inline inductor to smooth things out. I paired this up with a big chunk of 12 AA NiMH cells wired series/parallel to give me ~7.2V which is about right to run the BEC. The more modern solution would be some LiPo cells but then you need to build a balance charger into the device or expose the connectors so you can charge the cells individually. I've got a bunch of stuff that runs off NiMH cells and a nice high current smart charger that automatically selects voltage/current and this also influenced my decision to go this way.

Then there's the switch. People expect things to just turn on/off at the flick or press of a switch but you can't give them easy direct access to the power or they'll switch things off when they aren't ready. The Raspberry Pi really doesn't like that. There are workarounds you can do with mostly read-only filesystems but at the end of the day the Pi really should be shut down cleanly.

Luckily I had some Polulu solid state power switches lurking from a temporarily shelved project. My house may be overflowing with stuff but sometimes it comes in useful. I wired this so the power switch was connected to the 'on only' contact. That gets everything powered up. When you flick the switch to off, the alternate contact takes a pin on the Arduino low and the Arduino initiates a shutdown sequence. You saw the code for that in part 2. Here's the Python script for the shutdown of the Pi, which is just a variant on the old chestnut about fitting a shutdown switch to the case of a Pi.

#!/usr/bin/python
import time
import os
while 1:
  time.sleep(1)
  if os.path.isfile('/tmp/reboot'):
    time.sleep(5)
    os.system("sudo reboot")
  elif os.path.isfile('/tmp/poweroff'):
    time.sleep(5)
    os.system("sudo poweroff")
Not much to say about this, it just looks for files in '/tmp/' and reboots or shuts down depending on which file it sees. Stick it in /etc/rc.local again and the job's a goodun.

Things I didn't get right are I used a latching switch for on/off and I should have fitted a way to both charge the batteries and power the device externally.

The batteries lasted a couple of hours but then it had to be charged before it could be used again. We had mains power in the end so being able to use a PSU would have been good. Connecting the smart charger with it powered up made the charger shut down, otherwise that would have been an option.

The latching switch prevented me from making the box shut down when inactive. It would try to shut down (the Pi would shut down) but if the switch was physically in the 'on' position the power would stay on until you flicked the switch. I picked this up in time to fix it but couldn't find a nice momentary switch without resorting to mail order. Which would have come too late. It's a lesson learned for next time.

Using a different tool for each job and linking them together with MQTT - part 2

Now we have a working MQTT server, it's time to start making use of it.

As I was planning to use MQTT to broker messages between Web server CGI scripts, Javascript in Chrome web browser and an Arduino the obvious way to do this is push data at the USB serial port of the Arduino.

Normally this port is used for uploading the Arduino sketch to the board and sometimes people end up filling it with debug/status messages once the sketch is running. However there's a long history of it being used as an actual way to control stuff.

So I threw together a piece of 'middleware' that shuffles data between some MQTT topics and the USB serial port.

#!/usr/bin/python
import time
import os
import mosquitto
import serial
# commands to the arduino are as follow...
# R red LEDs
# G green LEDs
# B blue LEDs
# N no LEDs
# O open/go
# P power off
arduinoBootupTime = 5
arduinoIsBooted = 0
debug = True
# Define the various MQTT callback functions as this is an event driven model
def on_connect(mosq, obj, rc):
if debug:
print("rc: "+str(rc))
return
def on_message(mosq, obj, msg):
if debug:
print(msg.topic+" "+str(msg.payload))
arduino.write(str(msg.payload))
return
def on_publish(mosq, obj, mid):
if debug:
print("mid: "+str(mid))
return
def on_subscribe(mosq, obj, mid, granted_qos):
if debug:
print("Subscribed: "+str(mid)+" "+str(granted_qos))
return
def on_log(mosq, obj, level, string):
if debug:
print(string)
return
#
time.sleep(arduinoBootupTime)
# Connect to the local MQTT server to pass stuff to/from a browser
mqttc = mosquitto.Mosquitto()
mqttc.connect("localhost", 1883, 60)
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
# Subscribe to the topic that sends commands TO the Arduino
mqttc.subscribe("arduino/in", 0)
while 1:
if debug:
print "Trying to connect to Arduino\n"
arduino = serial.Serial('/dev/ttyUSB0',115200,timeout=1)
while arduino.isOpen():
if arduinoIsBooted == 0:
if debug:
print(arduino.name) + " connected - Giving " + str(arduinoBootupTime) + "s for it to bootstrap"
time.sleep(arduinoBootupTime)
arduinoIsBooted = 1
mqttc.loop()
arduinoOut = arduino.readline()
if len(arduinoOut) > 0:
if debug:
print "Received " + arduinoOut.rstrip() + " from the Arduino"
if arduinoOut.rstrip() == 'powerDown':
powerOffFile = open('/tmp/poweroff', 'a')
powerOffFile.close()
else:
mqttc.publish("arduino/out", arduinoOut.rstrip())
arduino.close()
time.sleep(10)

This is about as simple as things can be and mostly cribbed from example scripts. It waits a while to give the Arduino time to boot as the USB port attaching to Raspberry Pi will cause it to reset. Then it tries to connect and loops round forever passing messages back and forth.

The meat of this is in two functions, the first of which gets triggered as a callback when an MQTT message arrives...

def on_message(mosq, obj, msg):
arduino.write(str(msg.payload))
return
This simply sends the message straight to the Arduino. Coming the other way is almost an exact reverse except we're using newlines to mark the end of messages so we can read them with 'readline'. This means we need to strip them off before publishing to MQTT. Python has a handy function for this in 'rstrip'.

arduinoOut = arduino.readline()
if len(arduinoOut) > 0:
if arduinoOut.rstrip() == 'powerDown':
powerOffFile = open('/tmp/poweroff', 'a')
powerOffFile.close()
else:
mqttc.publish("arduino/out", arduinoOut.rstrip())
There's another little if/else in here to handle the shutdown sequence. I used the VERY simple method of writing a file to /tmp/ if the Raspberry Pi needs to shut down, which is controlled by the Arduino. I could have had a second script subscribed to the topic for this, but this keeps all the MQTT code in one place. Because the Pi uses memory for /tmp/ instead of saving to its SD card, this safely disappears once the machine is shut down.

That's about it, things coming out of the Arduino USB serial port end up in the topic '/arduino/out/' and stuff in the topic '/arduino/in/' get sent to the serial port. The test for the existence of the Arduino serial port '/dev/ttyUSB0' means it loops round forever trying to reconnect if the Arduino get unplugged or resets.

To make this run at startup I put it into /etc/rc.local which is another quick and dirty 'make it work' solution. It works. This is not a server it's a prop, so I'm being cavalier with scalable/secure ways of doing things.

Using a different tool for each job and linking them together with MQTT - part 1

I've recently finished a quite complicated prop that needed to have a 'user interface' and thought I'd put down my thoughts on how I built it.

At a high level what we've got is a Raspberry Pi doing the user interface using Chromium web browser in kiosk mode, an Arduino Nano doing the 'physical computing' and a Teensy microcontroller acting as a custom keyboard for interaction with the Raspberry Pi.

What I've done is in principle inefficient as I could have done it all with the Raspberry Pi. However using different technologies like this is a way to compartmentalise bits of the project and use the technology you're most comfortable with for each part.

I've already used MQTT to tie things together before so it was an obvious thing to use again. It is implemented with a very simple protocol that many things are capable of understanding, including diminutive memory-constrained microcontrollers like an Arduino or ESP8266. Also, the idea of bringing data into MQTT from a hodgepodge of sources to tie things together is not a foreign concept at all, it's pretty much designed for this.

What is MQTT?

In principle the MQTT Wiki is a good point to start but like a lot of documentation in the open source community assumes a chunk of pre-knowledge and is full of gaps. So I'm going to re-invent the wheel here and describe it again in fairly plain language...

MQTT is just a way to send and receive messages. These messages can be pretty much anything you want, text, images, sounds, any arbitrary binary data. In principle they can be as large as you like but if something listening on the other end doesn't have enough memory to receive it then it'll definitely fail and probably crash or lock up.

For MQTT to work it needs a server (called a broker) that everything connects to. The broker makes sure that messages get where they need to go. A commonly used server is Mosquitto and it's what I've used. Be aware that the version which installs by default on a Raspberry Pi (probably other Linux distributions too) is old and compiled without Websockets support. You should use the current version from the Mosquitto developers or you will be limited in which clients you can use. More on that in a bit.

Topics, subscribe, publish, LWT and QoS

There are a load of clients available, Python, Javascript, Arduino, NodeMCU/Lua etc. etc. and they all use the same terminology when you want to do something with them.

Topic

A topic is a 'channel' for messages. There can be an aribtrary number of these on a broker. Unless you do specific configuration on the broker to lock things down you can create/destroy these arbitrarily by sending to or listening for data on a topic. In my application I've got topics called 'arduino/in' and 'arduino/out' for sending to and receiving from the Arduino respectively. All topics can be 'bidirectional' ie. you send and receive on the same topic from a client, but that can complicate your code as you need to process your own messages coming back at you. Which is why I'm using topics in a 'unidirectional' manner.

The broker normally handles creating topics and tidying up afterwards automatically, again unless you want to control this.

Subscribe

When you want to receive messages from a topic, you 'subscribe' to it. Depending on the programming language you use it is likely this happens as a 'callback'. This means that when you subscribe you create a function that gets run every time a message comes in on the topic. Your code needs to be able to deal with being arbitrarily interrupted when this happens.

Publish

When you want to send a message to a topic you 'publish' it. There's very little more to be said, you publish and it appears.

LWT

The broker periodically checks to make sure any clients it has are contactable. You can optionally set a 'Last Will and Testament' when you connect the client, which publishes a message to the topic of your choice if the client is no longer contactable. This is a very simple way to check if a particular client is online. I did not use this in my application.

QoS

When you publish or subscribe to a topic you can specify the 'quality of service' on the connection. This comes as...
  • QoS 0: At most once, which is unreliable and the client should receive it but this is not guaranteed
  • QoS 1: At least once, which is reliable. However the client may receive duplicates
  • QoS 2: Exactly once, which is reliable.
Given I was dealing with two clients running on the same device as the broker I left things as QoS 0 for my application. Some clients such as the NodeMCU one only support QoS 0.

Installing Mosquitto on a Raspberry Pi

Do not be tempted to install it from the standard Raspbian repository with 'apt-get install mosquitto'. This will work but some clients will fail with unhelpful errors, particularly the NodeMCU and Javascript ones. The Javascript client requires Websockets support and NodeMCU needs MQTT v3.1.1 both of which are missing in the standard build.

There's a handy guide to installing a newer version with Websockets support here, but in case this goes away here's the potted recipe for the current version of Raspbian (Jessie) at time of writing.

wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install mosquitto
Once this is installed, have a look in the file  /etc/mosquitto/mosquitto.conf and add the following line below the default 'listener'. We don't need Websockets yet, but we will later.
listener 1883

listener 9001
protocol websockets
Then restart the service with...
 sudo service mosquitto restart

Testing Mosquitto works

This is fairly easy, but first you need to install some Mosquitto clients...
sudo apt-get install mosquitto-clients
Start one session to your server and run the following command. It'll sit there waiting for messages to come in on the topic called "test".
mosquitto_sub -t 'test'
In another session, run the following command to send a message to the same topic.
mosquitto_pub -t "test" -m "Hello world!"
You should get "Hello world!" come up in the first window. It really is that simple to send messages back and forth, the client defaults to connecting to the local machine.

There was a lot of work to achieve this, but now you've done this you could have two wirelessly connected NodeMCU microcontrollers sending messages to each other via the broker and make things happen remotely. Or as we'll see in the next part, by clicking a button on a web page you can make things move that aren't directly connected to the web server.

This is all without having to create your own protocol to do this because MQTT is widely supported. I've done that kind of thing in the past and it was significantly time consuming.

Kiosk setup on a Raspberry Pi running Jessie and the Pixel Desktop

I've started playing around with embedding a Pi with a little 2.4" screen into a prop and I've noticed all the howtos for this kind of thing are old and don't apply circa March 2017.

Now we have the Pixel desktop it's very similar but you need to edit the following file...

~/.config/lxsession/LXDE-pi/autostart

#@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
#@xscreensaver -no-splash
@point-rpi
@xset s off
@xset -dpms
@xset s noblank
@chromium-browser --kiosk --incognito http://www.bbc.co.uk/


Make it look like this by commenting out the lines for lxpanel and xscreensaver then add an entry to start Chromium at the end opening whatever page you'd like Chromium to start with.

Simples.

They had to do it eventually

Much as I love them the Pi was starting to get long in the tooth and needed a shot in the arm. When the B+ came out I was surprised it wasn't this, but the Raspberry Pi 2 is here now and the expected extra cores, update to Cortex A7 and speed/memory tweaks are in.

I've just stuck Rasbian on one and it is noticeably quicker. OK so I/O isn't going to be any better but those extra cores really help elsewhere.

Running the motion tracking code I was using on a B the difference is very marked. It's only single threaded so the actual image processing isn't much faster but the other cores get to do other OS tasks like update the display if you're watching the results.

I will definitely be ripping the B out of the motion tracking project and putting a Pi2 in. I reckon the B will get retasked for the peer to peer radio project I have in mind as the radio module is designed for the original 26 pin GPIO connector and it really doesn't need the extra grunt to push radio packets around at 256Kbps.

The good thing they have done is make it the same form factor as the B+ and compatible with the same OS images.

Raspberry Pi Motion tracking in Python Pt. 2


Not all USB webcams are created equal.

OK, this is obvious, cheap things are on average crappier than expensive things but the difference here is really marked.

I've built one of these cheap '6 LED' webcams into my project and until I got the code sorted wasn't that worried it would only do 8 FPS.

I was kind of expecting an imperfect image from a cheap webcam but now my code is good the difference in performance is really noticeable.

Knowing I can hit 18-20 FPS or higher with the MS Xbox 360 Live Camera I picked up later is really annoying as the basis of the project is mostly physically built and I thought I could just concentrate on the coding.

The Xbox camera also does a much sharper image with more consistent colour balance and contrast. Which is important as if the camera jerkily changes colour/contrast of the output as the cheaper one is prone to, this gets detected as motion.

None of this is overly surprising as the Xbox cameras were originally reasonably pricey and MS tend to make nice accessories for their consoles.

So unless I can get to the bottom of the poor performance of the original camera (unlikely) I'm going to have to pull it out and replace it with an Xbox one.

If you're thinking of a webcam based project these Xbox ones are really solidly made and seem to be supported by V4L just fine. More importantly they can be picked up secondhand for £1 from CEX, which is a bargain. So you can order a handful of identical cameras to mess about with and embed in things without worrying about cost much.

The ultimate thing to use is probably the official Pi camera which produces fantastic images. But that's 25x the cost for a bare board you need to make or buy an enclosure for.

Raspberry Pi Motion tracking in Python Pt. 1

My next project involves using a Raspberry Pi to do motion tracking. Not something that is difficult nowadays with well developed libraries for image processing like OpenCV.

What I did discover is that a lot of the example code I found was targetted at more powerful things than the Pi and runs at a snail's pace.
So I took one of these projects as a starting point and after initially trying to slim it down and failing I've started from scratch, taking inspiration from a couple of the examples I found.

I now have some Python/OpenCV code that will do >25fps from a USB webcam on the Pi if you keep the source image small.
Here's some of the output of this, with the object outlined and the green blobs showing the track it has moved through. My next step is to do some anticipation so it can track ahead of the object.

Ideally you need to overclock the Pi for best performance but if you only use a 160x120 source image it's still fine at 700Mhz.
I've ordered a Beaglebone Black for this project by way of an upgrade, but for now I'll stick with the Pi as I've managed to squeeze enough performance out of it to be going on with.

To keep power use and heat down the script drops the FPS deliberately when nothing is moving and then ramps up when something happens. I'm not sure if this is 100% necessary but it feels like something you should do and the temperature definitely stays down a bit.

Angry wasp in a box

The project I should be working on instead of messing around with radios involves a Raspberry Pi and Arduino Nano stuck in this old joystick base and working together.

The Pi could almost certainly do all the work but the Arduino is a very robust way to connect to stuff that is 5V friendly, can source a passable amount of current and it's cheap.

It's quite tight in there and the Pi is overclocked running flat out so gets very hot. Hot enough I think to affect stability as the thing tends to hang, which similar code didn't cause before I crammed it all in there.

This evening I hot glued a small fan to the composite socket just above a CPU heatsink I fitted thinking it would help with this. It does a fantastic job but sounds like there's an angry wasp in there. A VERY angry VERY large wasp, so loud I could hear it downstairs. I was expecting it to be a little noisy but it's so horrendous I've just ripped it out again.

Obviously a larger fan would be less noisy but there's really not much space.

Dangly bits

Today I have been connecting dangly bits to things. First up simple whip aerials to the Ciseco Explorer and Slice of radio. Range indoors isn't as good as I'd hoped, walls really do kill the signal.

Then I added the Pi Noir camera my brother bought me for Christmas to one of my Raspberry Pis. This works beautifully and produces a great image but seems to need a bit of faff to make it work with v4l.

The whole thing, especially the ribbon cable, feels like it won't stand rattling around exposed very well. So I've removed it again and packed it away until I can come up with something to hold it secure and have a bit more time to mess with it.