Skip to content

Instantly share code, notes, and snippets.

@ryangreenberg
Created April 21, 2013 17:56
Show Gist options
  • Save ryangreenberg/5430440 to your computer and use it in GitHub Desktop.
Save ryangreenberg/5430440 to your computer and use it in GitHub Desktop.
Potentiometer video control

This is code used to control the playback speed of a video playing in Quicktime Player. Upload arduino_read_potentiometer.cpp on your Arduino and run processing_control_video.pde in Processing. See video demo at http://www.youtube.com/watch?v=UfDRINiV4Kg

/*
* Potentiometer Passing
* by Ryan Greenberg
* 23 September 2009
*
* This program gets the value of two potentiometers connected to analog inputs
* and writes their values to serial for Processing to receive. These pots
* control video playback speed and volume. A blinking LED matches the
* tempo and volume of the video.
*/
int ledPin = 10; // select the output pin for LED
int spdPin = 2; // select the input pin for the speed pot
int volPin = 3; // select the input pin for the volume pot
int spd = 0; // variable to store the speed value coming from the pot
int vol = 0; // variable to store the volume value coming from the pot
int bpm = 194; // Speed of song in beats per minute, at 100% speed
// Calculate the BPM of a song manually at
// http://www.all8.com/tools/bpm.htm
float beatPeriod; // ms to wait between flashes
float beatMultiplier = 1.0; // number from -1 to 3 to multiply base bpm
long nextBeat; // time of next flash toggle
int beatOn = 0;
int pollPeriod = 1000; // ms to wait between polls
long nextPoll; // time of next poll
void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT
nextPoll = millis() + pollPeriod;
nextBeat = millis() + beatPeriod;
setBeatPeriod();
Serial.begin(9600);
}
void loop() {
// Flash light to the beat
if (millis() >= nextBeat) {
toggleBeat();
}
// Read changes to the beat
if (millis() >= nextPoll) {
pollPot();
}
}
void toggleBeat() {
nextBeat = millis() + beatPeriod;
if (beatOn == 1) {
digitalWrite(ledPin, LOW); // turn the ledPin off
beatOn = 0;
} else {
analogWrite(ledPin, vol / 1024.0 * 255);
// digitalWrite(ledPin, HIGH); // turn the ledPin on
beatOn = 1;
}
}
// An unfortunately named function
void pollPot() {
nextPoll = millis() + pollPeriod; // set time for next reading
spd = analogRead(spdPin); // read the speed
vol = analogRead(volPin); // read the volume
Serial.print("S"); // Send value to Processing
Serial.println(spd);
Serial.print("V");
Serial.println(vol);
beatMultiplier = spd/1023.0 * 4 - 1;
setBeatPeriod();
}
// Calculate the flash period from the bpm frequency
void setBeatPeriod(){
float oldBeatPeriod = beatPeriod;
// Avoid divide by zero error
if (beatMultiplier == 0) {
beatPeriod = 1000000; // Big enough
} else {
beatPeriod = abs((1.0 / (bpm * 2 * beatMultiplier / 60.0) * 1000));
}
nextBeat = nextBeat - oldBeatPeriod + beatPeriod;
}
/*
* Arduino Movie Player
* ----------------------
*
* Receives speed and volume values over the serial port,
* terminated with a carriage return (ascii 13) then newline (10).
*
* This matches what Arduino's " Serial.println(val)" function
* puts out.
*
* Created 25 October 2006
* copyleft 2006 Tod E. Kurt <tod@todbot.com
* http://todbot.com/
*
* Modified 21 September 2009 by Ryan Greenberg
*
*/
import processing.serial.*;
import com.apple.cocoa.foundation.*; // Only works on OS X with the proper libraries installed
//import processing.video.*; // Too slow
// Change this to the portname your Arduino board
String portname = "/dev/tty.usbserial-A7006RZH"; // or "COM5"
Serial port;
String buf="";
int cr = 13; // ASCII return == 13
int lf = 10; // ASCII linefeed == 10
int potVal;
int count = 0;
int col = 255;
float currentPlaySpeed = 1.0;
float currentVolume = 1.0;
//Movie myMovie;
void setup() {
port = new Serial(this, portname, 9600);
setupMovie();
size(100,100);
}
void keyPressed() {
if(key == ' ') {
background(255,0,0); // erase screen
}
}
void setupMovie() {
println("Setting up movie...");
// Play currently open movie in QuickTime Player
String script = "tell application \"QuickTime Player\" to play first document";
executeScript(script);
setVolume(7); // Start with volume turned all the way up
delay(1500); // Wait for movie to start playing
}
void draw() {
// Offer some visual feedback of the current pot value
// Mostly for debugging
background(col);
}
void setMovieSpeed(float s) {
float diff = abs(currentPlaySpeed - s);
println("Current: " + currentPlaySpeed + " Requested: " + s + " Diff: " + diff);
if (diff < .15) {
println("Not changing speed because change is insignificant");
} else {
println("Changing speed to " + s);
String script = "tell application \"QuickTime Player\" to set rate of first document to " + s;
executeScript(script);
currentPlaySpeed = s;
}
}
void setVolume(float v) {
float diff = abs(currentVolume - v);
println("Current: " + currentVolume + " Requested: " + v + " Diff: " + diff);
if (diff < .15) {
println("Not changing volume because change is insignificant");
} else {
String script = "tell application \"Finder\" to set volume " + v;
executeScript(script);
currentVolume = v;
}
}
// called whenever serial data arrives
void serialEvent(Serial p) {
int c = port.read();
// Add string to buffer if not end of line
if (c != lf && c != cr) {
buf += char(c);
}
if (c == lf) {
if (buf.charAt(0) == 'S') {
println("Got value for speed...");
int val = int(buf.substring(1));
float playSpeed = (val / 1023.0 * 4.0)-1;
setMovieSpeed(playSpeed);
col = (int)(val / 1023.0 * 255);
} else if (buf.charAt(0) == 'V') {
println("Got value for volume...");
int val = int(buf.substring(1));
float volume = (val / 1023.0 * 7);
setVolume(volume);
println("Setting volume to " + val);
}
buf = ""; // Clear buffer
}
}
// Used to run AppleScript
// Only works on MacOS computers
void executeScript(String script) {
NSAppleScript myScript = new NSAppleScript(script);
NSMutableDictionary errors = new NSMutableDictionary();
myScript.execute(errors);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment