twitter
Search

Entries in roving (3)

Sunday
Mar252012

Arduino, BOE Shield, PING, and a servo

The video above is in two parts: first with a crawler kit and then with wheels. Switching back to wheels required a code modification to change the time it takes to turn. 
All the parts in the video were released for the original STAMP/Propeller chips, but the code below will get you off and running on the Arduino shield. Only digital pins 10, 11, 12, and 13 are used, so any shield that does not require those pins is available for use. 
// BOE Shield code from "Robotics with the BOE Bot"
// Roaming With Whiskers source, modified to use a PING)))
// sensor on the PING))) servo bracket.
// Using code from the Ping))) example sketch.
#include <Servo.h>                           // Include servo library
Servo servoLeft;                             // Declare left, right and Ping))) servos
Servo servoRight;
Servo PingServo;
int minSafeDist = 11 ;                        // Minimum distance in inches
int pingPin = 10;                             // PING input on 10 so the last servo port is used.
int centerDist, leftDist, rightDist;          // Define distance variables
long duration, inches, cm;                    // Define variables for Ping)))
void setup()                                 // Built-in initialization block
  tone(4, 3000, 1000);                       // Play tone for 1 second
  delay(1000);                               // Delay to finish tone
  servoLeft.attach(13);                      // Attach left signal to pin 13 
  servoRight.attach(12);                     // Attach right signal to pin 12
  PingServo.attach(11);
}  
void loop(){
  LookAhead();
  if(inches >= minSafeDist) /* If the inches in front of an object is greater than or equal to the minimum safe distance (11 inches), react*/
  {
    forward (121); //Go Forward
    delay(110); // Wait 0.11 seconds
  }
  else // If not:
  {
    servoLeft.writeMicroseconds(1500);
    servoRight.writeMicroseconds(1500);
    LookAround(); // Check your surroundings for best route
    if(rightDist > leftDist) // If the right distance is greater than the left distance , turn right
    {
      turnRight (250); // Turn Right      
    }
    else if (leftDist > rightDist) // If the left distance is greater than the right distance , turn left
    {
      turnLeft (250); // Turn Left
    }
    else
    {
      backward (250); // Go Backward
    }
    delay (250);
  }
}
void forward(int time)                       // Forward function
{
  servoLeft.writeMicroseconds(1700);         // Left wheel counterclockwise
  servoRight.writeMicroseconds(1300);        // Right wheel clockwise
  delay(time);                               // Maneuver for time ms
}
void turnLeft(int time)                      // Left turn function
{
  servoLeft.writeMicroseconds(1300);         // Left wheel clockwise
  servoRight.writeMicroseconds(1300);        // Right wheel clockwise
  delay(time);                               // Maneuver for time ms
}
void turnRight(int time)                     // Right turn function
{
  servoLeft.writeMicroseconds(1700);         // Left wheel counterclockwise
  servoRight.writeMicroseconds(1700);        // Right wheel counterclockwise
  delay(time);                               // Maneuver for time ms
}
void backward(int time)                      // Backward function
{
  servoLeft.writeMicroseconds(1300);         // Left wheel clockwise
  servoRight.writeMicroseconds(1700);        // Right wheel counterclockwise
  delay(time);                               // Maneuver for time ms
}
unsigned long ping() {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW); //Send a low pulse
  delayMicroseconds(2); // wait for two microseconds
  digitalWrite(pingPin, HIGH); // Send a high pulse
  delayMicroseconds(5); // wait for 5 micro seconds
  digitalWrite(pingPin, LOW); // send a low pulse
  pinMode(pingPin,INPUT); // switch the Pingpin to input
  duration = pulseIn(pingPin, HIGH); //listen for echo
  /*Convert micro seconds to Inches
   -------------------------------------*/
  cm = microsecondsToCentimeters(duration);
  inches = microsecondsToInches(duration);
}
long microsecondsToInches(long microseconds) // converts time to a distance
{
  return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) // converts time to a distance
{
  return microseconds / 29 / 2;
}
void LookAhead() {
  PingServo.write(90);// angle to look forward
  delay(175); // wait 0.175 seconds
  ping();
}
void LookAround(){
  PingServo.write(20); // 20° angle
  delay(320); // wait 0.32 seconds
  ping();
  rightDist = inches; //get the right distance
  PingServo.write(160); // look to the other side
  delay(620); // wait 0.62 seconds
  ping(); 
  leftDist = inches; // get the left distance
  PingServo.write(90); // 90° angle
  delay(275); // wait 0.275 seconds
}

 

Wednesday
Feb012012

2WD Roving Robot

This is a simple robot using an Adafruit Motor Shield, Arduino Uno, and two motors. The video shows off the sensors and arrangements. The source code is below:

/*
Autonomous roving robot
Parts: 
   -Arduino Uno
   -Parallax PING))) ultrasonic sensor
   -Adafruit motor shield http://www.ladyada.net/make/mshield/
   -2WD Mobile Platform http://www.makershed.com/ProductDetails.asp?ProductCode=MKSEEED7
   -Lever switch (for back bumper)
   -Indicator LED
   -Energizer XPAL XP8000 battery (custom cable and self-built regulator for motors)
Original motion functions and design from Robot Living 8/30/2010 
Code borrowed from example sketches:
   -Ping
Original code created June 2011
by Daniel Gentleman
thoughtfix@gmail.com
http://thoughtfix.com

Additional credits: 
Victor Brilon
Mark Balliet
luckylarry.co.uk for the math on the Sharp sensor
Advice from arduino.cc forum
Advice from from #arduino on irc.freenode.net
Advice from adafruit forums
Further inspiration
      -Adafruit Industries
      -Make Magazine
Adafruit Motor shield library

Wiring (remember, analog 0 is also digital 14) 
- Left motor to Motor 1
- Right motor to Motor 2
- LEDs on digital 15 and 16
- PING))) on digital 17
- Sharp IR sensors on digital 18 and 19
- Lever switch (bumper attached) on digital 14
- USB power (from a USB battery) to the Arduino
- Regulated power (I used an Energizer XPAL XP8000 regulated to +5v) for servos
*/


#include <AFMotor.h>

AF_DCMotor motorL(1, MOTOR12_1KHZ);
AF_DCMotor motorR(2, MOTOR12_1KHZ);


int BSensor = 14; //Back sensor
int FLEDPin = 15; //Forward LED
int BLEDPin = 16; //Backup LED
int pingPin = 17; //Front sensor
int FSensorR = 18; //Front right sensor
int FSensorL = 19;  //Front left sensor
int count = 0;
int b=0;
int bs=0;
int sensorValue;
int forwardSensor;
int sensorValueB=1;
int leftSensor=0;
int rightSensor=0;
int obstacle=0;


void setup() {
  Serial.begin(9600); 
  randomSeed(analogRead(0));
  pinMode(BLEDPin, OUTPUT); 
  pinMode(FLEDPin, OUTPUT);
  pinMode(BSensor, INPUT);
  pinMode(pingPin, INPUT);
  pinMode(FSensorR, INPUT);
  pinMode(FSensorL, INPUT);
  motorL.setSpeed(200);
  motorR.setSpeed(200);
  motorL.run(RELEASE);
  motorR.run(RELEASE);
}

void loop()
{
  uint8_t i;
  Forward();
}

void Forward () // Charge forth!
{
  digitalWrite(FLEDPin, HIGH);                
  digitalWrite(BLEDPin, LOW);
  ForwardSensor ();
  if (obstacle == 0){ //unless something is in the way
  Serial.println("Going forward.");
  motorL.run(FORWARD);
  motorR.run(FORWARD);
  }

}

void ForwardSensor ()
{
  leftSensor = (ForwardSensorLeft());
  rightSensor =(ForwardSensorRight());
  forwardSensor = (getDistance());
  delay(30);
  //  Serial.print(leftSensor);
  //  Serial.println(" left");
  //  Serial.print(rightSensor);
  //  Serial.println(" right");
  //  Serial.print(forwardSensor);
  //  Serial.println(" front");
  if (forwardSensor <=30 || leftSensor <= 30 || rightSensor <= 30 )
  { // I gave 10cm of "wiggle room" so it doesn't turn endlessly. 
    obstacle=1;
    if (ForwardSensorRight() > (ForwardSensorLeft()-10)){
      RightBackward();
    }
    else if (ForwardSensorRight() < (ForwardSensorLeft()-10)){
      LeftBackward();
    }
    else{
      Backward();
    }
  }
  else {
    obstacle = 0;
  }
  sensorValue=0;
  rightSensor=0;
  leftSensor=0;
}

int ForwardSensorRight () 
{ // This function is here so you don't have to re-write code
  // if you use a different sensor.
  sensorValue = irDistance(FSensorR); 
  return sensorValue;
}

int ForwardSensorLeft ()
{ // This function is here so you don't have to re-write code
  // if you use a different sensor.
  sensorValue = irDistance(FSensorL); 
  return sensorValue;
}

void BackwardSensor ()
{
  sensorValueB = digitalRead(BSensor); 
  if (sensorValueB == 1)
  {
    Serial.println("Object detected while going backwards.");
    motorL.run(RELEASE);
    motorR.run(RELEASE);
    for (bs=0; bs <= 3; bs++) // Add blinky lights for personality on detecting object when backing up.
    {
      digitalWrite(FLEDPin, HIGH);                
      digitalWrite(BLEDPin, HIGH);
      delay(5);
      digitalWrite(FLEDPin, LOW);                
      digitalWrite(BLEDPin, LOW);
      delay (5);
    }
    b=31;
    bs=0;
    Forward();

  }
  sensorValueB = 0;
}

void Backward ()
{
  motorL.run(RELEASE);
  motorR.run(RELEASE);
  digitalWrite(FLEDPin, LOW);                
  digitalWrite(BLEDPin, HIGH);
  Serial.println("Going backwards.");

  do
  {
    b++;
    motorL.run(BACKWARD);
    motorR.run(BACKWARD);
    delay(20);
    BackwardSensor ();
  } 
  while (b < 20);

  b=0;
}


void LeftBackward ()
{
  motorL.run(RELEASE);
  motorR.run(RELEASE);
  digitalWrite(FLEDPin, LOW);                
  digitalWrite(BLEDPin, HIGH);
  Serial.println("Going left backwards.");

  do
  {
    b++;
    //    Serial.print("b = ");
    //    Serial.print(b);
    motorL.run(BACKWARD);
    motorR.run(RELEASE);
    BackwardSensor ();
    delay (20);
  } 
  while (b < 20);

  b=0;
}

void RightBackward ()
{
  motorL.run(RELEASE);
  motorR.run(RELEASE);
  digitalWrite(FLEDPin, LOW);                
  digitalWrite(BLEDPin, HIGH);
  Serial.println("Going right backwards.");

  do
  {
    b++;
    //    Serial.print("b = ");
    //    Serial.print(b);
    motorL.run(RELEASE);
    motorR.run(BACKWARD);
    BackwardSensor ();
    delay (20);
  } 
  while (b < 20);

  b=0;
}

int getDistance()

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
reread:  // takes another reading if cm=0
  long duration, cm;
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  cm = microsecondsToCentimeters(duration);
  //  Serial.print(cm);
  //  Serial.print("cm");
  //  Serial.println();
  delay(100);
  //  if (cm == 0) {
  //    goto reread;
  //  }
  return cm;


long microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return (microseconds/58);
}

int irDistance(int irPin) {
  float volts = analogRead(irPin)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
  int distance = 32.5*pow(volts, -1.10);          // theretical distance 32.5/ (1/Volts)S 
  //  Serial.print(distance);
  //  Serial.print(" from ");
  //  Serial.println(irPin);  
  delay (10);
  return distance;        // print the raw analog value to serial port
}

Wednesday
Feb012012

DFRobotShop Rover example code

A lot of people who submitted to the Adafruit/Instructables "Make it Tweet" challenge also submitted to the RobotShop Microcontroller contest, so many of us got our 50% off coupon codes for a DFRobotShop Rover. I noticed that the documentation on this was a little lacking especially where code is concerned. Even the example code needed some upgrading. 

After poking and prodding around for a while, I think I figured out all the pins, the on-board light sensor, and the on-board temperature sensor. The sketch below turns every operation into a function so it can be called selectively by the user who needs it. I am posting this here in hopes that it helps others with their robot projects:

 

 

/* DFRobotShop Rover bare minimum

Left and right are determined as though driving a car
with the USB and power ports in the rear. If you want
to test code without driving it off your desk, simply
remove the tank treads! 

Board Type: Arduino Duemilanove ATMega328
Motor Drivers: L293B dual H bridge

Motors run at 4.5v nominal, but the whole board can
be powered from 3.78v to 9V. 


pin 5; //Right Speed Control (analogWrite 0-255)
pin 6; //Left Speed Control (analogWrite 0-255)
pin 7; //Right Direction Control  (HIGH=forward, LOW=back)
pin 8; //Left Direction Control (HIGH=forward, LOW=back)

Ambient Light pin on Analog 0
Thermal Sensor (LM35) on Analog 1

*/
int lightPin = A0;
int thermoPin = A1;
int rightMotorPin = 5;
int leftMotorPin = 6;
int rightDirectionPin = 7;
int leftDirectionPin = 8;
int leftspeed = 255; //255 is maximum speed
int rightspeed = 255;

void setup(){
  pinMode(lightPin, INPUT);
  pinMode(thermoPin, INPUT);
  pinMode(rightMotorPin, OUTPUT);
  pinMode(leftMotorPin, OUTPUT);
  pinMode(rightDirectionPin, OUTPUT);
  pinMode(leftDirectionPin, OUTPUT);
  Serial.begin(9600); // 
}

void loop(){
  // Everything in here is just an example of how to use the functions below.
  forward (leftspeed,rightspeed); //Go Forward
  delay(2500);
  left (leftspeed,rightspeed); // Turn Left
  delay(2500);
  reverse (leftspeed,rightspeed); // Go Backward
  delay(2500);
  right (leftspeed,rightspeed); // Turn Right
  delay(2500);
  stop(); // Full Stop
  delay(2500);
  float TempC = getTemp();
  Serial.print(TempC);
  Serial.println(" degrees C");
  delay(500);
  float light = getLight();
  Serial.print(light);
  Serial.println(" percent readable light"); 
  delay(500);

}

// Everything below this line can be deleted or you can re-use the code

void stop(void) //Stop
{
  digitalWrite(leftMotorPin,LOW);
  digitalWrite(rightMotorPin,LOW);
}

void forward(char a,char b)
{
  analogWrite (leftMotorPin,a);
  digitalWrite(leftDirectionPin,LOW);
  analogWrite (rightMotorPin,b);
  digitalWrite(rightDirectionPin,LOW);
}

void reverse (char a,char b)
{
  analogWrite (leftMotorPin,a);
  digitalWrite(leftDirectionPin,HIGH);
  analogWrite (rightMotorPin,b);
  digitalWrite(rightDirectionPin,HIGH);
}

void left (char a,char b)
{
  analogWrite (leftMotorPin,a);
  digitalWrite(leftDirectionPin,HIGH);
  analogWrite (rightMotorPin,b);
  digitalWrite(rightDirectionPin,LOW);
}

void right (char a,char b)
{
  analogWrite (leftMotorPin,a);
  digitalWrite(leftDirectionPin,LOW);
  analogWrite (rightMotorPin,b);
  digitalWrite(rightDirectionPin,HIGH);
}

float getTemp ()
{
  float sensorRead = analogRead(thermoPin); // Get reading
  float tempRead = (5.0 * sensorRead * 100.0)/1024.0; // 5V
  return tempRead;
}

float getLight()
{
  float lightRead = analogRead(lightPin);
  float lightPercent = map(lightRead, 1024, 0, 0, 100); // to percent of light reading
  return lightPercent;
}