Pages: [1] 2 3   Go Down
Author Topic: Controlling two servos through serial  (Read 4865 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to control two servos through serial to controll a nerf gun, and its gonna be awesome. im gonna put a camera on it and have it go to my ipod touch, and controll it all with OSCemote on my ipod touch. Does anyone have any good code like this, but for two servos instead of one:
/*
 * NewSerialServo
 * --------------
 * Servo control from the Serial port
 *
 * Alteration of the control interface to use < and > keys
 * to slew the servo horn left and right.  Works best with
 * the Linux/Mac terminal "screen" program.
 *
 * Created 10 December 2007
 * copyleft 2007 Brian D. Wendt
 */

/** Adjust these values for your servo and setup, if necessary **/
int servoPin     =  2;    // control pin for servo motor
int minPulse     =  600;  // minimum servo position
int maxPulse     =  2400; // maximum servo position
int turnRate     =  100;  // servo turn rate increment (larger value, faster rate)
int refreshTime  =  20;   // time (ms) between pulses (50Hz)

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position
int pulseWidth;          // servo pulse width
int moveServo;           // raw user input
long lastPulse   = 0;    // recorded time (ms) of the last pulse


void setup() {
  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
  centerServo = maxPulse - ((maxPulse - minPulse)/2);
  pulseWidth = centerServo;   // Give the servo a starting point (or it floats)
  Serial.begin(9600);
  Serial.println("      Arduino Serial Servo Control");
  Serial.println("Press < or > to move, spacebar to center");
  Serial.println();
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo = Serial.read();

    // ASCII '<' is 44, ASCII '>' is 46 (comma and period, really)
    if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; }
    if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; }
    if (moveServo == 32) { pulseWidth = centerServo; }

    // stop servo pulse at min and max
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
    if (pulseWidth < minPulse) { pulseWidth = minPulse; }

    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    // Serial.print("Pulse Width: ");
    // Serial.print(pulseWidth);
    // Serial.println("us");   // microseconds
  }

  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servoPin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servoPin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25770
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Does anyone have any good code like this, but for two servos instead of one
Have you tried a search?

Code:
// ASCII '<' is 44, ASCII '>' is 46 (comma and period, really)
   if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; }
   if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; }
   if (moveServo == 32) { pulseWidth = centerServo; }
This section and comment just cracks me up.
« Last Edit: May 27, 2009, 01:53:24 pm by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ive searched for a while, and i havent found anything(that worked). Could someone who actualy knows what there doing edit this code and make it for two servos. u should probably assign them to other keys, like up be w, left be a, down be s, and right be d. im gonna put a fire button on it too, so could you make f be an I/O thing. the trigger is just a standard I/O switch, but i dont know how to control it with an arduino.

im a noob, so plz help
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have figured some stuff out and i have some code, but it doesnt work quite rite yet can someone fix it? the left and right(a and d) work, but the up and down(w and s) are kinda funky. it tries to catch up to the other servo, and doesnt listen to the terminal commands i give it. here is my code:
Code:
#include <Servo.h>

Servo servo1;
Servo servo2;

/** Adjust these values for your servo and setup, if necessary **/
int servo1Pin     =  10;    // control pin for servo motor
int servo2Pin     =  11;    // control pin for servo motor
int minPulse     =  900;  // minimum servo position
int maxPulse     =  2100; // maximum servo position
int turnRate     =  100;  // servo turn rate increment (larger value, faster rate)
int refreshTime  =  20;   // time (ms) between pulses (50Hz)

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position
int pulseWidth;          // servo pulse width
int moveServo1;           // raw user input
int moveServo2;           // raw user input
long lastPulse   = 0;    // recorded time (ms) of the last pulse


void setup() {
  pinMode(servo1Pin, OUTPUT);  // Set servo pin as an output pin
  pinMode(servo2Pin, OUTPUT);  // Set servo pin as an output pin
  centerServo = maxPulse - ((maxPulse - minPulse)/2);
  pulseWidth = centerServo;   // Give the servo a starting point (or it floats)
  Serial.begin(9600);
  Serial.println("      Arduino Serial Servo Control");
  Serial.println("Press < or > to move, spacebar to center");
  Serial.println();
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo1 = Serial.read();
    moveServo2 = Serial.read();

    // ASCII 'a' is 44, ASCII 'd' is 46
    if (moveServo1 == 97) { pulseWidth = pulseWidth - turnRate; }
    if (moveServo1 == 100) { pulseWidth = pulseWidth + turnRate; }
    if (moveServo1 == 32) { pulseWidth = centerServo; }
  
    // ASCII 's' is 44, ASCII 'w' is 46
    if (moveServo2 == 115) { pulseWidth = pulseWidth - turnRate; }
    if (moveServo2 == 119) { pulseWidth = pulseWidth + turnRate; }
    if (moveServo2 == 32) { pulseWidth = centerServo; }

    // stop servo pulse at min and max
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
    if (pulseWidth < minPulse) { pulseWidth = minPulse; }

    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    // Serial.print("Pulse Width: ");
    // Serial.print(pulseWidth);
    // Serial.println("us");   // microseconds
  }

  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo1Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servo1Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo2Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servo2Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25770
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it tries to catch up to the other servo, and doesnt listen to the terminal commands i give it. here is my code

How are you powering the servos?
From a separate supply, I hope.

Code:
if (moveServo1 == 97) { pulseWidth = pulseWidth - turnRate; }
Is easier to read if :
Code:
if (moveServo1 == 'a') { pulseWidth = pulseWidth - turnRate; }

Not sure why you've written this section as two separate clauses:
Code:
if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo1Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servo1Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo2Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servo2Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
« Last Edit: May 28, 2009, 01:46:18 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

should i be? im just powering them off the arduino board. whats the voltage on servos anyway, because i dont really have any available power supplies. is it just like 1.5V, so i could just put on a AA?
« Last Edit: May 28, 2009, 01:48:14 am by thenewdoctorwho » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25770
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No, it's more like 5 or 6V (4 x AA).

Code:
 if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo1 = Serial.read();
    moveServo2 = Serial.read();
I wouldn't count on this always working.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what could i replace this with? im not a coder yet, i just combined a couple of code examples that didnt work for various reasons. im still just a noob. my mac hasnt told me that im consuming too much power from the servos, which it does if i do too much. but i could use my arduino power supply and my usb port. would that be ok?
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25770
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

http://arduino.cc/en/Serial/Read

How many times do you calculate "pulseWidth"?
How many times do you use it?  smiley-wink
« Last Edit: May 28, 2009, 02:13:43 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Im not exactly sure what it even is, but i think that is used a lot. i posted all the code, so u can check for urself
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

how do you even recalculate it. can you rewrite the code a bit so that its correct. I'm not good at coding.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, i have made a few revisions. i gave the servos seperate pulseWidths, but servo2 doesnt work at all now. it doesnt try to catch up, but it doesnt move when i tell it to.I cant get the second pulsewidth to change

Code:
#include <Servo.h>

Servo servo1;
Servo servo2;

/** Adjust these values for your servo and setup, if necessary **/
int servo1Pin     =  10;    // control pin for servo motor
int servo2Pin     =  11;    // control pin for servo motor 2
int minPulse     =  900;  // minimum servo position
int maxPulse     =  2100; // maximum servo position
int turnRate     =  100;  // servo turn rate increment (larger value, faster rate)
int refreshTime  =  20;   // time (ms) between pulses (50Hz)

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position
int pulseWidth1;          // servo pulse width
int pulseWidth2;          // servo pulse width
int moveServo1;           // raw user input
int moveServo2;           // raw user input
long lastPulse   = 0;    // recorded time (ms) of the last pulse


void setup() {
  pinMode(servo1Pin, OUTPUT);  // Set servo pin as an output pin
  pinMode(servo2Pin, OUTPUT);  // Set servo pin as an output pin
  centerServo = maxPulse - ((maxPulse - minPulse)/2);
  pulseWidth1, pulseWidth2 = centerServo;   // Give the servo a starting point (or it floats)
  Serial.begin(9600);
  Serial.println("      Arduino Serial Servo Control");
  Serial.println("Press a, s, d, or w to move, spacebar to center");
  Serial.println();
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
            // read the incoming byte:
            moveServo1 = Serial.read();
            moveServo2 = Serial.read();

    // ASCII 'a' is 97, ASCII 'd' is 100
    if (moveServo1 == 97) { pulseWidth1 = pulseWidth1 - turnRate; }
    if (moveServo1 == 100) { pulseWidth1 = pulseWidth1 + turnRate; }
    if (moveServo1 == 32) { pulseWidth1 = centerServo; }
  
    // ASCII 's' is 115, ASCII 'w' is 119
    if (moveServo2 == 115) { pulseWidth2 = pulseWidth2 - turnRate; }
    if (moveServo2 == 119) { pulseWidth2 = pulseWidth2 + turnRate; }
    if (moveServo2 == 32) { pulseWidth2 = centerServo; }

    // stop servo pulse at min and max
    if (pulseWidth1 > maxPulse) { pulseWidth1 = maxPulse; }
    if (pulseWidth1 < minPulse) { pulseWidth1 = minPulse; }
    
      // stop servo pulse at min and max
    if (pulseWidth2 > maxPulse) { pulseWidth2 = maxPulse; }
    if (pulseWidth2 < minPulse) { pulseWidth2 = minPulse; }

    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    Serial.print("Pulse Width: ");
    Serial.print(pulseWidth1, pulseWidth2);
    Serial.println("us");   // microseconds
  }

  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo1Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth1);  // pulse width
    digitalWrite(servo1Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo2Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth2);  // pulse width
    digitalWrite(servo2Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}
the servos also make these noises like there trying to move, and it doesnt sound good. i also set it to print in the pulsewidths on both.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25770
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
 if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servo1Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth1);  // pulse width
    digitalWrite(servo1Pin, LOW);    // stop the pulse

    digitalWrite(servo2Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth2);  // pulse width
    digitalWrite(servo2Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
Might do the trick.
As I said earlier.

Code:
#include <Servo.h>

Servo servo1;
Servo servo2;
Is redundant.

Code:
pulseWidth1, pulseWidth2 = centerServo;
Would be more legible as:
Code:
pulseWidth1 = pulseWidth2 = centerServo;
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have figured out the problem, but i dont know what a solution would be. and thanks AWOL, its exactly what you said.this is it:
Code:
 if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo1 = Serial.read();
    moveServo2 = Serial.read();
and only servo1 works. but if i change it to this:
Code:
if (Serial.available() > 0) {
            // read the incoming byte:
            moveServo1, moveServo2 = Serial.read();
only servo2 works. what do i need to change to make this work?
i also made some more adjustments, just to be sure. i made two of almost everything, for each servo. Here is my current code:
Code:
#include <Servo.h>

Servo servo1;
Servo servo2;

/** Adjust these values for your servo and setup, if necessary **/
int servo1Pin     =  10;    // control pin for servo motor
int minPulse1     =  900;  // minimum servo position
int maxPulse1     =  2100; // maximum servo position
int turnRate1     =  100;  // servo turn rate increment (larger value, faster rate)
int refreshTime1  =  20;   // time (ms) between pulses (50Hz)
int servo2Pin     =  11;    // control pin for servo motor 2
int minPulse2     =  900;  // minimum servo position
int maxPulse2     =  2100; // maximum servo position
int turnRate2     =  100;  // servo turn rate increment (larger value, faster rate)
int refreshTime2  =  20;   // time (ms) between pulses (50Hz)
int centerServo1   =  1500;         // center servo position
int centerServo2   =  1500;         // center servo position

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position
int pulseWidth1;          // servo pulse width
int pulseWidth2;          // servo pulse width
int moveServo1;           // raw user input
int moveServo2;           // raw user input
long lastPulse   = 0;    // recorded time (ms) of the last pulse


void setup() {
  pinMode(servo1Pin, OUTPUT);  // Set servo pin as an output pin
  pinMode(servo2Pin, OUTPUT);  // Set servo pin as an output pin
  centerServo1 = maxPulse1 - ((maxPulse1 - minPulse1)/2);
  centerServo1 = maxPulse2 - ((maxPulse2 - minPulse2)/2);
  pulseWidth1 = centerServo;   // Give the servo a starting point (or it floats)
  pulseWidth2 = centerServo;   // Give the servo a starting point (or it floats)
  Serial.begin(9600);
  Serial.println("      Arduino Serial Servo Control");
  Serial.println("Press a, s, d, or w to move, spacebar to center");
  Serial.println();
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
            // read the incoming byte:
            moveServo1, moveServo2 = Serial.read();

    // ASCII 'a' is 97, ASCII 'd' is 100
    if (moveServo1 == 97) { pulseWidth1 = pulseWidth1 - turnRate1; }
    if (moveServo1 == 100) { pulseWidth1 = pulseWidth1 + turnRate1; }
    if (moveServo1 == 32) { pulseWidth1 = centerServo1; }
  
    // ASCII 's' is 115, ASCII 'w' is 119
    if (moveServo2 == 115) { pulseWidth2 = pulseWidth2 - turnRate2; }
    if (moveServo2 == 119) { pulseWidth2 = pulseWidth2 + turnRate2; }
    if (moveServo2 == 32) { pulseWidth2 = centerServo2; }

    // stop servo pulse at min and max
    if (pulseWidth1 > maxPulse1) { pulseWidth1 = maxPulse1; }
    if (pulseWidth1 < minPulse1) { pulseWidth1 = minPulse1; }
    
      // stop servo pulse at min and max
    if (pulseWidth2 > maxPulse2) { pulseWidth2 = maxPulse2; }
    if (pulseWidth2 < minPulse2) { pulseWidth2 = minPulse2; }

    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    Serial.print("Servo 1: ");
    Serial.print(pulseWidth1);
    Serial.print(" Servo 2: ");
    Serial.print(pulseWidth2);
    Serial.println("us");   // microseconds
  }

  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime1) {
    digitalWrite(servo1Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth1);  // pulse width
    digitalWrite(servo1Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
  if (millis() - lastPulse >= refreshTime2) {
    digitalWrite(servo2Pin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth2);  // pulse width
    digitalWrite(servo2Pin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 290
Posts: 25770
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Please, please, don't use this:
Code:
moveServo1, moveServo2 = Serial.read();

I don't want to write this for you but I'll try to nudge you in the right direction:
Code:
if (Serial.available() > 0) {
Looks at the incoming character buffer, and if any are available, returns how many there are in the buffer.

So what does your code do if "Serial.available" returns just "1"?
The first time you call "Serial.read", you get that character.
The second time you call "Serial.read", you get ... -1.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Pages: [1] 2 3   Go Up
Jump to: