Foot Jockey

Summary
When I am busy doing work sitting at my desk I like to play some good music in my ear to help me zone out. The problem is that I often start feeling the urge to dance but I obviously can’t since I’m in the middle of typing and mouse clicking my projects away. So the only part of me that’s left to dance is pretty much just my feet. That’s what sparked the concept for Foot Jockey.
Basically it’s just two pedals setup under your desk that let you tap your feet to the muscial beat. On your desk are 2 different characters that dance back and forth to the control of your two feet. Since the pedals have an analog range of values you have a certain degree of control over how much the two characters dance. The 2 characters are attached through magnets so they can easily be interchangable and possibly controlled through a thin surface to hide the servo motors that move them. In addition to the characters dancing back and forth I also created a simple visualization that animates based on the pedals movements. I imagined the 2 figures dancing in front of the screen with the visuals functioning as an imaginary nightclub backdrop for them to enjoy dancing in! The visualization is based on a simple recursion algorithm using rotation.
Since you can’t go dancing at a club while you’re at work why not create a club on your desk!

Parts Used
– Arduino microcontroller module
– 2 servo motors to control figures
– 2 funny looking magnetized figures
– Pedals (gas & brakes), essentially 2 potentiometers
– Processing handles all the visuals and interfacing with the serial information

Images
FootJockey Setup
FootJockey setup
Mr.Spliff and Monkey Clubbing
Mr.Spliff and Monkey out clubbing on my desk!
The Pedals
The pedals to control all the action
Attached by Magnet
Attached by magnet
Arduino Board
Arduino module with microcontroller

Arduino Code
////// Foot Jockey ////////
int gas = 0; // first analog sensor
int brake = 1; // second analog sensor
int inByte = 0; // incoming serial byte

int gasservoPin = 2; // Control pin for gas servo motor
int brakeservoPin = 3; // Control pin for brake servo motor
int minPulse = 500; // Minimum servo position
int maxPulse = 2500; // Maximum servo position
int pulseG = 0;
int pulseB = 0;

int lastPulseG = 0;
int lastPulseB = 0;
int refreshTimeG = 20;
int refreshTimeB = 20;

int gasValue = 0;
int brakeValue = 0;

void setup()
{
pinMode(gasservoPin, OUTPUT);
pinMode(brakeservoPin, OUTPUT);
pulseG = minPulse;
pulseB = minPulse;
Serial.begin(9600);
}

void loop()
{
gasValue = analogRead(gas);
brakeValue = analogRead(brake);
pulseG = (gasValue – 660) * 7.5; // adjusting the potentiometer range to fit the servo’s range
pulseB = (brakeValue – 350) * 3.7; // adjusting the potentiometer range to fit the servo’s range

if (millis() – lastPulseG >= refreshTimeG) {
digitalWrite(gasservoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseG); // Length of the pulse sets the motor position
digitalWrite(gasservoPin, LOW); // Turn the motor off
lastPulseG = millis(); // save the time of the last pulse
//Serial.println(gasValue, DEC);
}
if (millis() – lastPulseB >= refreshTimeB) {
digitalWrite(brakeservoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseB); // Length of the pulse sets the motor position
digitalWrite(brakeservoPin, LOW); // Turn the motor off
lastPulseB = millis(); // save the time of the last pulse
//Serial.print(brakeValue, DEC);
}

int gNew = ((gasValue/4) * 2) – 180;
int bNew = (brakeValue/2) – 200;
delay(10);

if (Serial.available() > 0) {
inByte = Serial.read();
Serial.print(bNew, BYTE); // Send the byte
Serial.print(gNew, BYTE); // Send the byte
}
}

Processing Code
/////////// FootJocky Visualization ///////////
// Based on code from Daniel Shiffman and Tom Igoe
import processing.serial.*;

float theta;
Serial port;
int[] serialInArray = new int[2]; // Where we’ll put what we receive
int serialCount = 0;
int gasMove;
int brakeMove;

float c;
boolean firstContact = false;

void setup() {
size(640,480);
smooth();
println(Serial.list());
port = new Serial(this, Serial.list()[1], 9600);
port.write(65);
}

void draw() {
background(0);
framerate(30);
stroke(255);
if (firstContact == false) {
delay(300);
port.write(65);
}

// Let’s pick an angle 0 to 90 degrees based on the mouse position
float a = (gasMove / (float) width) * 360f;
// Convert it to radians
theta = radians(a);
translate(width/2,height);
translate(0,-240);
// Start the recursive branching!
branch(30);

}

void serialEvent(Serial port) {
// if this is the first byte received,
// take note of that fact:
if (firstContact == false) {
firstContact = true;
}
// Add the latest byte from the serial port to array:
serialInArray[serialCount] = port.read();
serialCount++;

// If we have 3 bytes:
if (serialCount > 1 ) {
gasMove = serialInArray[0];
brakeMove = serialInArray[1];

// print the values (for debugging purposes only):
println(gasMove + “\t” + brakeMove);
// Send a capital A to request new sensor readings:
port.write(65);
// Reset serialCount:
serialCount = 0;
}
}

void branch(float h) {
h *= 0.66f;
float r = random(150,240);
c = brakeMove*2;
fill(r,70,c,20);
noStroke();

// All recursive functions must have an exit condition!!!!
if (h > 2) {
pushMatrix(); // Save the current state of transformation (i.e. where are we now)
rotate(theta); // Rotate by theta
rect(h,h,80*h*brakeMove,80*h*brakeMove);
translate(0,-h);
branch(h);
popMatrix();

pushMatrix();
rotate(-theta);
translate(0,-h);
branch(h);
popMatrix();
}
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: