For many years my daughter called me in the evening in her room: “Daddy, please play the barrel organ!”
I usually asked: “How fast?”
And she replied: “Full speed!”
Okay.
After about ten years – my hands have become old and tired – I knew that I need a machine. I spoke to my daughter and we began to make plans.
After hours of thinking we built a prototype with some toys:
And this is the funny result!
Attention: first you will hear nothing (or some noise from my stomach). Only when I touch my smartphone, you will hear LED ZEPPELIN! Yeah!
Here are some detailed images:
- Raspberry Pi with XBee USB dongle
- Arduino UNO with Motor Shield and Wireless Shield and XBee module
- The barrel organ and the electric motor
The ingredients for our openHAB Raspberry Pi Arduino XBee Led Zeppelin Music Machine:
- HABDroid running on a Samsung Galaxy smartphone
- a Raspberry Pi
- with a XBee USB dongle
- the openHAB runtime (extended with a custom XBee Binding)
- an Arduino UNO
- with a motor shield
- a wireless shield (with a XBee module fitted)
- an electric motor
- a barrel organ
The sequence of events:
- my finger pushes the “Led Zeppelin on/off” switch on the HABDroid app on my smartphone
- HABDroid sends the event over my WLAN to the openHAB runtime running on the Raspberry Pi
- my openHAB binding receives the event, connects to the XBee USB dongle and sends “1” (0x31)
- my Arduino UNO receives the “1” over the XBee receiver item on the Wireless Shield
- my Arduino UNO sends “full speed” to the connected electronic motor
- the electronic motor starts and drives the barrel organ
Here is a very basic list of what you have to do if you want to build the same crazy thing:
- Install openHAB on a Raspberry Pi (must be connected to a LAN because we want to use HABDroid on a smartphone to control the openHAB runtime) – s. notes for openHAB
- Plug a XBee USB dongle into the Raspberry Pi – s. notes for XBee
- Do some Linux configuration on your Raspberry Pi – I use Raspbian – s. notes for Raspbian
- Configure your openHAB runtime to provide a switch for HABDroid – s. notes for openHAB
- Install a Java IDE for coding your custom XBee openHAB Binding for sending data over the XBee USB dongle and export it to your openHAB installation – s. notes for openHAB
- Place your Arduino UNO with a Motor Shield and a Wireless Shield (with a XBee module fitted)
- Install the Arduino IDE to create the “XBee” code and upload it to your Arduino – s. notes for the Arduino UNO
- Find a solution for how you can connect your Motor Shield to an electric motor and finally to the barrel organ.
- Think like a hobbyist and leave your family for two weeks to get it work!
Notes for Xbee:
For wireless commication between Raspberry Pi and the Arduino UNO we use two XBee modules. One as ZigBee Coordinator, the other one as ZigBee Router, both in API mode.
TIP: if you want to configure and test the XBee modules in a comfortable way, do it with the XCTU GUI! Here’s a screenshot:
Notes for Raspbian (or the OS which you run on your Raspberry Pi):
- Install Rxtx: sudo apt-get install librxtx-java – this installs librxtxSerial.so into /usr/lib/jni which we need for our XBee communication
- find our where your XBee USB dongle is mounted. In my case it is: /dev/ttyUSB0
- go to /dev and find out the group name of your XBee USB dongle. In my case it’s the group dialout
- add your openhab user to the dialout group
Notes for openHAB:
Edit the openHAB start scripts on your Raspberry Pi. In my case: /usr/share/openhab/bin/openhab.sh
You’ll find a part like this one:
... JAVA_ARGS_DEFAULT="-Dosgi.clean=true \ -Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0 \ -Declipse.ignoreApp=true \ -Dosgi.noShutdown=true \ -Djetty.port=${HTTP_PORT} \ -Dopenhab.configfile="${OPENHAB_CONF_DIR}/configurations/openhab.cfg" \ -Dopenhab.configdir="${OPENHAB_CONF_DIR}/configurations" \ -Dopenhab.logdir="${OPENHAB_LOG_DIR}" \ -Dsmarthome.userdata="${OPENHAB_USER_DATA_DIR}" -Djetty.home="${OPENHAB_DIR}" \ -Djetty.port.ssl=${HTTPS_PORT} \ -Djetty.config="${OPENHAB_CONF_DIR}/jetty" \ -Djetty.logs="${OPENHAB_LOG_DIR}" \ -Djetty.rundir="${OPENHAB_DIR}" \ -Dfelix.fileinstall.dir="${OPENHAB_DIR}/addons" \ -Dfelix.fileinstall.filter=.*\\.jar \ -Djava.library.path="${OPENHAB_DIR}/lib:/usr/lib/jni" \ ...
- I added the line starting with “-Dgnu.io.rxtx.SerialPorts” (don’t forget to use the name of your XBee USB dongle mounting)
- and I extended the java.library.path parameter with the /usr/lib/jni path (s. below Rxtx installation)
The sitemap configuration:
Frame label="Music Machine" { Switch item=MusicMachineSwitch label="Led Zeppelin on/off" }
My items configuration:
Switch MusicMachineSwitch "Xbee Music Machine Switch" { mzxbee }
My setting for the openhab.cfg:
These are some configurations, which I use in my Java code. I want to communicate with 9600 baud, the mounting point for my Xbee USB dongle is /dev/ttyUSB0 and the MAC address of the receiver is “00 13 A2 00 40 A2 5A EC”
mzxbee:baud=9600 mzxbee:comPort=/dev/ttyUSB0 mzxbee:address=0013A20040A25AEC
For our custom XBee openHAB Binding we use this Java API:
XBee Java Library
Here’s the important part of the Java code:
logger.debug("Instantiating device with comPort " + comPort + " and " + baud + " baud..."); XBeeDevice myDevice = new XBeeDevice(comPort, baud); logger.debug("Opening device..."); myDevice.open(); logger.debug("Instantiating address..."); XBee64BitAddress addr64 = new XBee64BitAddress(address); logger.debug("Instantiating RemoteXBeeDevice device..."); RemoteXBeeDevice myRemoteXBeeDevice = new RemoteXBeeDevice(myDevice, addr64); logger.debug("********************* Sending sync data: " + value + " > byte value: " + Character.digit(value,16)); myDevice.sendData(myRemoteXBeeDevice, new byte[]{ (byte)value }); logger.debug("Closing device..."); myDevice.close();
value can be 1 to turn the music machine on and 0 to turn it off.
Notes for the Arduino UNO
This is the code for the Arduino UNO. I want to let a LED blink, when the Arduino starts. The same LED shall light, when the music plays.
#include <XBee.h> int incomingByte = 0; // for incoming serial data int dirA = 12; int brake = 9; int mspeed = 3; const int led = 7; Rx16Response zbRx = Rx16Response(); XBee xbee = XBee(); void setup() { Serial.begin(9600); // opens serial port, sets data rate to 9600 bps xbee.setSerial(Serial); pinMode(led, OUTPUT); pinMode(dirA, OUTPUT); pinMode(brake, OUTPUT); pinMode(mspeed, OUTPUT); // blink twice at startup digitalWrite(led, LOW); delay(1000); digitalWrite(led, HIGH); // first blink delay(50); digitalWrite(led, LOW); delay(200); digitalWrite(led, HIGH); // second blink delay(50); digitalWrite(led, LOW); } void loop() { digitalWrite(dirA, LOW); digitalWrite(brake, LOW); // send data only when you receive data: if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read(); if(incomingByte == '0'){ digitalWrite(led, LOW); analogWrite(mspeed, 0); } else if(incomingByte == '1'){ digitalWrite(led, HIGH); analogWrite(mspeed, 255); } } }
To-Dos:
- add speed control! More speed! Much more!
- … ideas …?
Comments 1
LOL! What an amazing project!
Made my day!