Concept: create a robotic musical instrument using a sensor and actuator
Sensor: Pressure sensitive pad
Actuator: Solenoid
Solenoid powered by 12v dc required TIP120 transistor to switch on and link to Arduino (which runs at 5v dc) – the circuit includes a diode to prevent damage to the Arduino caused by “inductive motor kick back”.
Here is the code used:
Solenoid Code
/* Solenoid Triggered by Pressure Sensor – 5th May 2010
by Benjamin Freeth, MRes. Digital Media, Culture Lab, Newcastle University
Pressure Sensor connected to Analog 0
Solenoid connected to Digital Pin 3
inputs
*/
int potPinA = 0; // select the input pin for the potentiometer
int solenoidPinA = 3; // select the pin for the solenoid
int valA = 0; // variable to store the value coming from the
void setup() {
pinMode(solenoidPinA, OUTPUT); // declare the ledPin as an OUTPUT}
Serial.begin(9600); // initialize serial communications at 9600 bps:
}
void loop() {
valA = analogRead(potPinA); // read the value from the sensor
Serial.print(“sensor = ” ); // print the results to the serial monitor:
Serial.println(valA); // print the sensor value and a line break to seperate sensor values
if (valA >= 1) // If statement to test variable if greater than or equal to 1 i.e. pressure sensor has not been pressed
{// various resistors could be used to change the sensitivity or range of this sensor? – try this!
digitalWrite(solenoidPinA, LOW); // send the solenoidPinA LOW i.e. switch off the solenoid
}
else if (valA <= 0) // if the sensor value is less than or equal to 0 i.e. the sensor has been pressed
{
digitalWrite(solenoidPinA, HIGH); // solenoidPinA on, switch solenoid on
delay (100);
digitalWrite(solenoidPinA, LOW); // switches solenoid off to stop it burning out
}
}
Wood Pecker Project
From experimenting with this circuit it would be nice to create a project using the trees outside the civic centre, solenoids mounted in the trees could be triggered by PIR or pressure senstive pads. Zigbee radio shields from Libelium could be used to radio to the solenoids in the trees which would create a woodpecker effect and drawing attention from passersby.




I used Tom Igoe’s processing sketch to program the zigbee radios:
/*
XBee terminal
Language: processing
This program is a basic serial terminal program.
It replaces newline characters from the keyboard
with return characters. It’s designed for use with
Linux, Unix, and OS X and XBee radios, because the
XBees don’t send newline characters back.
*/
import processing.serial.*;
Serial myPort; // the serial port you’re using
String portnum; // name of the serial port
String outString = “”; // the string being sent out the serial port
String inString = “”; // the string coming in from the serial port
int receivedLines = 0; // how many lines have been received
int bufferedLines = 10; // number of incoming lines to keep
void setup() {
size(400, 300); // window size
// create a font with the second font available to the system:
PFont myFont = createFont(PFont.list()[40], 14);
textFont(myFont);
// list all the serial ports:
println(Serial.list());
// based on the list of serial ports printed from the
//previous command, change the 0 to your port’s number:
portnum = Serial.list()[0];
// initialize the serial port:
myPort = new Serial(this, portnum, 9600);
}
void draw() {
// clear the screen:
background(0);
// print the name of the serial port:
text(“Serial port: ” + portnum, 10, 20);
// Print out what you get:
text(“typed: ” + outString, 10, 40);
text(“received:\n” + inString, 10, 80);
}
// This method responds to key presses when the
// program window is active:
void keyPressed() {
switch (key) {
// in OSX, if the user types return,
// a linefeed is returned. But to
// communicate with the XBee, you want a carriage return:
case ‘\n’:
myPort.write(outString + “\r”);
outString = “”;
break;
case 8: // backspace
// delete the last character in the string:
outString = outString.substring(0, outString.length() -1);
break;
case ‘+’: // we have to send the + signs even without a return:
myPort.write(key);
// add the key to the end of the string:
outString += key;
break;
case 65535: // If the user types the shift key, don’t type anything:
break;
// any other key typed, add it to outString:
default:
// add the key to the end of the string:
outString += key;
break;
}
}
// this method runs when bytes show up in the serial port:
void serialEvent(Serial myPort) {
// read the next byte from the serial port:
int inByte = myPort.read();
// add it to inString:
inString += char(inByte);
if (inByte == ‘\r’) {
// if the byte is a carriage return, print
// a newline and carriage return:
inString += ‘\n’;
// count the number of newlines:
receivedLines++;
// if there are more than 10 lines, delete the first one:
if (receivedLines > bufferedLines) {
deleteFirstLine();
}
}
}
// deletes the top line of inString so that it all fits on the screen:
void deleteFirstLine() {
// find the first newline:
int firstChar = inString.indexOf(‘\n’);
// delete it:
inString= inString.substring(firstChar+1);
}
Xbee Radio Addresses
I used the following addresses for each Xbee radio:
Xbee 1: ATMY 1234 ATDL5678 ATID1111 ATDH0
Xbee 2: ATMY5678 ATDL1234 ATID1111 ATDH0
To test the link up i used the code by Tom Igoe from his Making Things Talk book – turning a potentiometer on one Arduino makes an led brighten or dim on the other arduino and vice versa – the information being transmitted by the Xbee Shields. Here is the code used to test the link up:
Xbee Duplex Code:
/*
XBee Analog Duplex sender
Language: Wiring/Arduino
This sketch configures an XBee radio via the serial port,
sends the value of an analog sensor out, and listens for input
from the radio, using it to set the value of a PWM output.
Thanks to Robert Faludi for the critique and improvements.
*/
#define sensorPin 0 // input sensor
//#define txLed 2 // LED to indicate outgoing data
//#define rxLed 3 // LED to indicate incoming data
#define analogLed 9 // LED that changes brightness with incoming value
#define threshold 10 // how much change you need to see on
// the sensor before sending
int lastSensorReading = 0; // previous state of the switch
int inByte= -1; // incoming byte from serial RX
char inString[6]; // string for incoming serial data
int stringPos = 0; // string index counter
void setup() {
// configure serial communications:
Serial.begin(9600);
// configure output pins:
//pinMode(txLed, OUTPUT);
//pinMode(rxLed, OUTPUT);
pinMode (analogLed, OUTPUT);
// set XBee’s destination address:
setDestination();
// blink the TX LED indicating that the main program’s about to start:
//blink(3);
}
void setDestination() {
// put the radio in command mode:
Serial.print(“+++”);
// wait for the radio to respond with “OK\r”
char thisByte = 0; // what id the value of OK? is this really reading it?
while (thisByte != ‘\r’) {
if (Serial.available() > 0) {
thisByte = Serial.read();
}
}
// set the destination address, using 16-bit addressing.
// if you’re using two radios, one radio’s destination
// should be the other radio’s MY address, and vice versa:
// ok but what about the ATDL? – should this be the other radios or the same – it would make sense to be the other radios but may be for the one this arduino is attazched to – like
//linking the two up ATDL to ATMY ???? need to check this?
Serial.print(“ATDH0\r”);
Serial.print(“ATDL5678\r”); // should this be 1234 too or is this part of the destination address?
//lets try it!
//Serial.print(“ATDL1234\r”); lets stick with the original code for now…
// set my address using 16-bit addressing:
Serial.print(“ATMY1234\r”);
// set the PAN ID. If you’re working in a place where many people
// are using XBees, you should set your own PAN ID distinct
// from other projects.
Serial.print(“ATID1111\r”);
// put the radio in data mode:
Serial.print(“ATCN\r”);
}
/* Blink the tx LED:
void blink(int howManyTimes) {
for (int i=0; i< howManyTimes; i++) {
digitalWrite(txLed, HIGH);
delay(200);
digitalWrite(txLed, LOW);
delay(200);
}
}*/
void loop() {
// listen for incoming serial data:
if (Serial.available() > 0) {
// turn on the RX LED whenever you’re reading data:
//digitalWrite(rxLed, HIGH);
handleSerial();
}
// else {
// turn off the receive LED when there’s no incoming data:
// digitalWrite(rxLed, LOW);
// }
// listen to the potentiometer:
char sensorValue = readSensor();
// if there’s something to send, send it:
if (sensorValue > 0) {
//light the tx LED to say you’re sending:
// digitalWrite(txLed, HIGH);
Serial.print(sensorValue, DEC );
Serial.print(“\r”);
// turn off the tx LED:
// digitalWrite(txLed, LOW);
}
}
void handleSerial() {
inByte = Serial.read();
// save only ASCII numeric characters (ASCII 0 – 9):
if ((inByte >= ’0′) && (inByte <= ’9′)){
inString[stringPos] = inByte;
stringPos++;
}
// if you get an ASCII carriage return:
if (inByte == ‘\r’) {
// convert the string to a number:
int brightness = atoi(inString);
// set the analog output LED:
analogWrite(analogLed, brightness);
// put zeroes in the array
for (int c = 0; c < stringPos; c++) {
inString = 0;
}
// reset the string pointer:
stringPos = 0;
}
}
char readSensor() {
char message = 0;
// read the sensor:
int sensorReading = analogRead(sensorPin);
// look for a change from the last reading
// that’s greater than the threshold:
if (abs(sensorReading – lastSensorReading) > threshold) {
message = sensorReading/4;
lastSensorReading = sensorReading;
}
return message;
}
MEMORY
Having the ability to remember and replay the triggering of the solenoids will add depth to the project.
To investigate this i have looked at the 8 step tone sequencer on the following site:
http://www.beavisaudio.com/projects/digital/ArduinoPunkConsole/
The code contains arrays which store variables and act as memory.
// Set up the array for each step
int steps[] = {100,120,140,160,180,200,220,240};
A “for loop” is then used to move through the sequence:
void loop()
{
// Main sequence loop
for (int i=0; i<8; i++)
The version i built:
I changed some of the original source code to create an animation on the LCD screen and also had to switch off the spash screen the LCD came programmed with:
Demonstrating the 8 Step Sequencer:











