Assignment: Servo Motor: Actuation Assignment 2
Collaborators:
Using two servo motors, two binder clips and just enough packaging material to keep it off the ground, this little servo-crawler rather awkwardly slides across the table (until he starts to reach the end of the wire). The triangular clips lead to a "two-steps forward, one-step back" approach to movement.
As an extra touch, an iPhone can wirelessly start and stop the movement of the crawler. When a Processing sketch is running in the background, touching a button on the iPhone (using the TouchOSC application) immediately starts the crawler moving. Touching the button again will stop the crawling (though not immediately -- a bug somewhere).
/*
* Servo with iPhone Control
* (modified by npdoty off of original code from TUI class potentiometer controlled servo)
*/
int servoPin = 7; // Control pin for servo motor
int servoPin2 = 8;
int pulseWidth = 2100; // Amount to pulse the servo
int pulseWidth2 = 700;
long lastPulse = 0; // the time in millisecs of the last pulse
int refreshTime = 20; // the time in millisecs needed in between pulses
//beginning and end positions of each servo (they need to move different amounts)
int beginW = 2100;
int endW = 1300;
int beginW2 = 700;
int endW2 = 1800;
//target position of each servo
int targetPulseWidth = endW;
int targetPulseWidth2 = endW2;
//difference between current position and target position
int difference = 0;
int difference2 = 0;
//number of steps to divide up the movement of each 'step'
int numSteps = 10;
int minPulse = 500; // minimum pulse width
boolean move = false; //should the crawler move?
void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pinMode(servoPin2, OUTPUT); // Set servo pin as an output pin
pulseWidth = minPulse; // Set the motor position to the minimum
Serial.begin(9600); // connect to the serial port
Serial.println("servo_serial_better ready");
}
void loop() {
if (Serial.available()) //read input from Processing (the iPhone)
{
char c = Serial.read();
if (c == '1')
{
move = true;
}
else
{
move = false;
}
}
if (move)
{
pulseWidth = pulseWidth + difference;
pulseWidth2 = pulseWidth2 + difference2;
//debug info
Serial.print("servo1: "); Serial.print(pulseWidth); Serial.print(" servo2: "); Serial.println(pulseWidth2);
Serial.print("diff: "); Serial.print(difference); Serial.print(" diff2: "); Serial.println(difference2);
Serial.print("target: "); Serial.print(targetPulseWidth); Serial.print(" target2: "); Serial.println(targetPulseWidth2);
updateServo(); // update servo position
//start back the other way when you've finished
if (pulseWidth <= endW)
{
targetPulseWidth = beginW;
targetPulseWidth2 = beginW2;
difference = (targetPulseWidth - pulseWidth) / numSteps;
difference2 = (targetPulseWidth2 - pulseWidth2) / numSteps;
}
else if (pulseWidth >= beginW)
{
targetPulseWidth = endW;
targetPulseWidth2 = endW2;
difference = (targetPulseWidth - pulseWidth) / numSteps;
difference2 = (targetPulseWidth2 - pulseWidth2) / numSteps;
}
}
}
// called every loop().
void updateServo() {
// pulse the two servos again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse >= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulseWidth); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
digitalWrite(servoPin2, HIGH); // Turn the motor on
delayMicroseconds(pulseWidth2); // Length of the pulse sets the motor position
digitalWrite(servoPin2, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}
/**
* TouchOSC
*
* Example displaying values received from
* the "Simple" layout (Page1 only so far)
* http://hexler.net/touchosc
* modified by npdoty for sending messages over a serial port to an Arduino
*/
import oscP5.*;
import netP5.*;
import processing.serial.*;
// Change this to the portname your Arduino board
String portname = "/dev/tty.usbserial-A7006ysf"; // or "COM5"
Serial port;
String buf="";
int cr = 13; // ASCII return == 13
int lf = 10; // ASCII linefeed == 10
OscP5 oscP5;
float v_fader1 = 0.0f;
float v_fader2 = 0.0f;
float v_fader3 = 0.0f;
float v_fader4 = 0.0f;
float v_fader5 = 0.0f;
float v_toggle1 = 0.0f;
float v_toggle2 = 0.0f;
float v_toggle3 = 0.0f;
float v_toggle4 = 0.0f;
void setup() {
size(320,440);
frameRate(25);
/* start oscP5, listening for incoming messages at port 8000 */
oscP5 = new OscP5(this,8000);
port = new Serial(this, portname, 9600);
}
void oscEvent(OscMessage theOscMessage) {
String addr = theOscMessage.addrPattern();
float val = theOscMessage.get(0).floatValue();
if(addr.equals("/1/fader1")) { v_fader1 = val; }
else if(addr.equals("/1/fader2")) { v_fader2 = val; }
else if(addr.equals("/1/fader3")) { v_fader3 = val; }
else if(addr.equals("/1/fader4")) { v_fader4 = val; }
else if(addr.equals("/1/fader5")) { v_fader5 = val; }
else if(addr.equals("/1/toggle1")) { v_toggle1 = val; }
else if(addr.equals("/1/toggle2")) { v_toggle2 = val; }
else if(addr.equals("/1/toggle3")) { v_toggle3 = val; }
else if(addr.equals("/1/toggle4")) { v_toggle4 = val; }
}
void draw() {
background(0);
// fader5 + toggle 1-4 outlines
fill(0);
stroke(0, 196, 168);
rect(17,21,287,55);
rect(17,369,60,50);
rect(92,369,60,50);
rect(168,369,60,50);
rect(244,369,60,50);
// fader5 + toggle 1-4 fills
fill(0, 196, 168);
rect(17,21,v_fader5*287,55);
if(v_toggle1 == 1.0f)
{
port.write('1'); //turn on crawler
rect(22,374,50,40);
}
else
{
port.write('0'); //turn off crawler
fill(0);
rect(22,374,50,40);
}
if(v_toggle2 == 1.0f) rect(97,374,50,40);
if(v_toggle3 == 1.0f) rect(173,374,50,40);
if(v_toggle4 == 1.0f) rect(249,374,50,40);
// fader 1-4 outlines
fill(0);
stroke(255, 237, 0);
rect(17,95,60,255);
rect(92,95,60,255);
rect(168,95,60,255);
rect(244,95,60,255);
// fader 1-4 fills
fill(255, 237, 0);
rect(17,95 + 255 - v_fader1*255,60,v_fader1*255);
rect(92,95 + 255 - v_fader2*255,60,v_fader2*255);
rect(168,95 + 255 - v_fader3*255,60,v_fader3*255);
rect(244,95 + 255 - v_fader4*255,60,v_fader4*255);
}