Robotic arm, need help with servo movement

Hello!
My Name is Lance and I am new to Arduino.
I am working on an open source 3D printed robotic arm project:

modeled after the uArm:
http://store.ufactory.cc/complete-assembled-acrylic-kit/
Below is the code for some initial testing. I want the servos to move smoothly so the arm doesn't wobble when the high torque servos jerk from on position to the next. I'm looking for smooth natural movement.
Oh and don't assume I know anything about the code, I am a total newbe.

More on the Lite Arm
My goal for this arm is for it to read gcode from pronterface and move to correct x,y,z coordinates. If anyone can suggest how I can go about that I would be very grateful.

// Testing for Lite Arm Project
//     http://www.thingiverse.com/thing:407800
#include <Servo.h>

Servo servobase;         
Servo servoshoulder;         
Servo servoforearm;

void setup() { 
  servobase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoshoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoforearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max
} 

void loop() {            // Loop through motion tests
  home1();     //go to start pos           
  delay(1000); // Wait 1000 milliseconds (1 seconds)
  pos1();
  delay(1000);
  pos2();
  delay(1000);
  pos3();
  delay(1000);
  
}


void home1() {
  servobase.write(90);
  servoshoulder.write(90);
  servoforearm.write(90);
  
}

void pos1() { //pen to paper
  servobase.write(90); 
  servoshoulder.write(42);
  servoforearm.write(120);
  
}

void pos2() { //move forward (draw line)
  servobase.write(90); 
  servoshoulder.write(37.5);
  servoforearm.write(105);
  
}

void pos3() { //move forward (draw line)
  servobase.write(90);
  servoshoulder.write(28.5);
  servoforearm.write(90);
  
}

See: Files, Examples, Servo, Sweep
To see how to step it slower with a for loop.

This is re-kindling my interest:

Must. Finish. Building. My. uArm.

You will get finer control if you use servo.writeMicroseconds()

...R

steinie44:
See: Files, Examples, Servo, Sweep
To see how to step it slower with a for loop.

How do you sweep 3 servos at the same time?

Robin2:
You will get finer control if you use servo.writeMicroseconds()

...R

Yes I know, I kept it simple here
Also made a conversion calculator in google sheets that pretty cool

enter degree_____ ="enter degree"(1000/180)+1000 (<this mill give you microseconds)
Enter Microseconds______ = ("enter microseconds"-1000)
(180/1000) (<this will give you the angle)

JimboZA:
This is re-kindling my interest:

Must. Finish. Building. My. uArm.

Where is the "like" button?

How do you sweep 3 servos at the same time?

Blink without delay. This example blinks 2 LEDs at different rates.

// Blink without delay State Machine JDS
// Constants
const int Green = 7;
const int Red = 8;

//Variables
byte GreenState = 0;
byte RedState = 0;
long PrevMillisGreen = 0;
long PrevMillisRed = 0;
long GreenInterval = 900;
long RedInterval = 200;
unsigned long CurrentMillis = millis();

void setup() {
  // put your setup code here, to run once:
  pinMode(Green, OUTPUT);
  pinMode(Red, OUTPUT);
  Serial.begin(9600);
  Serial.print(__FILE__ " " __DATE__ " " __TIME__);
  Serial.print("  IDE "); Serial.println(ARDUINO);
}

void loop() {
  // put your main code here, to run repeatedly:
  CurrentMillis = millis();
  if (CurrentMillis - PrevMillisGreen > GreenInterval)
  { GreenState = !GreenState;
    digitalWrite(Green, GreenState);
    PrevMillisGreen = CurrentMillis;
  }
  if (CurrentMillis - PrevMillisRed > RedInterval)
  { RedState = !RedState;
    digitalWrite(Red, RedState);
    PrevMillisRed = CurrentMillis;
  }
}

steinie44:

How do you sweep 3 servos at the same time?

Blink without delay. This example blinks 2 LEDs at different rates.

// Blink without delay State Machine JDS

// Constants
const int Green = 7;
const int Red = 8;

//Variables
byte GreenState = 0;
byte RedState = 0;
long PrevMillisGreen = 0;
long PrevMillisRed = 0;
long GreenInterval = 900;
long RedInterval = 200;
unsigned long CurrentMillis = millis();

void setup() {
  // put your setup code here, to run once:
  pinMode(Green, OUTPUT);
  pinMode(Red, OUTPUT);
  Serial.begin(9600);
  Serial.print(FILE " " DATE " " TIME);
  Serial.print("  IDE "); Serial.println(ARDUINO);
}

void loop() {
  // put your main code here, to run repeatedly:
  CurrentMillis = millis();
  if (CurrentMillis - PrevMillisGreen > GreenInterval)
  { GreenState = !GreenState;
    digitalWrite(Green, GreenState);
    PrevMillisGreen = CurrentMillis;
  }
  if (CurrentMillis - PrevMillisRed > RedInterval)
  { RedState = !RedState;
    digitalWrite(Red, RedState);
    PrevMillisRed = CurrentMillis;
  }
}

I think I've lost you, or better yet, I'm lost

Where would I place the other 2 servos in the code to execute a synchronized movement?

#include <Servo.h> 
 
Servo servobase;         
Servo servoshoulder;         
Servo servoforearm;
 
int pos = 0;    // variable to store the servo position 
 
void setup() 
{ 
  servobase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoshoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoforearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max 
} 
 
 
void loop() 
{ 
  for(pos = 90; pos < 37.5; pos += 1)  // goes from 90 degrees to 37.5 degrees 
  {                                  // in steps of 1 degree 
    servoshoulder.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 37.5; pos>=1; pos-=1)     // goes from 37.5 degrees to 90 degrees 
  {                                
    servoshoulder.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
}

The below link has info on a library to control servo movement speed.

http://arduino.cc/forum/index.php/topic,61586.30.html

Armatec:
Where would I place the other 2 servos in the code to execute a synchronized movement?

If you want all 3 servos to move at the same time you need code like this

servoBase.write(servoBasePos);
servoShoulder.write(servoShoulderPos);
servoForearm.write(servoForearmPos);

And in each case servoXPos is just a small bit further than the previous position of that servo.

I would have code something like this

// define global variables

void setup() {
   // usual stuff
}

void loop() {
   updateLimbPositions();
   moveLimbs();
}

void updateLimbPositions() {
   // this is just simple demo stuff
   servoBasePos += 50; // microsecs 
   servoShoulderPos += 80;
   servoForearmPos += 20;
   if (servoBasePos > 1900) {
       servoBasePos = 1900;
   }
   if (servoShoulderPos > 1900) {
       servoShoulderPos = 1900;
   }
   if (servoForearmPos > 1900) {
       servoForearmPos = 1900;
   }
}

void moveLimbs() {
   servoBase.writeMicroseconds(servoBasePos);
   servoShoulder.writeMicroseconds(servoShoulderPos);
   servoForearm.writeMicroseconds(servoForearmPos);
}

...R

Like I said total newbe

// "define global variables"
#include <Servo.h> 
 
Servo servoBase;         
Servo servoShoulder;     //I assume that I add this the same way    
Servo servoForearm;
 
int servoBasePos = 0;
int servoShoulderPos = 1;
int servoForearmPos = 2;
//int pos = 0;    // variable to store the servo position 
void setup() 
{ 
  servoBase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoShoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoForearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max 
} 

void loop() {
   updateLimbPositions();
   moveLimbs();
   
}

void updateLimbPositions() {
   // "this is just simple demo stuff"
   servoBasePos += 5000; // microsecs 
   servoShoulderPos += 5000; // ??? How should this be written)
   servoForearmPos += 5000; //
   if (servoBasePos > 1500) {
       servoBasePos = 1500;
   }
   if (servoShoulderPos > 1500) {
       servoShoulderPos = 1233;
   }
   if (servoForearmPos > 1500) {
       servoForearmPos = 1666;
   }
}

void moveLimbs() {
   servoBase.writeMicroseconds(servoBasePos);
   servoShoulder.writeMicroseconds(servoShoulderPos);
   servoForearm.writeMicroseconds(servoForearmPos);
}

When I run this it goes directly to the position and does not move

What I want is to go from "home position"
90(degrees). or 1500(microseconds) Base
1500 Shoulder
1500 Forearm

to "position 1"
1500 Base
1233 Shoulder
1666 Forearm

then to "position 2"
1500 Base
1158 Shoulder
1500 Forearm

moving in steps on 1 degree same as the stock sweep code delay.

I really appreciate the help!
Lance-

Armatec:
I want the servos to move smoothly so the arm doesn't wobble when the high torque servos jerk from on position to the next. I'm looking for smooth natural movement.

That's a nice looking robot arm, btw.

Something you'll probably want to do is a "ramp-up...ramp-down" on the speed of the servos. So - each time thru the loop as you increase the servo speed, increase the "distance" between the amounts you set, until you reach a fixed upper bound.

The below is rough pseudo-code - but it should illustrate the idea I am meaning:

from = 10; // start position of servo
to = 120; // end position of servo

min = 1; // minimum acceleration
max = 10; // maximum acceleration

rdpos = 0; // ramp down position

pos = from; // start the servo at this position
ai = 1; // acceleration incrementor starting value
ac = 1; // acceleration constant

Loop:
      servo.write(pos);

      if pos >= to then exit loop; // reached the end of movement

      pos = pos + ai; // accelerate the positioning of the servo

      ai = ai + ac; // increment the acceleration incrementor by the acceleration constant (see note below)

      if ai > max then 
           ai = max; // bounds check for max acceleration
           rdpos = to - (pos - from); // position at which to start ramping down

      if ai < min then ai = min; // bounds check for min acceleration

      if pos >= rdpos then 
           ai = -ai; // invert acceleration to slow down servo until done
           ac = -ac;

Ok - the above code is -completely- untested, and it also only allows for positive directional movement of the servo (that is, from a position smaller relative to the end position) - it will likely need to be debugged and then generalized to allow for movement in the opposite direction.

Note: You might want to only increment the incrementor every "n" times (where n is some integer) thru the loop, in order to make the ramp up and down less abrupt. Alternatively, one could imagine where most of these values are floats of some sort, and only when the servo.write() is performed do you cast the value to an integer.

However you perform the ramp-up/ramp-down for the acceleration curve - the point is to do something like this; ideally, doing so will make the movements smoother and more fluid, and allow the mass being moved to come up naturally to speed, instead of forcing it to move at full speed (which results in the jerkiness you have experienced).

Armatec:
When I run this it goes directly to the position and does not move

Why did you modify my code?

...R

Robin2:

Armatec:
When I run this it goes directly to the position and does not move

Why did you modify my code?

...R

It has to be completed to some degree correct?
Is this what it should look like with "all the usual stuff"?

// "define global variables"
#include <Servo.h> 
 
Servo servoBase;         
Servo servoShoulder;     //I assume that I add this the same way    
Servo servoForearm;
 
int servoBasePos = 0;
int servoShoulderPos = 1;// variable to store the servo position 
int servoForearmPos = 2;//if i dont add the above i get thee error below
//sketch_aug23a:40: error: 'servoBasePos' was not declared in this scope
//sketch_aug23a:41: error: 'servoShoulderPos' was not declared in this scope
//sketch_aug23a:42: error: 'servoForearmPos' was not declared in this scope
void setup() 
{ 
  servoBase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoShoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoForearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max 
} 


void loop() {
   updateLimbPositions();
   moveLimbs();
}

void updateLimbPositions() {
   // this is just simple demo stuff
   servoBasePos += 50; // microsecs 
   servoShoulderPos += 80;
   servoForearmPos += 20;
   if (servoBasePos > 1900) {
       servoBasePos = 1900;
   }
   if (servoShoulderPos > 1900) {
       servoShoulderPos = 1900;
   }
   if (servoForearmPos > 1900) {
       servoForearmPos = 1900;
   }
}

void moveLimbs() {
   servoBase.writeMicroseconds(servoBasePos);
   servoShoulder.writeMicroseconds(servoShoulderPos);
   servoForearm.writeMicroseconds(servoForearmPos);
}

cr0sh:
That's a nice looking robot arm, btw.

Thank you!
I am checking out your suggestions I will be asking questions soon.

I can just post video of your code in my machine:)

Robin2's code (I think it's what he meant)

// "define global variables"
#include <Servo.h> 
 
Servo servoBase;         
Servo servoShoulder;     //I assume that I add this the same way    
Servo servoForearm;
 
int servoBasePos = 0;
int servoShoulderPos = 1;// variable to store the servo position 
int servoForearmPos = 2;//if i dont add the above i get thee error below
//sketch_aug23a:40: error: 'servoBasePos' was not declared in this scope
//sketch_aug23a:41: error: 'servoShoulderPos' was not declared in this scope
//sketch_aug23a:42: error: 'servoForearmPos' was not declared in this scope
void setup() 
{ 
  servoBase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoShoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoForearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max 
} 


void loop() {
   updateLimbPositions();
   moveLimbs();
}

void updateLimbPositions() {
   // this is just simple demo stuff
   servoBasePos += 50; // microsecs 
   servoShoulderPos += 80;
   servoForearmPos += 20;
   if (servoBasePos > 1900) {
       servoBasePos = 1900;
   }
   if (servoShoulderPos > 1900) {
       servoShoulderPos = 1900;
   }
   if (servoForearmPos > 1900) {
       servoForearmPos = 1900;
   }
}

void moveLimbs() {
   servoBase.writeMicroseconds(servoBasePos);
   servoShoulder.writeMicroseconds(servoShoulderPos);
   servoForearm.writeMicroseconds(servoForearmPos);
}

My original code from the top of page 1

// Testing for Lite Arm Project
//     http://www.thingiverse.com/thing:407800
#include <Servo.h>

Servo servobase;         
Servo servoshoulder;         
Servo servoforearm;

void setup() { 
  servobase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoshoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoforearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max
} 

void loop() {            // Loop through motion tests
  home1();     //go to start pos           
  delay(1000); // Wait 1000 milliseconds (1 seconds)
  pos1();
  delay(1000);
  pos2();
  delay(1000);
  pos3();
  delay(1000);
  
}


void home1() {
  servobase.write(90);
  servoshoulder.write(90);
  servoforearm.write(90);
  
}

void pos1() { //pen to paper
  servobase.write(90); 
  servoshoulder.write(42);
  servoforearm.write(120);
  
}

void pos2() { //move forward (draw line)
  servobase.write(90); 
  servoshoulder.write(37.5);
  servoforearm.write(105);
  
}

void pos3() { //move forward (draw line)
  servobase.write(90);
  servoshoulder.write(28.5);
  servoforearm.write(90);
  
}

Interesting project. Making code that controls servo movement speed would make for some interesting robotic arm and camera pan/tilt setups. I've tinkered with an arduino controlled ssc-32 servo controller which has speed control and the results were interesting. Basically a web page GUI to control the servo positioning.

edit: below are some web page GUIs I made for controlling the servos

zoomkat:
Interesting project. Making code that controls servo movement speed would make for some interesting robotic arm and camera pan/tilt setups. I've tinkered with an arduino controlled ssc-32 servo controller which has speed control and the results were interesting. Basically a web page GUI to control the servo positioning.

That's pretty cool.
I looked at the VaroSpeed link you posted and have not figured it out yet. I searched far and wide for a solution on the web and this forum before I posted anything, then I decided maybe it's time to make another post on this subject and find a definitive solution for everyone else with this issue.

I don't understand the purpose of the two videos. It looks like my code doesn't work. Have you examined it to see why? My earlier comment was about the huge increase in the increments.

Yes, you did correctly add the definitons for the variables - but they shouldn't start at 1. They should start at the minimum servo positions of about 1000 - I assumed you would figure that out from how they are used.

EDIT to add ...
I've now tried my code with one servo and the problem was immediately apparent - I had forgotten to include a delay to give the servo time to move so they all go to their end point so quickly that there only seems to be one move.

You need to add (say) delay(50); as the last thing in loop(). And you shouldn't use delay() in your real code - just for this demo.

Try this version

// "define global variables"
#include <Servo.h> 
 
Servo servoBase;         
Servo servoShoulder;     //I assume that I add this the same way    
Servo servoForearm;
 
int servoBasePos = 1000;
int servoShoulderPos = 1000;// variable to store the servo position 
int servoForearmPos = 1000;//if i dont add the above i get thee error below

void setup() 
{ 
  servoBase.attach(9, 1000, 2000);  // Set servo to digital pin 9, min, max
  servoShoulder.attach(10, 1000, 2000);  // Set servo to digital pin 10, min, max
  servoForearm.attach(11, 1000, 2000); // Set servo to digital pin 11, min, max 
  
  moveLimbs(); // to the initial position
  
  delay(1000);  // so we can see the initial position
} 


void loop() {
   updateLimbPositions();
   moveLimbs();
   delay(50);
}

void updateLimbPositions() {
   // this is just simple demo stuff
   servoBasePos += 25; // microsecs 
   servoShoulderPos += 15;
   servoForearmPos += 10;
   if (servoBasePos > 1900) {
       servoBasePos = 1900;
   }
   if (servoShoulderPos > 1900) {
       servoShoulderPos = 1900;
   }
   if (servoForearmPos > 1900) {
       servoForearmPos = 1900;
   }
}

void moveLimbs() {
   servoBase.writeMicroseconds(servoBasePos);
   servoShoulder.writeMicroseconds(servoShoulderPos);
   servoForearm.writeMicroseconds(servoForearmPos);
}

I note that you have set min and max limits for all of your servos. If these numbers suit your actual servos that is fine. The servo I used for testing seems to work between 400 and 2000 usecs.

...R

You need to add (say) delay(50); as the last thing in loop(). And you shouldn't use delay() in your real code - just for this demo.

New code should be based on using Millis and not delay. Maybe a little more complex, but probably better control.