Since September I’ve been teaching ICT and Computing solely in a primary school, having spent two hectic but enjoyable years teaching from KS2 to KS4 in a girls’ school in London. I’m re-writing a curriculum that has much more focus on programming, and I am trying to include KS1 (and even Reception) in this. It’s a challenge because we have discrete 1 hour lessons in an ICT suite designed for older children, using desktop PCs. We do not have any working tablets, no Beebots nor indeed the physical space for a whole class to be using them at the same time.
I can and do teach Scratch as low as Year 2 (US 1st grade), but years below that are especially tricky. I couldn’t find any free web or PC-based resources that did what I want (ScratchJr is great but requires tablets), so my first attempt was a maze game I made in Scratch for Year 1 (US equivalent: kindergarten) where you had to program a character to reach a target using instruction blocks: up, down, left, right and then a number to say how many steps you should go.
This was a mixed success. Some children loved it, and suggested some fantastic ideas I incorporated into the game, such as levels, more mazes, more targets, hazards. The great thing about making teaching resources in Scratch is that if a child has a simple idea to improve it, you can edit the game there and then and reload it so they can see their idea made real even if they are too young to use Scratch themselves. Some children, however, found it hard to access and got frustrated. Indeed, one girl was so terrified of the dragon hazard she burst into tears and had to be consoled by a teaching assistant – which was a valuable lesson to me about how invested young children can get in a world I created for them, something I had forgotten with the passage of time but suddenly recalled from my own childhood.
After a bit of thought I made a new project. This is much more complex, but it’s not a game. It is not competitive, it does not have points or levels but it is much more creative and open and you will see that even if the child does not understand how it works, they can still make amazing things just by experimenting.
It’s a turtle graphics program made in Scratch. You program your turtle to go forwards, backwards, turn left or right by clicking on blocks (you can click on the turtle and change it to other animals of choice). This program sends the turtle forwards 3, then turns right 6. The 6 is a bit of an arbitrary number. Year 1 are too young to have angles in degrees thrown at them, so I made the turn amount multiples of the default Scratch turn amount of 15 degrees.
To run the program you click on a big ‘go’ button in a green flag. This is deliberate, using the symbol and colours that mimic what they will find when they do their own Scratch coding next year: the move and turn buttons are blue for a reason.
Click ‘go’ four times and you get a square. I got the children to act this out on the carpet, moving forwards, turning right, forwards, right… until we traced a square with our feet. We looked at how we can make smaller or larger squares by changing the forwards number. We also had a fantastic discussing about why the ‘up’ arrow does not mean ‘up’ but really means ‘forwards’ – I was thrilled when a girl who struggles a bit to use the computer mouse and keyboard gave a brilliant explanation: ‘it will go right because that’s the way the turtle is facing.’ I may have punched the air at that point – with no explanation from me she had worked out that the instructions are from the turtle’s point of view, not ours.
I then got them to experiment and see what other shapes they could make. Here are some of their patterns:
You’ll notice here that even without being told about them, many children discovered the blocks that make the turtle’s pen thicker and change colour. Some even found the magic ‘plus’ number block – this increases from 1 to 9 and then loops back to 1 allowing angles, thickness and colours to change with every run of their programs.
Some also discovered that if you click on the top of the big orange bracket (again the colour and shape are deliberate to mimic Scratch) you get a repeat block that allows you to run your instructions multiple times with one click on the go button:
Keep clicking on the repeat number and you get ‘for ever’ and it just keeps going. With thick lines and lots of turn blocks some children made very colourful animations that were great fun to watch, something I had not expected or planned. You can also edit your code while it is running, just like in Scratch itself or Sonic Pi. So this is live coding for Year 1!
There were no tears, very little frustration across the year group. I did get a couple of boys (who had enjoyed the previous competitive game) get cross when they couldn’t make patterns, in both cases because they were only moving their turtles forwards or backwards but not turning at all. Once we swapped a single forwards/backwards instruction block for a turn they started making patterns and were happy.
If you’d like to try my project for yourself, here it is. I’d love to hear any ideas you may have to improve it to. The thing I’m most unsure about is the turn number – the number doesn’t really relate to anything but I wanted a certain amount of ‘granularity’ to enable many different polygons to be made, and multiples of 15 degrees allow this. Anyway – have a play. Playing is learning. Playing is good.
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://icecast.radiofrance.fr/fip-midfi.mp3
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.
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.
Update – running automatically at boot
If you want to make this run automatically at boot, you need to do a couple of things. You need to change all the references to the .gif files to have absolute paths to the folder where you put the image files. Then edit an autostart file with: sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart
to add a line something like this: @python3 /home/pi/Desktop/HyperPixelRadio/radio-gui.py
(you will need to change the path to where you saved the main Python program).
**Update June 2020**
In recreating this on a fresh Raspbian Buster install and a new, bigger HyperPixel display and I’ve had a few… issues.
I could not get MPC to play out of the analogue audio jack at all – until I unplugged the HDMI display. Even when VLC and everything else was playing via analogue out, MPC persisted with playing out of HDMI. No idea why.
Also, to get it to run at startup I needed to add @python3 /home/pi/Desktop/HyperPixelRadio/radio-gui.py
to a different file with this command:
sudo nano /etc/xdg/lxsession/LXDE-pi/autostart
I also need to work out how to rotate the screen…
New version of the program with IP address and shutdown buttons
#!/usr/bin/env python3
from tkinter import Tk, Label, Button, PhotoImage
import os, time, subprocess
time1 = ''
IP = subprocess.check_output(["hostname", "-I"]).split()[0]
class MyFirstGUI:
def __init__(self, master):
global fiplogo
self.master = master
master.title("HyperPixelRadio")
fiplogo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/fip100.gif")
self.label = Label(master, text="HyperPixel Radio by @blogmywiki", font=('Lato Heavy',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, padx=4)
r2logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/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, padx=4)
r4logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/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, padx=4)
x4logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/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, padx=4)
r5logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/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, padx=4)
r6logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/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, padx=4)
wslogo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/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, padx=4)
self.down_button = Button(master, text="< VOL", command=self.down, height=5, width=10)
self.down_button.grid(row=3)
self.up_button = Button(master, text="shut down", command=self.shutdown, height=5, width=10)
self.up_button.grid(row=3, column=1)
self.close_button = Button(master, text="close app", command=self.close, height=5, width=10)
self.close_button.grid(row=3, column=2)
self.ip_button = Button(master, text="show IP", command=self.ipaddr, height=5, width=10)
self.ip_button.grid(row=3, column=3)
#spare button could be for 'now playing' info
self.ip_button = Button(master, text=" ", command=self.nowPlaying, height=5, width=10)
self.ip_button.grid(row=3, column=4)
self.stop_button = Button(master, text="pause", command=self.stop, height=5, width = 10)
self.stop_button.grid(row=3, column=5)
self.up_button = Button(master, text="VOL >", command=self.up, height=5, width=10)
self.up_button.grid(row=3, column=6)
def ipaddr(self):
self.label.config(text=IP)
def nowPlaying(self):
self.label.config(text="now playing info here")
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")
def shutdown(self):
print("shutting down system")
os.system("sudo shutdown now")
root = Tk()
#root.configure(background='cyan3')
root.configure(cursor='none')
root.attributes('-fullscreen', True)
my_gui = MyFirstGUI(root)
time1 = ''
clock = Label(root, font=('Lato Light', 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()
Original version of the program
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()
Update, Feb 2020
** I added Scala Radio… and Fip can currently be found at http://icecast.radiofrance.fr/fip-midfi.mp3
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.
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:
Found time to work on my #microbit RC matrix. Smooth scrolling was target for weekend – almost there! Lots of todos but a nice milestone :) pic.twitter.com/ltxOTggHgg
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!
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.