Simple project, willing to pay $$$ for basic coding - 4 Servos + Ping)))

Nope that was someone else. Similar project though--- I'm using Servo's rather than stepper motors, and mine has nothing to do with optics etc.

do you actually mean Servos, generally these are thought of as the thing that is used in RC projects and their speed is not normally controlled but their position is with PWM and is maintained using an internal closed loop feedback in the servo itself.

I can help, what is your budget.

Cheers Pete.

Yes I do indeed mean servos. Lame old cheap 180 degree servos. I know they are not the most precise, or in any way the most reliable motors out there - at the moment I'm really just out to build a proof of concept but I can't adjust the code accordingly.

I'm not entirely sure how but I am definitely able to adjust the speed of the servos...Maybe it has to do with altering the frequency of the internal loop?

It would probably make more sense if I showed you the code I already have:

1st Tab:

// Controlling a servo position using a potentiometer (variable resistor) 
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 

#include <Servo.h> 

#define roll  0
#define pitch 1
#define yaw   2
#define Boo   3

#define UP    1
#define DOWN  0
#define HOLD  2

Servo servo[4];  // create servo object to control a servo 

int direct[4] = {0,0,0,0};
int steps[4];
int pos[4] = {0,0,0,0};
int target[4];
int hold[4];
int maxCount[4];
int minCount[4];

long servoMin[4];
long servoMax[4];
long servoPauseMin[4];
long servoPauseMax[4];
long servoSpeed[4];

long previousMillis[4] = {0,0,0,0};        // will store last time LED was updated
unsigned long currentMillis[4];
long interval = 4000;           // interval at which to blink (milliseconds)

2nd Tab - Drive:

void drive(int servos, int minTarget, int maxTarget,int minHold, int maxHold, int speeds) { 
  
  if(direct[servos] == UP){
     if (pos[servos] < maxTarget){
        pos[servos] = pos[servos] + speeds ;
     }
     else if (pos[servos] >= maxTarget){ 
       
      maxCount[servos]++;
        if(maxCount[servos] >= maxHold){
           maxCount[servos] = 0;
           direct[servos] = DOWN;
        }
      }
  }
  
  if(direct[servos] == DOWN){
      if(pos[servos] > minTarget){
            pos[servos] = pos[servos] - speeds ;
          }
      else if (pos[servos] <= minTarget){
        
         minCount[servos]++;
        if(minCount[servos] >= minHold){
           minCount[servos] = 0;
           direct[servos] = UP;
           Serial.print("........................................................" );
        }
      }
  }
  
  /*
  Serial.print("\t servo" );                       
  Serial.print(servos); 
  Serial.print(" = "); 
  Serial.print(pos[servos]); 
  Serial.print(" "); 
  Serial.print(minTarget); 
  Serial.print(" "); 
  Serial.print(maxTarget); 
   Serial.print("\t direction = " );                       
  Serial.println(direct[servos]); 
  //if(servos == 2) Serial.println(); 
  */
  
  servo[servos].write(pos[servos]);
   delay(15);
}

3rd Tab - Loop:

void loop() {    //(servo, its minimum target, maximum target, pause at the min position, pause at max position, its speed)
    
       // servo[pitch].write(80);    //pitch range = 20 - 80
       //servo[roll].write(120);    //roll range = 100 - 130
    
      
        servoMin[roll] = 0;
        servoMax[roll]= 180;
        servoPauseMin[roll] = 0;
        servoPauseMax[roll] = 0;
        servoSpeed[roll]= 1;
       
        servoMin[pitch]= 0;
        servoMax[pitch] = 180;
        servoPauseMin[pitch]= 0;
        servoPauseMax[pitch]= 0;
        servoSpeed[pitch]= 2; 
        
        servoMin[yaw]= 0;
        servoMax[yaw] = 180;
        servoPauseMin[yaw]= 0;
        servoPauseMax[yaw]= 0;
        servoSpeed[yaw]= 2;
        
        servoMin[Boo]= 0;
        servoMax[Boo] = 180 ;
        servoPauseMin[Boo]= 0;
        servoPauseMax[Boo]= 0;
        servoSpeed[Boo]=  1;
 /*
      
        servoMin[roll] = random(0, 100);
        servoMax[roll]= random(servoMin[roll], 180);
        servoPauseMin[roll] = random(0, 2000);
        servoPauseMax[roll] = random(0, 2000);
        servoSpeed[roll]= random(0, 5);
       
        servoMin[pitch]= random(0, 100);
        servoMax[pitch] = random(servoMin[pitch], 180);
        servoPauseMin[pitch]= random(0, 2000);
        servoPauseMax[pitch]= random(0, 2000);
        servoSpeed[pitch]= random(0, 5);  
        
        servoMin[yaw]= random(0, 100);
        servoMax[yaw] = random(servoMin[yaw], 180);
        servoPauseMin[yaw]= random(0, 1000);
        servoPauseMax[yaw]= random(0, 1000);
        servoSpeed[yaw]= random(0, 5);
 */
        
      drive(roll,servoMin[roll],servoMax[roll],servoPauseMin[roll], servoPauseMax[roll],servoSpeed[roll]); 
      drive(pitch, servoMin[pitch],servoMax[pitch],servoPauseMin[pitch],servoPauseMax[pitch],servoSpeed[pitch]);
      drive(yaw,servoMin[yaw],servoMax[yaw],servoPauseMin[yaw],servoPauseMax[yaw],servoSpeed[yaw]);
      drive(Boo,servoMin[Boo],servoMax[Boo],servoPauseMin[Boo],servoPauseMax[Boo],servoSpeed[Boo]);
      
      
      
     //drive(roll,180,0,1000,1000,1); 
    // drive(pitch,180,0,1000,1000,4);
     //drive(yaw,180,0,1000,1000,2); 
       
}

4th Tab - Setup:

void setup() { 
  
  
   randomSeed(analogRead(0));
   
   Serial.begin(9600);
   
  servo[roll].attach(2);  // attaches the servo on pin 9 to the servo object 
  servo[pitch].attach(3);  // attaches the servo on pin 9 to the servo object
  servo[yaw].attach(4);  // attaches the servo on pin 9 to the servo object
  servo[Boo].attach(5);  // attaches the servo on pin 9 to the servo object
  
  pos[roll] = 90;
  pos[pitch] = 90;
  pos[yaw] = 90;
  pos[Boo] = 90;
  
}

And as for the budget, I really wouldn't know - I can't really gauge how difficult a task this would be for someone to code.... I also don't know what people usually ask for in these kind of scenarios.... :blush:

Any advice?

OK so it sounds like you have already answered your own question.

If you can vary the speed of the servos by altering a delay in between the setting of the Pulse width that sets the position of the servo just link this delay to the results from your ultrasound sensor.

You can use the map function to map an input range from the sensor to an output range that fits in with how fast/slow you want to move the servo.

Cheers Pete.

Thanks for your reply Pete!

What I need to do makes sense in my mind (mapping a range from the sensor, working out an input range for the speed of the servo, and linking the two together) - the issue is I don't know how to modify the code in order to do that.

Any suggestions would be really helpful....

  • I know I need to define the sensor (aka assign it a name).

  • Link it to pin, and set it as an input pin.

  • Work out the input range of the sensor and map that to an output range for the servo speed.

  • Link the two values somehow in the code.....

How could I modify my code to do those tasks?

Thank you!

Mike

OK so first off what Ultrasound ranger are you using.

have you actually got it wired up to the arduino.

Cheers Pete.

I'm using the Ping ultrasound reader from Parallax. I have hooked it up to the Arduino using the sample code they provided and it works fine (outputting distance values to the serial monitor).

OK so post the code you have to control the speed of the servos and the code for the ultrasonic ranger and i can look at knitting them together for you in the way i described before.

Cheers Pete.

Thank you so much for all your help Pete!

I posted the code I have for controlling the speed of the servos a few posts back. The portion of the code where I physically input a value for speed is in the 3rd tab "loop", where I can change the 'servoSpeed[roll]= 1;' section.

The code I have for the sensor is listed below:

const int pingPin = 11;
unsigned int duration, inches;

void setup() {
  Serial.begin(9600);
}

void loop() {
  pinMode(pingPin, OUTPUT);          // Set pin to OUTPUT
  digitalWrite(pingPin, LOW);        // Ensure pin is low
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);       // Start ranging
  delayMicroseconds(5);              //   with 5 microsecond burst
  digitalWrite(pingPin, LOW);        // End ranging
  pinMode(pingPin, INPUT);           // Set pin to INPUT
  duration = pulseIn(pingPin, HIGH); // Read echo pulse
  inches = duration / 74 / 2;        // Convert to inches
  Serial.println(inches);            // Display result
  delay(200);		             // Short delay
}

I hope thats all you need, let me know if I didn't express myself specifically enough at any stage :wink:

Thanks again,
Mike

Is inches a global variable? If so, how does that relate to roll, pitch, yaw, or Boo?

Which servo's speed is supposed to be controlled by inches, and how?

Inches is indeed a global variable. I would like the speed of all the servo's (roll, pitch, yaw, & boo) to be equally affected by the change in distance (defined in inches).

For example, if I'm 10 inches away from the sensor, I would like the speed of all the servos to be 1 ( servoSpeed[roll]= 1, servoSpeed[yaw]= 1 etc.) If I increase that distance to 20 inches, all the servo's speed would change to 2.

To summarize it:

-All the servos are moving at equal speeds.

-The value for speed is directly proportional to the distance in inches from the sensor.

I hope that answers your question. Thanks for posting!
Mike

-The value for speed is directly proportional to the distance in inches from the sensor.

So, in loop(), change:

        servoSpeed[roll]= 1;
        servoSpeed[pitch]= 2; 
        servoSpeed[yaw]= 2;
        servoSpeed[Boo]=  1;

to:

        servoSpeed[roll]= inches/10;
        servoSpeed[pitch]= 2 * inches/10; 
        servoSpeed[yaw]= 2 * inches/10;
        servoSpeed[Boo]=  inches/10;

PaulS:

        servoSpeed[roll]= inches/10;

servoSpeed[pitch]= 2 * inches/10;
        servoSpeed[yaw]= 2 * inches/10;
        servoSpeed[Boo]=  inches/10;

If they are all to be the same speed then the code needs to be ...

        servoSpeed[roll]= inches/10;
        servoSpeed[pitch]=  inches/10; 
        servoSpeed[yaw]=  inches/10;
        servoSpeed[Boo]=  inches/10;

although it might be quicker to calculate it once and use it several times

        int Speed = inches/10;
        servoSpeed[roll]= Speed;
        servoSpeed[pitch]= Speed; 
        servoSpeed[yaw]= Speed;
        servoSpeed[Boo]=  Speed;

Cheers Pete.

Thank you so much everyone for all your support! Using the code that you guys suggested the servos now communicate with the sensor and it all works beautifully.....except for one small thing.

For some reason the servo's movement is now really jittery, especially when working at higher speeds. I don't know if its an issue with the code (somewhere in the loop prompt), or if its the batteries which cannot provide enough amperage for the servos under heavy loads (the battery pack is 4 AS's).

If anyone has an idea why this might bee, some suggestions to resolve the problem would be highly appreciated.

Thanks a million,

Michael

or if its the batteries which cannot provide enough amperage for the servos under heavy loads (the battery pack is 4 AS's).

Ooh, ooh, I know. It isn't the software.

So four AA's is not a good way to power the servos? Could any one suggest an alternative capable of providing the charge necessary?

PaulS:

or if its the batteries which cannot provide enough amperage for the servos under heavy loads (the battery pack is 4 AS's).

Ooh, ooh, I know. It isn't the software.

Oddly enough it could well be the software :~ If the timing loop that is setting the time between the PWM is too long the servos stop trying to seek, they go into no resistance mode. If the servos are under a small load that causes them to move off the desired point slightly when this happens then they will indeed jitter or oscillate about the desired point.

But then a really big battery might fix it too XD

Cheers Pete.

Could any one suggest an alternative capable of providing the charge necessary?

I'd suggest that you think about where the servo you are using was intended to be used. Most likely, the place you got it from also sells RC cars, trucks, boats, airplanes, and helicopters. You'll notice that none of them use 4AA batteries. They use big, rechargeable batteries.

Why? Because servos need a lot of current, and 4AA batteries just can't provide the needed current. Look at the batteries available from the same vendor you got your servo from, and pick one of them. Matched to your servo's voltage and current requirements, of course.