Tuesday, 28 July 2015

Change Blogger's "Cookie Consent" bar


If like me you are a user of blogger you will have no doubt notice that Google have kindly added a cookie consent message to your blog.


You may have also seen the announcement when signing into the blogger


Leading you to here to find about more information, including details on how to change the cookie consent bar to be appropriate for your blog.

If you want to change the values in the pop-up bar you can do so by adding a <script> tag into your templates <head>.

Log into Blogger, select Template from the menu and choose "Edit HTML" under the template.

In between the <head> and </head> tags you need to add a script tag and set a variable called "cookieOptions" which contains a json data e.g.:

<script>cookieOptions = {"msg": "This website uses cookies to ensure you get the best experience", "link": "http://www.stuffaboutcode.com/p/about.html", "close": "Ok", "learn": "More" };</script>

Will change the bar to:


The tags all change particular elements of the bar:
  • msg = the message displayed in the box
  • link = the url which clicking "Learn More" will redirect too
  • learn = the text in the "Learn More" button
  • close = the text in the "Got it" button
Note - the official page says the "msg" tag is actually "message", this is incorrect, changing "message" wont affect it.

You don't have to change all the elements, if you just wanted to change the message you could use:

<script>cookieOptions = {"msg": "This website uses cookies to ensure you get the best experience"};</script>

and all the other elements would remain the same.

You can also disable the bar setting cookieChoices to a blank json document using:

<script>cookieChoices = {};</script>


Wednesday, 24 June 2015

Raspberry Pi CPU Temperature

For a project I am working on I needed a really quick way of reading the Raspberry Pi's CPU temperature, most of the solutions I found ran the command line
vcgencmd measure_temp
... via Python's subprocess function and parsed the result.

This just wasn't quick enough for my project as I needed something which would gather lots of data, not just the cpu temperature every second, so I pulled together my own module and class which reads the data directly from /sys/class/thermal/thermal_zone0/temp.

You can find the module at github.com/martinohanlon/CPUTemp, but to use it, just add the following CPUTemp class to your code:
class CPUTemp:
    def __init__(self, tempfilename = "/sys/class/thermal/thermal_zone0/temp"):
        self.tempfilename = tempfilename

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

    def open(self):
        self.tempfile = open(self.tempfilename, "r")
    
    def read(self):
        self.tempfile.seek(0)
        return self.tempfile.read().rstrip()

    def get_temperature(self):
        return self.get_temperature_in_c()

    def get_temperature_in_c(self):
        tempraw = self.read()
        return float(tempraw[:-3] + "." + tempraw[-3:])

    def get_temperature_in_f(self):
        return self.convert_c_to_f(self.get_temperature_in_c())
    
    def convert_c_to_f(self, c):
        return c * 9.0 / 5.0 + 32.0

    def __exit__(self, type, value, traceback):
        self.close()
            
    def close(self):
        self.tempfile.close()
Then to read the temperature use:
with CPUTemp() as cpu_temp:
    print("{} C".format(cpu_temp.get_temperature()))
    print("{} F".format(cpu_temp.get_temperature_in_f()))

Sunday, 21 June 2015

Astro Pi Snake Game

I recently made Snake for the Astro Pi, just for fun really, but I am putting it online as I would like to see what others can do with it - it is literally screaming out to be hacked and improved.

I've given some ideas and tips but there is much more than could be done.

Anyone budding coders up for the challenge?


I started with the code I originally wrote for Minecraft - Snake and made the changes so that rather than creating blocks in Minecraft it turned on leds and used the joystick to control the motion. I was also surprised by how much I improved the overall structure of the code, it wasn't poorly coded it was just a bit untidy.

To try it yourself, get the code from github.com/martinohanlon/AstroPiSnake and run it, by opening a terminal and using the commands:
git clone https://github.com/martinohanlon/AstroPiSnake
cd AstroPiSnake
sudo python astropisnake.py
What else could you do? How would you improve it? Can you improve it?

These are some of the ideas I thought of:
  1. Introduce levels, the better the player does, the faster the snake should go. The speed of the snake is set by the sleep in the startGame() method.
  2. The original game had more than one apple. The apple property would have to be changed to a list and the move() method would have to check if one of many apples had been eaten.
  3. Power ups - special apples which appear for a short amount of time and if you eat them you can go across the screen i.e. exiting the screen on the left would make you appear on the right.
Let me know how you get on - perhaps they'll be a prize!


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 or 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 needed some software which would connect with the good lady's hardware and talk to MPD to 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 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.