Roving robot

what is the type of servo motor ? Do you have the schema of your circuit ? What is the goal of the capacitor ?

#define LeftWheelPin 6
#define RightWheelPin 5
#define ArmServoPin 4
#define SonarPin 0

#define runningLED 2
#define errorLED 7

short ArmAngle, dAngleMax,dAngleMin, dAngleMaxTemp, dAngleMinTemp;
short ArmAngleRange, ArmAngleTarget;
short LeftSpeed;
short RightSpeed;
short ArmTrim = 0;
int distance, dmax, dmin, dmaxtemp, dmintemp;

unsigned long lastPulseL;
unsigned long lastPulseR;
unsigned long lastPulseA;

int i, k;
unsigned short refreshTime = 15;
unsigned long timeLast, timeLastFast;
unsigned long timeLastSlow;
unsigned int timeStart;

// --------------------------------------------------- LED flashing 
void flashLED(short pin, short times) {
  for (i = 0; i<=times; i++) {
    digitalWrite(pin, HIGH);
    delay(100);
    digitalWrite(pin, LOW);
    delay(500);  
  }
} 

// ---------------------------------------------------- Refreshes all servo pulses
void updateServos() {

  if (millis() - lastPulseL >= refreshTime) {
    digitalWrite(LeftWheelPin, HIGH);
    delayMicroseconds((LeftSpeed+90)*11+500);
    digitalWrite(LeftWheelPin, LOW);
    lastPulseL = millis();
  }

  if (millis() - lastPulseR >= refreshTime) {
    digitalWrite(RightWheelPin, HIGH);
    delayMicroseconds((-RightSpeed+90)*11+500);
    digitalWrite(RightWheelPin, LOW);
    lastPulseR = millis();
  }

  if (millis() - lastPulseA >= refreshTime) {
    digitalWrite(ArmServoPin, HIGH);
    delayMicroseconds((ArmAngle+ArmTrim+90)*11+500);
    digitalWrite(ArmServoPin, LOW);
    lastPulseA = millis();
  }

} // end updateServos

// ----------------------------------------------------- Rover move and turn function
void move(int speed, int turnSpeed) {
  //LeftSpeed = speed - turnSpeed;
  //RightSpeed = speed + turnSpeed;

  if (LeftSpeed < 30 && LeftSpeed < (speed - turnSpeed)) {
    LeftSpeed++;
    //LeftSpeed = ((LeftSpeed*10)+1)/10
  }
  else if (LeftSpeed > -30 && LeftSpeed > (speed - turnSpeed)) {
    LeftSpeed--;
    //LeftSpeed = ((LeftSpeed*10)-1)/10;
  }

  if (RightSpeed < 30 && RightSpeed < (speed + turnSpeed)) {
    RightSpeed++;
  }
  else if (RightSpeed > -30 && RightSpeed > (speed + turnSpeed)) {
    RightSpeed--;
  }

  //if (speed == 0 && turnSpeed == 0) {
  //  LeftSpeed = 0;
  //  RightSpeed = 0;
  //}
}    // End move

// -------------------------------------------------- Update ArmAngle
void armturn() {

  if (ArmAngle < 90 && ArmAngle < ArmAngleTarget) {
    ArmAngle = ArmAngle ++;
  }
  else if (ArmAngle > -90 && ArmAngle > ArmAngleTarget) {
    ArmAngle = ArmAngle --;
  }
}

// ------------------------------------------------- sonar distance function
long ping() {
  long raw;

  raw = analogRead(SonarPin)+analogRead(SonarPin)+analogRead(SonarPin)+analogRead(SonarPin);
  raw = raw/4;
  return raw + raw*123/512;
}


// -------------------------------------------------- Main navigation function 
void roving() {
  int speed, turn;
  randomSeed(millis());
  
  if (dmax > 300 && abs(dAngleMax) < 10) {
    ArmAngleRange = 15;
    speed = 20;
    turn = -dAngleMax;
  }    
  else if (dmax > 60) {
    ArmAngleRange = 60;
    speed = 16;
    turn = -dAngleMax/4;
  }  
  else if (dmax > 30) {
    ArmAngleRange = 70;
    speed = dmax/5 - 6;
    turn = -dAngleMax/24;
  }
  else if (dmax <= 30) {
    ArmAngleRange = 80;
    speed = 0;
    turn = -dAngleMax/20;
    digitalWrite(runningLED, HIGH);
  }
  if ((dmin <= 19)&&(abs(dAngleMin)<60)) {
    ArmAngleRange = 80;
    digitalWrite(errorLED, HIGH);
    speed = -4;
    if (dAngleMin !=0) {
      turn = dAngleMin/20;
    }
    else {
      if (random(0,1)) {
        turn = -2;
      }
      else {
        turn = 2;
      }
    }
  }
  /*
  else {
    move(0,0);
    flashLED(errorLED,5);
  }
  */
  move(speed, turn);
}  


void setup() {
  pinMode(LeftWheelPin, OUTPUT);
  pinMode(RightWheelPin, OUTPUT);
  pinMode(ArmServoPin, OUTPUT);
  pinMode(errorLED, OUTPUT);
  pinMode(runningLED, OUTPUT);
  pinMode(SonarPin, INPUT);
  Serial.begin(9600);

  LeftSpeed = 0;
  RightSpeed = 0;
  ArmAngleRange = 80;
  ArmAngleTarget = 80;
  distance = 50;
  dmaxtemp = 20;
  dmintemp = 1000;

  flashLED(runningLED,5);

  timeStart = millis();

  move(0,0);
}

// -------------------------------------------------- Main Loop
void loop() {

  digitalWrite(errorLED, LOW); 

  if (millis() - timeLast > 100) {
    distance = ping();
    
    
    if (distance < dmintemp) {
      dmintemp = distance;
      dAngleMinTemp = ArmAngle;
    }
    if (distance > dmaxtemp) {
      dmaxtemp = distance;
      dAngleMaxTemp = ArmAngle;
    }
    roving();   
    timeLast = millis();
    updateServos();
  }

  if ((millis() - timeLastSlow > 500) && (abs(ArmAngle) >= abs(ArmAngleTarget))) {
    if (ArmAngleTarget > 0) {    
      ArmAngleTarget = ArmAngleRange*-1;
    }
    else {
      ArmAngleTarget = ArmAngleRange;
    }
    dAngleMax = dAngleMaxTemp;
    dAngleMin = dAngleMinTemp;
    
    dmax = dmaxtemp;
    dmin = dmintemp;
    dmaxtemp = 10;
    dmintemp = 1000;
    
    /*
    Serial.print("Angles: ");
    Serial.print(dAngleMax,DEC);
    Serial.print(", ");
    Serial.print(dAngleMin,DEC);
    Serial.print(" - Distances: ");
    Serial.print(dmax,DEC);
    Serial.print(", ");
    Serial.println(dmin,DEC);
    */
    timeLastSlow = millis();
    updateServos();
  }

  if (millis() - timeLastFast > 4) { 
    armturn();
    timeLastFast = millis();
  }


  //updateServos();
  //Serial.println(distance,DEC); 
  digitalWrite(runningLED, LOW);

  updateServos();
}

This code is more "advanced" than the one used in the video. Basically every time the sonar servo completes a sweep, the angle for the direction with the maximum distance is determined, and the robot tries to turn in that direction. The direction with the minimum distance is also determined, and the rover tries to turn away from that direction.

-Z-

This code is more "advanced" than the one used in the video. Basically every time the sonar servo completes a sweep, the angle for the direction with the maximum distance is determined, and the robot tries to turn in that direction. The direction with the minimum distance is also determined, and the rover tries to turn away from that direction.

-Z-

How do you do to synchronize the servo of your sensor ? After few seconds, the angle of mine is not respected... It starts to go more on the right a little bit and it difficult to calibrate it. After three minutes, it is not anymore in the good direction.

This code is more "advanced" than the one used in the video. Basically every time the sonar servo completes a sweep, the angle for the direction with the maximum distance is determined, and the robot tries to turn in that direction. The direction with the minimum distance is also determined, and the rover tries to turn away from that direction.

-Z-

How do you do to synchronize the servo of your sensor ? After few seconds, the angle of mine is not respected... It starts to go more on the right a little bit and it difficult to calibrate it. After three minutes, it is not anymore in the good direction.

What do you mean? The servo driving the sonar is just a normal servo controlled through PWM, I've never needed to calibrate it. I check the angle of the sonar just by knowing the angle I'm telling the servo to point. The angle is probably not 100% accurate, but the robot only needs a rough idea which direction is clear of stuff.

-Z-

Ok I know why I have a problem with my servo. My servo has a continuous rotation. So it is difficult to know exactly where is the servo after few moments.

The code looks great.
So to build the rover, I will use two continuous servos and one regular servo for the sonic ping. I do not know where the arm fits in. Maybe an updated photo will help.

Q1) The continous servos: Do I need to calibrate them so that they can go forward and backwards? Maybe your code only handles forward.

Answer: Yes, you need to calibrate them for forward and baclword operation

Sorry I've been quite busy lately. The "arm" in the code is just referring to the servo that moves the ultrasonic sensor. And yes, the code will tell the robot to move backwards under certain conditions.

-Z-

Very cool project! I will definitely use some of these ideas for my HummBot project.
My HummBot will start with two IR sensors, but having seen this I will also add a Ultrasonic sensor.
The sensor you used is nice and small and seems pretty accurate.

Thanks, Mega

I know this is an Old topic but this is exactly what im trying to do. I get a "problem uploading to board" error when trying to upload the code from this thread. im using the latrest arduino board and the latest software 0013.

avrdude: stk500_getsync(): not in sync: resp=0x00
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x00

is there any working code to make a robot like this floating around?

Go on this page there is a code source for a robot.

http://www.irit.fr/~Nicolas.Lassabe/robot.php

If you are getting that error, it usually means you have something wrong in the hardware, the computer is having difficulty communicating with the arduino. If the code compiles, the code is not the problem.

hello everyone,

im dealing with a similar project yet i am going to be using 5-6 servos. i know there is an easy program that can control servos on pwm pins nine and ten but how can i control all six. I was wondering if i could buy a motor controller to couple with my arduino, is this possible? What type of motor controller would you suggest? Or, if there is a easier alternative please let me know.

btw I know very little about what i'm doing and researching this is hasn't gotten me much luck.

You can control 12 servo motors with digital pins without motor controller.

On this projets I controle 5 servos :
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1209542023/5#5

You can control 12 servo motors with digital pins without motor controller.

I don't think its practical for an Arduino sketch to drive that many servos in software if it needs to spend much time doing other tasks as well. The problem is that each servo needs to be driven for 1 to 2 milliseconds and all the servos should be updated every 20 milliseconds. That doesn't leave much time to do anything else if lots of servos need servicing

This thread has a library that drives up to 8 servos using a Arduino hardware so that the sketch does not need to spend time pulsing the servos : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230479947

I agree with you. I dont spend time to wait the servos, there is the source code here :
http://www.irit.fr/~Nicolas.Lassabe/controller_robot.pde

It's not so difficult to write your own controller to do that without to have a library.

shenakan, I did look at that code before posting my comment. It handles the refresh nicely but still blocks for the duration of each servo pulse. 8 servos pulsing at 2 milliseconds will only leave 20% of the available processing time to do anything else.

You'r right I don't spend time 20ms to wait but I spend between 1-2ms for pulses.

With 8 servos, this means I spend between 8-16ms for pulses every 20ms. So I still have between 55%-71% to execute my code and not 20% (if my operations are correct). It is not so bad. It was enough to control my robot with sensors.

(1000ms/(20ms+16ms)*20ms=555ms)
(1000ms/(20ms+8ms)*20ms=714ms)

with 8 servos:
20ms frame - 16ms pulsing leaves 4ms, 4 ms is 20% of 20 milliseconds.

I just wanted to pointing out that if you pulsed 12 servos by waiting for each pulse to finish you would have little time to do anything else.
Another issue with the sketch directly pulsing the servos is that it needs to be structured to service the servos every 20ms or so. As your code demonstrates, that can certainly be done, but for some it may be easier to only have to consider a servo when a new value needs to be written.

I also think that an advantage of a library is that it assists the grouping of the major systems of an application into separate components. This can make a complex application easier to understand, maintain and enhance because it reduces the likelihood of unintended interaction between components by providing a clear set of interfaces.

Anyway, good to read about your robot – have fun!