Here are some rough notes from our IRFS hardware hackday so I can find them again. The hackday was organised by Cefn Hoile, Andrew Nicolaou and Jasmine Cox, and was utterly brilliant.
This is work by Dan Nuttall, Jasmine Cox, Sean O’Halpin, Nikolaos Tsipas and me (though I did little!) at a hackday organised as part of our 10% time at IRFS at BBC R&D.
The idea was to make a panic button for radio, that allowed you to skip all or part of a programme, e.g. the Archers.
here’s the version we made:
here’s the more exciting ‘farmer’ interface, designed by Jasmine and hooked up by Nikolaos:
Here’s a video of a wifi version I made at home: http://www.flickr.com/photos/nicecupoftea/8649416824/in/photostream/
It consists of a Raspberry PI, a home-made Shrimp with a button, some code that plays IP streams for the audio, which listens for changes to a file and switches streams when it sees a change. Code listens to the serial port and when it detects a button change, changes the right file. I guess we could use the GPIO on the Pi for the button, but I don’t know how to do that yet.
At home, I had a go with my own Pi – I had a power supply and wifi card for it, but no fancy display. This is what I used:
- Raspberry pi
- SD card (I used a speed 10 generic 8GB one)
- some sort of speaker
- wifi usb card for the pi
- power supply for the pi
- arduino or shrimp with a button
I installed wheezy on an SD card via this:
http://www.raspberrypi.org/downloads
http://elinux.org/RPi_Easy_SD_Card_Setup
I then put it in the PI, connected via ethernet and sharing internet on the Mac. I got the IP address using
ping 192.168.2.255
and looking in console.app for a response from a pi – it was 192.168.2.4. I ssh’ed to that using pi@192.168.2.4 password raspberry, then tried to update apt-get
sudo apt-get update
Err http://archive.raspberrypi.org wheezy InRelease
Err http://mirrordirector.raspbian.org wheezy InRelease
Err http://archive.raspberrypi.org wheezy Release.gpg
Temporary failure resolving 'archive.raspberrypi.org'
The default nameserver from the mac didn’t work. Using the google dns fixed it, though this kept getting overwritten on a reboot for some reason:
sudo nano /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
then update apt-get
sudo apt-get update
Install mpd player
sudo apt-get install mpd
[....] Starting Music Player Daemon: mpdlisten: bind to '[::1]:6600' failed: Failed to create socket: Address family not supported by protocol (continuing anyway, because binding to '127.0.0.1:6600' succeeded)
Failed to load database: Failed to open database file "/var/lib/mpd/tag_cache": No such file or directory
. ok
Install the stuff needed for Dan’s player code:
sudo aptitude install ruby1.9.1-dev #for bundler
sudo apt-get install libsqlite3-dev
sudo apt-get install git #install git
Install Dan’s code:
git clone https://github.com/pixelblend/radiodan.git # the code
sudo gem install bundler #to get all the required gems
cd radiodan
bundle install
Put the simple button code on the arduino using laptop:
// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}
void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
//Serial.println(buttonState);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
Serial.println("on");
}
else {
// turn LED off:
digitalWrite(ledPin, LOW);
//Serial.println("off");
}
}
Install required gem for Sean’s serial reading code:
sudo gem install serialport
add in Sean’s ruby code in radiodan/bin/read-serial.rb :
require 'serialport'
filename = ARGV[0] or abort "Need to specify path to file"
sp = SerialPort.new(filename, 9600)
sp.read_timeout = 100
sp.flow_control = SerialPort::NONE
p sp
TIMEOUT = 0.01
TIME_LIMIT = 0.25
PANIC_FILE = "../tmp/panic"
last_time = Time.now.to_f
state = :off
reading = true
begin
while reading
selectors = IO.select([sp], [], [], TIMEOUT)
time = Time.now.to_f
if selectors
input = selectors.first.first
data = input.gets.chomp
state = state == :on ? :off : :on
if state == :on
File.open(PANIC_FILE, "wb") do |file|
file.write Time.now.to_s
end
end
p [data, state]
flushing = true
while flushing
selectors = IO.select([sp], [], [], TIMEOUT)
if selectors
input = selectors.first.first
junk = input.gets
end
time = Time.now.to_f
if time > last_time + TIME_LIMIT
flushing = false
end
end
end
last_time = Time.now.to_f
end
ensure
sp.close
end
plug in the arduino to the pi using the USB port, and identify it:
ls /dev | grep USB
> ttyUSB0
run the serial code in the background
cd bin
ruby read-serial.rb /dev/ttyUSB0
and
./bin/download # get the data - should run in the background
./bin/radio
-> at this point if it’s all running correctly it should work (hear R4 from speaker, press the button and it goes to radio 1 for 5 secs and then returns)
for wifi I used
http://dl.dropboxusercontent.com/u/80256631/install-rtl8188cus.txt
via
http://elinux.org/RaspberryPiBoardVerifiedPeripherals#USB_Wi-Fi_Adapters
I did this at the end, which took a looong time:
“Do you want to continue and update the software packages list, kernel software
packages and upgrade the Pi’s firmware and software or do you want to terminate
the script?”
get IP addresss with ifconfig and use wlan0
iwconfig
-> should be associated with an SSID
-> I had some problems with this…turning it off and on again worked 🙂
Just for reference, here’s the full code for the exciting 7 segment LED display Cefn found for us that Jasmine wrote.
The old ebay listing is here and the library and sample code is here (zip file)
// set pin numbers:
const int buttonPin = 9; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
//We always have to include the library
#include "LedControl.h"
/* we always wait a bit between updates of the display */
unsigned long delaytime=250;
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(12,11,10,1);
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
Serial.begin(9600);
writeRadio4();
}
void loop(){
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
Serial.println("on");
writeRadio1();
}
else {
// turn LED off:
digitalWrite(ledPin, LOW);
// Serial.println("off");
}
}
void writeRadio4() {
lc.setRow(0,7,0x05);
delay(delaytime);
lc.setChar(0,6,'a',false);
delay(delaytime);
lc.setChar(0,5,'d',false);
delay(delaytime);
lc.setRow(0,4,B00010000);
delay(delaytime);
lc.setRow(0,3,0x1D);
delay(delaytime);
lc.setDigit(0,1,4,true); // Display 3 to Digit 3, " "
delay(2000);
lc.clearDisplay(0);
delay(delaytime);
}
void writeRadio1(){
lc.setRow(0,7,0x05);
delay(delaytime);
lc.setChar(0,6,'a',false);
delay(delaytime);
lc.setChar(0,5,'d',false);
delay(delaytime);
lc.setRow(0,4,B00010000);
delay(delaytime);
lc.setRow(0,3,0x1D);
delay(delaytime);
lc.setDigit(0,1,1,true); // Display 3 to Digit 3, " "
delay(delaytime);
lc.clearDisplay(0);
delay(5000);
}