HyperPixel touchscreen radio

I just got a HyperPIxel Raspberry Pi touch-screen LCD display from Pimoroni. This neat display is the same size as the Raspberry Pi itself, and covers all its GPIO pins but it is a touchscreen and it does shift 800×480 pixel video at 60 frames a second. I have plans to do something with a camera and this screen, but as a first project I fell back to my standard: can I make a radio from it?

Being a touch screen, some kind of GUI would be a good idea, and the project I hacked together gave me an excuse to play with Tkinter, the default, but far from ideal, GUI toolkit that Python has installed by default.

I had problems getting the HyperPixel to work at first – I had to do a clean install of Raspbian Jesse, presumably because some other project was interfering with some of the GPIO pins.

First I installed mpc and mpd which I use on the Raspberry Pi to play radio streams or mp3 files:

sudo apt-get install mpc mpd

If you’ve not used mpc before, open the mpd config file with nano like this:
sudo nano /etc/mpd.conf

Then edit these lines to remove some # signs (uncomment) and change the mixer_type from hardware to software so it looks like this:

audio_output {
type "alsa"
name "My ALSA Device"
device "hw:0,0" # optional
mixer_type "software" # optional
mixer_device "default" # optional
mixer_control "PCM" # optional
mixer_index "0" # optional
}

Now add some radio station URLs using the mpc add command. I added BBC 6music, BBC World Service News, FIP, Radio 4 and others. For example to add FIP I typed
mpc add http://chai5she.cdn.dvmr.fr/fip-midfi.mp3

You can find BBC radio URLs on my big list here.

I added 7 stations but you can add more or fewer. They get added in order but you can check your playlist of stations or MP3 files by typing
mpc playlist

And you can change the order using the move command, for example to move station 4 to preset 2 just type:
mpc move 4 2

I then made some 100×100 pixel GIF images (see end of post) for the station logos and wrote some Python/Tkinter code to display the buttons to play each station, a stop/pause button and one to exit the app as it runs full screen. The volume buttons don’t work on my installation for some reason I haven’t fathomed yet.

You could add loads of extras to this like weather and news headlines – or ‘now playing’ information using the frankly mad workaround I used on my web-interface radio back in 2014 (it’s harder than you’d think!)

I did add a digital clock, which accounts for the cut-and-shunt abomination of Python code you see below. If someone can make it more elegant, I’d be highly delighted. It does, however, work.

from tkinter import Tk, Label, Button, E, W, PhotoImage
import os, time

class MyFirstGUI:
    def __init__(self, master):
        global fiplogo
        self.master = master
        master.title("HyperPixelRadio")

        fiplogo = PhotoImage(file="fip100.gif")

        self.label = Label(master, text="HyperPixel Radio by @blogmywiki", font=('Roboto',25), fg = 'blue')
        self.label.grid(columnspan=7, pady=20)

        self.fip_button = Button(master, image=fiplogo, command=self.fip, height=100, width = 100)
        self.fip_button.image = fiplogo
        self.fip_button.grid(row=1, pady=10)

        r2logo = PhotoImage(file="radio2.gif")
        self.r2_button = Button(master, image=r2logo, command=self.r2, height=100, width = 100)
        self.r2_button.image = r2logo
        self.r2_button.grid(row=1, column=1)

        r4logo = PhotoImage(file="radio4.gif")
        self.r4_button = Button(master, image=r4logo, command=self.r4, height=100, width = 100)
        self.r4_button.image = r4logo
        self.r4_button.grid(row=1, column=2)

        x4logo = PhotoImage(file="4extra.gif")
        self.x4_button = Button(master, image=x4logo, command=self.x4, height=100, width = 100)
        self.x4_button.image = x4logo
        self.x4_button.grid(row=1, column=3)

        r5logo = PhotoImage(file="5live.gif")
        self.r5_button = Button(master, image=r5logo, command=self.r5, height=100, width = 100)
        self.r5_button.image = r5logo
        self.r5_button.grid(row=1, column=4)

        r6logo = PhotoImage(file="6music.gif")
        self.r6music_button = Button(master, image=r6logo, command=self.r6music, height=100, width = 100)
        self.r6music_button.image = r6logo
        self.r6music_button.grid(row=1, column=5)

        wslogo = PhotoImage(file="bbcws.gif")
        self.ws_button = Button(master, image=wslogo, command=self.ws, height=100, width = 100)
        self.ws_button.image = wslogo
        self.ws_button.grid(row=1, column=6)

        self.down_button = Button(master, text="< VOL", command=self.down, height=5, width=10)
        self.down_button.grid(row=3)

        self.stop_button = Button(master, text="STOP", command=self.stop, height=5, width = 10)
        self.stop_button.grid(row=3, column=2)

        self.close_button = Button(master, text="close app", command=self.close, height=5, width=10)
        self.close_button.grid(row=3, column=4)

        self.up_button = Button(master, text="VOL >", command=self.up, height=5, width=10)
        self.up_button.grid(row=3, column=6)

    def fip(self):
        print("fip!")
        self.label.config(text='fip - France Inter Paris')
        os.system("mpc play 1")

    def r4(self):
        print("BBC Radio 4 FM")
        self.label.config(text='BBC Radio 4 FM')
        os.system("mpc play 2")

    def x4(self):
        print("BBC Radio 4 Extra")
        self.label.config(text='BBC Radio 4 Extra')
        os.system("mpc play 7")

    def r6music(self):
        print("BBC 6music")
        self.label.config(text='BBC Radio 6Music')
        os.system("mpc play 3")

    def ws(self):
        print("BBC World Service News Stream")
        self.label.config(text='BBC World Service News')
        os.system("mpc play 4")

    def r2(self):
        print("BBC Radio 2")
        self.label.config(text='BBC Radio 2')
        os.system("mpc play 5")

    def r5(self):
        print("BBC Radio 5 Live")
        self.label.config(text='BBC Radio 5 Live')
        os.system("mpc play 6")

    def stop(self):
        print("stop MPC player")
        self.label.config(text='-paused-')
        os.system("mpc stop")

    def close(self):
        os.system("mpc stop")
        root.destroy()

    def up(self):
        os.system("mpc volume +30")

    def down(self):
        os.system("mpc volume -30")

root = Tk()

#root.geometry('720x480')
#root.configure(background='cyan3')
root.attributes('-fullscreen', True)
my_gui = MyFirstGUI(root)

time1 = ''
clock = Label(root, font=('Roboto', 48, 'bold'))
clock.grid(row=4, columnspan=7, pady=20)
def tick():
    global time1
    # get the current local time from the PC
    time2 = time.strftime('%H:%M:%S')
    # if time string has changed, update it
    if time2 != time1:
        time1 = time2
        clock.config(text=time2)
    # calls itself every 200 milliseconds
    # to update the time display as needed
    # could use >200 ms, but display gets jerky
    clock.after(200, tick)
tick()

root.mainloop()

Posted in Raspberry Pi | Tagged , , , | 1 Comment

Standalone microbit scrolling displays

I wanted to make a scrolling display for my desk on parents’ evening, and thought I might use a micro:bit. Then I thought 5 micro:bits might be even better. But how to get them scrolling one message across? I didn’t want to use a computer to control them, I wanted them to be standalone, self-contained. And the radio abilities of the micro:bit mean that no wires should be needed.

So here’s a very simple bit of Python that will turn any number of micro:bits into a rough and ready big scrolling display. There are two different programs, one for the transmitting micro:bit which goes on the right-hand end. Code your message into the Python script and flash it using the Mu editor. When all your other micro:bits are ready, press button A to begin.

--------------------
|RX4|RX3|RX2|RX1|TX|
--------------------

The receiver code goes on all the other micro:bits numbered 1 upwards, lower numbers on the right. Change the number for each device. When powered up they stay blank until they receive the message from the transmitter.

Transmitter code – this goes on the micro:bit on the far right. Code your message in here:

from microbit import *
import radio

message = 'Mr Booth - ICT'

while True:
    if button_a.was_pressed():
        radio.on()
        radio.send(message)
        while True:
            display.scroll(message)

Here’s the receiver code – change the rxnumber for the device number, numbering from 1 on the right, higher numbers as you go left:

from microbit import *
import radio
radio.on()

# set the receive device number here
rxnumber = 1

sleeptime = rxnumber * 750

while True:
    incoming = radio.receive()
    if incoming:
        sleep(sleeptime)
        while True:
            display.scroll(incoming)

UPDATE

Unbeknown to me, Philip Meitiner of the micro:bit Educational Foundation has been working on pretty much exactly the same idea! Can’t wait to see his code as I suspect his is a much more elegant solution:

Posted in Uncategorized | Tagged , | Leave a comment

Book Review: Code Academy by Sean McManus

Code Academy by Sean McManus, illustrated by Rosan Magar.
Ivy Kids / Quarto Publishing, £9.99

This is an intriguing new book to introduce coding to children – there’s no guided age on the back but I think it should appeal to KS2 / 9-11 year olds.

It is beautifully designed, with a good clear layout and attractive illustrations by Rosan Magar. It has a press-out cardboard robot in the front flap, a game poster and stickers at the back that the reader can award themselves as they progress through the exercises. This does make it less useful as a school library text book – it is designed to be written in and each section ends with a certificate that you award yourself. It would, however, make a good present for a child curious about technology and probably work best with a parent or older sibling working through it.

Topics covered include an overview of programming languages, the binary number system, Scratch and HTML, with a welcome emphasis on Scratch. The binary section is short, but strikes me as being a bit odd – it doesn’t really go anywhere and breaks up the flow of the book which builds nicely in the Scratch section through different concepts such as co-ordinates, loops, variables, selection, sprite design and music. I don’t think the binary section would be missed if it were dropped.

I think the focus on Scratch (free, child-centred, widely-supported, works on many devices) is an excellent idea, and I like the inclusion of a section on flowcharts to plan a number guessing game before coding it. It takes the reader through animation, sprite design, planning and making music in a good progression that should be easy to follow and make projects increasingly exciting for children. There is also a web site to offer support where code can be downloaded if readers get stuck.

The chapter on HTML covers the most basic tags, and progresses to add colour using hexadecimal colour codes, which is a nice idea, although it doesn’t explain why #FF0000 is red, #00FF00 is blue etc. This seems like a bit of a missed opportunity to demystify the hex numbers and explain a bit of physics at the same time. Although Javascript is mentioned at the start of the book, there’s no Javascript coding activity in the book, which might have made the HTML a bit more exciting; lack of space and the book’s scope may have made this not possible but its inclusion might have expanded the appeal of the book.

In summary, a well-designed and well-written introduction to coding which could inspire primary-aged children to study computer science in later years, and it will provide a good support to school studies of computing. A timely release for anyone looking for a seasonal gift for a technologically-curious but inexperienced child, grand-child, niece – or for a school prize!

Posted in Uncategorized | Tagged , , , | Leave a comment

Thoughts upon entering a secondhand bookshop

Bought with Loos change

Secondhand bookshops really are the most wonderful things, especially for those, like me, with brains but not brass. It is like being allowed into a salon filled with the greatest minds of our age (Faulkner, Shakespeare, McEwan) whose thoughts you can share for not much more than a hundred pennies.

I wandered in to one such emporium today looking for a sequel. Mr Andrew Millar (who apparently looks uncannily like Rita Tushingham in real life) and some of the other professional readers and writers on his excellent podcast Backlisted said that Gentlemen Prefer Blondes was possibly The Great American Novel, at least a fascinating counterpart to The Great Gatsby, and if Gentlemen Prefer Blondes was the bestselling American novel of 1925, who am I to disagree with the American book-buying public? Anyway I had read and very much enjoyed Gentlemen Prefer Blondes, quite the page-turner and I had no difficulty in finishing it at all, which was a relief because I must say that Mr Millar gets quite cross when people do not finish books they do not like, and I have to say that I think that even I, with my brains, would struggle to finish some of the books that he and his friend Mr John ‘Mitch’ Inson wax lyrical about from time to time.

Reader, you cannot imagine the joy that filled me when, sandwiched between a dozen Alexander McCall Smiths (the proprietor seems only to be on nodding terms with the alphabet), there sat, shyly, a copy of the very sequel to the prequel I had found in this very shop a few weeks previously. Though they have now had the two books by the Loos kind of Anita, it occurred to me that I have never seen a book in there by the other Anita, Brookner (after whom the Brookner Prize is so named.) It is not as if Miss Brookner did not write very many novels, they say she wrote one every summer so as to avoid sunlight, so why do they never have any of them in the shop? I mean, Miss Donna Tartt seems to be just as good at avoiding sunlight and yet somehow manages only to write one book every decade and yet they always have plenty of her novels in this particular shop.

And then I began to wonder if the reason I never find any of Miss Brookner’s books (nor Jane Gardam and scarcely never any of Miss Muriel Sparks’s either) is that they are just too good and people hang on to them. Which means that then most of the books in the secondhand bookshop must, by definition be, at the very best, unwanted if not, at worst, not very good at all. I wondered that as I scanned the shelves crammed with what looked like the complete works of Ian McEwan, Alexander McCall Smith and three identical copies of The Life of Pi. But then there also were orphaned books I love and would have taken home had I not already given home to their identical twins: two copies of The Riddle of the Sands, two copies of The Owl Service, a battered copy of A Fraction of the Whole.

I suppose it just comes down to the fact that one man’s trash is another man’s Treasure Island.

 

 

 

 

 

Posted in fiction, literature | Tagged , , , | Leave a comment

Interfacing Scratch and Python


Hello to Jason Isaacs is the new ‘hello world’.

I decided it might be cool to knock up a simple Scratch interface for the MonkMakes Robot Rover – a bit like the block coding game I made for Year 1 but also controlling a real robot in the real world.

The GPIO commands needed to control the robot directly were going to be a bit heavy and involved, so I decided to see if I could use Scratch to interact with a Python program using the library supplied with the MonkMakes robot. Turns out it’s pretty easy to do this. I’ll write up the robot code later, but here’s a simple example of Scratch interacting with Python.

First I installed scratchpy with
sudo pip install scratchpy

I then opened Scratch and made a very simple program where Scratch cat waits for the message ‘jason’ and replies by saying ‘Hello’. Then I enabled remote sensor connections in Scratch by right-clicking on the () Sensor Value block, found in the sensing category. I then selected the “Enable remote sensor connections” option.

In Python/IDLE 2 I then ran a very simple program to ask your name and broadcast the answer to Scratch. If you replied ‘jason’ you are rewarded with a ‘hello’ back from Scratch cat.

import Scratch
s = scratch.Scratch()
name = raw_input("What is your name? ")
s.broadcast(name)

It’s also possible to respond in Python to messages from Scratch, which I’ll explain next time when we look at the Scratch project to drive a robot round the screen – and a real one round your floor.

Posted in computers, Raspberry Pi | Tagged , , | Leave a comment