Wednesday, 20 May 2015

Interactive Minecraft Astro Pi

I have created what I think is a fun way to explore your new Astro Pi - its an interactive Astro Pi in Minecraft.


All of the components on the board are 'hitable' so when you right click them while holding a sword, it will tell you about that component is or make it work e.g. if you hit the humidity sensor it will tell you the humidity value at that time, or if you hit the led matrix it will light that led on the board.


If you have got an Astro Pi board and haven't yet set it up take a look at my Astro Pi - Getting Started Tutorial.

Once your Astro Pi is up and running you can download the code from github.com/martinohanlon/MinecraftInteractiveAstroPi and run it by opening a terminal and using the following commands:
cd ~
git clone https://github.com/martinohanlon/MinecraftInteractiveAstroPi.git
cd MinecraftInteractiveAstroPi
sudo python mcinteractiveastropi.py
The Minecraft Astro Pi board will appear above the player, so fly up (double tap space) and have a look around. You interact with it by hitting it (right clicking) with a sword.

Someone let me know that they got an error while trying to use the program with Python 2 because AstroPi needs a module called PIL which wasn't installed. I didn't get this error but if you received the error "No module named PIL", run the following command to install it:
sudo pip install Pillow


Monday, 18 May 2015

Raspberry Pi Vintage Radio Build

Mrs O'Hanlon buys tat (aka vintage collectibles) and the one thing she seems to buy more than anything else is old radio's, which never work. One such broken audio player I found in her collection was a circa 1955 Vidor Lady Anne and I decided to give it a new lease of life and turn it into a Raspberry Pi powered music player.

My aims were to use the original switches, knobs and dials for the controls and when finished it would look the same as the original.



I wanted to use the original on/off switch to start and stop playback, the medium wave / long wave positions to select a playlist (M for Martin's playlist and L for Mrs O'Hanlon's playlist) and the tuning wheel to skip tracks forward and backwards.


I needed a few things to make this a reality:

  • A Raspberry Pi!
  • A decent DAC (Digital to Analogue Converter) and AMP to power the speaker
  • A music player with a programmable API so I could integrate the original controls
  • A way of talking to Lady Anne's ancient hardware.
  • A program which would be the bridge between Lady Anne and the music player

DAC & Amp

At the Raspberry Pi 3rd Birthday Party I met the guys from IQ Audio and I purchased their DAC+ and Amp+ boards, which appealed to me because of the modular build and because the DAC+ still allowed access to GPIO pins (via an L shaped pin connector you can solder to the bottom). This gave me the guts of the system, now I needed software and hardware.


Music Player

I decided on Volumio as the music player, which is a very fancy open source music player which sits over the top of MPD (music player daemon). It has a very nice responsive web front which works really well with both desktop and mobile browsers.


As volumio is built on top of MPD I could use the python-mpd2 module for interfacing with it - see my blog post Volumio, MPD & Python for an overview of how this works.

Lady Anne's Hardware

I stripped out all the gubbins from the old music player apart from the on/off switch and the volume control.



Including 60 years of fluff and dust from the speaker.


This left me with a frame with the switch and the volume control potentiometer, the next step was to work out how the switch worked, its made up of layers, with each layer having a rotating copper disk which when turned connected 2 more more connections.



Much testing was done with a multimeter to work out what each of the terminals on the switch did.

The switch is actually many switches and when I connected a current to it, I was also surprised to see that it also wasn't digital, it simply leaks current, off is anywhere between 0v - 1.5v and this totally messes up the Raspberry Pi's GPIO pins.

As I needed an ADC (Analogue to Digital Converter) to read the value from the potentiometer I came up with the concept of an 'analogue' switch and used an MCP3008 ADC to read the values from the switch and when it was above certain voltage I considered it to be on, below it was off - see my blog post Raspberry Pi, MCP3008 ADC & Python for an overview of using the MCP3008 ADC.


To get the MCP3008 to work with the IQ Audio DAC I had to do a bit of hacking. While the majority of the GPIO pins are exposed by the connector on the DAC, neither of the SPI chip select pins are, which I needed, to talk to the MCP3008.

A few emails to IQAudio suggested that while the pins weren't connected, they could be, so I put a small wire between the raspberry pi header and the GPIO connector on the DAC.


The last piece of hardware I needed was a rotary encoder which would fit under the tuning wheel and skip tracks - see my post Raspberry Pi and KY040 Rotary Encoder for an overview on how to use one.


Add all that together and what you end up with is this a breadboard design which looks like this.


Radio control program

Before I put it all together I need some software which would connect with the good lady's hardware, talk to MPD and make the controls work.

I sketched out a design (like a proper professional) which would broadly involve creating classes to manage each element of the hardware (on/off, playlist selector, volume control, etc) all of which would all place events in a queue.


The events would be actions that would need to be taken by the main radio control program (e.g. on, off, change volume, skip track, etc) by talking to MPD.  Event based software is really useful for managing hardware where multiple things can all happen at once, but you only want to do one thing at a time.

The software is online at github.com/martinohanlon/PiLadyAnneRadio and it includes information about the structure of the code and installation - although don't expect it to work without modification as while most of the classes are re-usable its built specifically for this radio.

Putting it together

To put it all together I needed to find a way of mounting the Raspberry Pi, DAC & Amp in Lady Anne and turning a mess of components and jumper cables on a breadboard into something which would work reliability.

I moved the breadboard jumble onto stripboard - I made myself a map and soldered the cables and components directly onto the board.


I mounted the Pi, DAC & Amp and the stripboard onto perspex which I bolted onto Lady Anne's original frame. Luckily the original lady had a space inside the case for a large battery which was just the right size to fit the Pi in.


That was it, the lady lived...

There was are a couple of things I want to improve. The original potentiometer is rubbish, its not linear and for the first half a turn nothing happens. It could also do with a better speaker, the quality is not bad, but at higher volumes it cuts out.

Tuesday, 12 May 2015

Astro Pi - Getting Started Tutorial

You have managed to get your hands on an Astro-Pi Sense HAT board...  Lucky you.  If you need some help getting started - read on.


Install Astro-Pi software
If you didn't get an Astro Pi prebuilt SD card with your board you will need to install the software.

Open up a terminal and run the following command, it will take about 5 minutes to run on a Pi 2 and about a 20 minutes on a Pi 1.
wget -O - http://www.raspberrypi.org/files/astro-pi/astro-pi-install.sh --no-check-certificate | bash
When the install has finished you will have to reboot your Pi.

Example programs
The nice people at Raspberry Pi have provided some example programs which are a great way to test if everything is working

Open a terminal and change directory to the Astro-Pi example's and list the contents:
cd ~/astro-pi-hat/examples/
ls

Each of the files which ends in .py is an example python program and can be run from the terminal using
sudo python [name_of_example.py]
e.g.
sudo python rainbow.py


Run each of the example program and see what they do:
  • colour_cycle.py - loops through all the colours on the led matrix.
  • compass.py - shows a dot on the led matrix which points north
  • pygame_joysticks - shows how to use the pygame module to read the mini joystick and display the joystick direction on the led matrix
  • rainbow.py - shows a rainbow of colours on the led matrix
  • rotation.py - shows how to rotate the led matrix and shows a question mark
  • space_invader.py - displays the space invader icon in the space_invader.png file on the led matrix
  • text_scroll.py - a scrolling text message appears on the led matrix
Hello Space
Writing your first program for the Astro Pi board is really simple, there is a great Astro Pi python library that takes away most of the complex code and leaves you to have fun.

Because the Astro Pi board needs access to the GPIO pins you will need to run your programs as a 'super user' using sudo. I think the easiest way of doing this is to start the Python editor IDLE using sudo that way you can run your programs without having to do anything special.

Open IDLE as a super user by starting a terminal and typing:
sudo idle3 &
The python shell will now start, click File -> New Window to create a new program.

Import the AstroPi class and create the object:
from astro_pi import AstroPi

ap = AstroPi()
You can use the show_message() function to display a message on the LED matrix:
ap.show_message("Hello Space")
To run your program, click Run -> Run Module.

You should see hello space scroll on the LED matrix.

LED Matrix

The AstroPi class allow you to interact with the colour LED matrix using the set_pixel(x, y, red, green, blue) function. x and y are the coordinates on the led matrix starting top left 0-7. red, green, blue are the colour values 0-255.

To make the top left pixel red you would use:
ap.set_pixel(0, 0, 255, 0, 0)
To make the bottom right pixel white (all colours) you would use:
ap.set_pixel(7, 7, 255, 255, 255)
Add the code above to your program and run it.

To turn a pixel off you would set it to black (no colours):
ap.set_pixel(7, 7, 0, 0, 0)
You can clear all the pixels using:
ap.clear()
The clear() function can also be used to set all the pixels to one colour by passing the r,g,b values in a list i.e. blue:
ap.clear([0,0,255])

Reading Sensors
The Astro Pi board comes with the following sensors which you can read:
  • Orientation (yaw, pitch & roll) via an accelerometer, 3D gyroscope and magnetometer
  • Pressure
  • Humidity
  • Temperature (via the pressure and humidity sensors)
Create a new program and as before import the AstroPi class and create the object:
from astro_pi import AstroPi

ap = AstroPi()
The pressure in millibars can read using the get_pressure() function:
pressure = ap.get_pressure()
print(pressure)
The percentage of relative humidity can be read using the get_humidity function:
humidity = ap.get_humidity()
print(humidity)
The temperature in degrees Celsius can be read using the get_temperature() function.
temp = ap.get_temperature()
print(temp)
The Astro Pi boards humidity and pressure sensors can both read temperature and you can specify which one you want to use with the get_temperature_from_humidity() and get_temperature_from_pressure() functions:
temp = ap.get_temperature_from_pressure()
print(temp)

temp = ap.get_temperature_from_humidity()
print(temp)
Orientation of the Astro Pi board can be read in degrees and radians using the functions get_orientation_radians() and get_orientation_degrees(). Both functions return the 3 flight axes of yaw, pitch and roll as a python dictionary:
orientation = ap.get_orientation_degrees()
print(orientation["yaw"])
print(orientation["pitch"])
print(orientation["roll"])

orientation = ap.get_orientation_radians()
print(orientation["yaw"])
print(orientation["pitch"])
print(orientation["roll"])
Run the program to see the sensor values displayed.

These are just a sample of the functions available, there is a complete list and reference in the ~/astro-pi-hat/docs/index.md file, which you can also view here github.com/astro-pi/astro-pi-hat/blob/master/docs/index.md

Tuesday, 5 May 2015

Raspberry Pi and KY040 Rotary Encoder

For a Raspberry Pi powered vintage radio build I'm doing I wanted to replace the original tuning dial with a turning switch which I could use to skip tracks backwards and forwards.

Being notoriously tight I opted for the VERY cheap KY040 (Amazon UK, US) rotary encoder module (less than £1 from the right stores). What a didn't realise when I brought it was that it doesn't use the typical 'gray code' for its encoding - this led to more than a few hours of frustration, so here is some setup and code to save you from the same!


The KY040 has 5 pins:
  • GND - ground
  • + - 3.3v
  • SW - switch
  • DT - data
  • CLK - clock
The SW pin is the switch pin and goes high when the rotary encoder is pushed.

The CLK (clock) and DT (data) pins are how you read the direction the encoder has been turned. The CLK pin goes low when the encoder has been turned and the DT pin shows which was it has been turned, low for clockwise, high for anti clockwise.

The SW, CLK and DT pins should be connected to GPIO pins on the and Pi, the + and GND are pretty self explanatory and should be connected to a 3.3v and ground pin.


I connected CLK to GPIO 5, DT to GPIO 6 and SW to GPIO 13.

The code uses RPi.GPIO's edge detection functions to trigger a callback when the CLK pin goes low and then reads the value from the data pin to work out if it was turned clockwise or anti-clockwise.

The code repository is on github https://github.com/martinohanlon/KY040.

There is a class, KY040, which expects the GPIO pins to be passed and 2 callback functions which are called when the dial is turned or the switch is pressed.

#KY040 Python Class
#Martin O'Hanlon
#stuffaboutcode.com

import RPi.GPIO as GPIO
from time import sleep

class KY040:

    CLOCKWISE = 0
    ANTICLOCKWISE = 1
    
    def __init__(self, clockPin, dataPin, switchPin,
                 rotaryCallback, switchCallback):
        #persist values
        self.clockPin = clockPin
        self.dataPin = dataPin
        self.switchPin = switchPin
        self.rotaryCallback = rotaryCallback
        self.switchCallback = switchCallback

        #setup pins
        GPIO.setup(clockPin, GPIO.IN)
        GPIO.setup(dataPin, GPIO.IN)
        GPIO.setup(switchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

    def start(self):
        GPIO.add_event_detect(self.clockPin,
                              GPIO.FALLING,
                              callback=self._clockCallback,
                              bouncetime=250)
        GPIO.add_event_detect(self.switchPin,
                              GPIO.FALLING,
                              callback=self._switchCallback,
                              bouncetime=300)

    def stop(self):
        GPIO.remove_event_detect(self.clockPin)
        GPIO.remove_event_detect(self.switchPin)
    
    def _clockCallback(self, pin):
        if GPIO.input(self.clockPin) == 0:
            data = GPIO.input(self.dataPin)
            if data == 1:
                self.rotaryCallback(self.ANTICLOCKWISE)
            else:
                self.rotaryCallback(self.CLOCKWISE)
    
    def _switchCallback(self, pin):
        if GPIO.input(self.switchPin) == 0:
            self.switchCallback()

#test
if __name__ == "__main__":
    
    CLOCKPIN = 5
    DATAPIN = 6
    SWITCHPIN = 13

    def rotaryChange(direction):
        print "turned - " + str(direction)
    def switchPressed():
        print "button pressed"

    GPIO.setmode(GPIO.BCM)
    
    ky040 = KY040(CLOCKPIN, DATAPIN, SWITCHPIN,
                  rotaryChange, switchPressed)

    ky040.start()

    try:
        while True:
            sleep(0.1)
    finally:
        ky040.stop()
        GPIO.cleanup()

You can buy the same rotary encoder without the module but you will have to add pull ups to the CLK and DT pins.

Wednesday, 29 April 2015

Raspberry Pi, MCP3008 ADC & Python

I'm converting a vintage radio into a Raspberry Pi powered music player and I needed an analogue to digital converter (ADC) to allow my raspberry pi to read the old crusty switched and volume controls.

The MCP3008 ADC is pretty cheap and easy to use with the Pi, so I bagged myself one.


Raspberry Pi Spy has got a really good tutorial on setting up an MCP3008 to read analogue sensors which I followed to get everything running, but the code didn't fit my needs so I created a python class for reading data from the MCP3008.
from spidev import SpiDev

class MCP3008:
    def __init__(self, bus = 0, device = 0, channel = 0):
        self.bus, self.device, self.channel = bus, device, channel
        self.spi = SpiDev()

    def __enter__(self):
        self.open()
        return self

    def open(self):
        self.spi.open(self.bus, self.device)
    
    def read(self):
        adc = self.spi.xfer2([1, (8 + self.channel) << 4, 0])
        data = ((adc[1] & 3) << 8) + adc[2]
        return data

    def __exit__(self, type, value, traceback):
            self.close()
            
    def close(self):
        self.spi.close()

The class is really easy to use, using Python's 'with' statement to control it:
with MCP3008(channel = 0) as ch0:
    print ch0.read()
The code is here - github.com/martinohanlon/mcp3008

Sunday, 12 April 2015

Python, MPD and Volumio

I'm building a Raspberry Pi powered vintage radio, by stripping out all the gubbings and add a raspberry pi, IQAudio DAC & Amp.


I'm going to use Volumio to provide the music player and UI, but in order to get the existing buttons on the radio working I need to interact with MPD (Music Player Daemon) which is the server software which makes it all work.

There is a python library called python-mpd2 [code] which provides an api for communicating with MPD, its pretty easy to use and it allows you to do things such as change the volume, play, pause, stop, skip tracks, change playlists, search for music, etc.

Install python-mpd2

I found that I need to install python's "setup tools" when using the volumio image:
wget https://bootstrap.pypa.io/ez_setup.py -O - | sudo python
Once setup tools is installed you can download python-mpd2 and install it:
git clone git://github.com/Mic92/python-mpd2.git
cd python-mpd2
sudo python setup.py install
Usage

The python-mpd2 module is pretty easy to use, its effectively a python client for the MPD server. The first steps are to import it, create the MPDClient and connect to the server.
from mpd import MPDClient
client = MPDClient()
#to connect to MPD you need to know the IP address and port
client.connect("localhost", 6600)
Once you are connected you can use the client to issue commands to the MPD server, such as pulling back the current status and the current version.
print(client.status())
print(client.mpd_version)
Some useful other mpd-python2 functions are:
#set the volume between 0 and 100
client.setvol(100)

#play song at certain position
client.play(1)

#pause and resume playback
client.pause(0)
client.pause(1)

#skip to the next or previous track
client.next()
client.previous()

#clear current playlist and load a new one
client.playlistclear()
client.load("nameofyourplaylist")
Here is a complete list of mpd-python2 commands.

Thursday, 2 April 2015

Autcraft - Autism Awareness Day

2nd April is Autism Awareness Day and on this day Start Duncan tries to get as many people talking about Autism and Bullying. You can read his call to arms on his blog.


Stuart (or AutismFather) runs a really special Minecraft server called Autcraft which is for children with Autism and their families.

He started Autcraft because there were so many Autistic children who where bullied or were excluded on other Minecraft servers, which I really struggle with, so I wanted to create a Minecraft program and a video to support Stuart, Autcraft and Autism Awareness Day.



The animation is all written in Python and a lot of the code is borrowed from some of my other Minecraft projects.

The code to create the diamond block text was taken from my Minecraft twitter client and the leg and boot is created in the same way I create and move around the ships in the Minecraft Starwars animation.

The rest of it is just Monty Python inspire silliness with a very important message "don't stand for bullying".

If you want to take a look at the code or run it yourself - github.com/martinohanlon/minecraft-autismawarenessday