twitter
Search

Entries in robot (6)

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
Mar212012

Parallax BOE Shield for Arduino: First Look

I'm a big fan of Parallax and adafruit industries, so was glad to learn that they are now stocking the Parallax BOE Shield for Arduino. I already owned this kit but have yet to have time to play with it. The video above is an unboxing of the BOE Shield, PING))) sensor mounting bracket, and crawler kit. 
The original Parallax BOE-Bot uses Propeller controller and is very good for learning robotics in that environment. The lessons, documentation, and examples are quite detailed. With a focus on education, Parallax wisely decided to expand this platform into Arduino territory. The only "required" pins for the shield are two of 10, 11, 12, and 13. You can choose which two in your Arduino code. The rest can be used with your normal stackable Arduino shields.
To get a general idea of the BOE Shield and completed robot in action, take a look at adafruit's new product announcement.
Here's a photo of the crawler kit sitting on an original BOE bot (borrowed from Parallax's site) that I intend to use with the BOE Shield.
I'll be posting all my source code and a bunch of pictures or videos, but it will all pale in comparison to the online book from Parallax.
Stay tuned for more!

 

Wednesday
Feb152012

Dirt cheap robot chassis

I am satisfied with the Magician Chassis that I picked up from Sparkfun. So many mount points!

http://www.sparkfun.com/products/10825

Wednesday
Feb012012

Laser ToyBot for Cats

This is a simple bot that really belongs installed in an R2-D2 toy. It's simply an Ardweeny on a breadboard, a set of AA batteries, a continuous rotation servo, a standard servo, and a laser. If there's a desire for source code, I'll post it here. However, it's simply a matter of random writes to both servos (after calibrating the vertical servo so it doesn't move more than 15 degrees.) 

 

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
}