Obstacle Avoiding Robot Project

I'm using an AdaFruit V2.3 Motor Shield and i'm having problems with the library and directory.
Everytime I try to confirm, it says directory not found.
I've changed the name to "Adafruit_MotorShield" and added it to the Arduino Library.
Also i'll post the code as well to see if anything is wrong with it as well.

#include <Adafruit_MotorShield.h>
#define trigPin 12 // define the pins of your sensor
#define echoPin 13 
AF_DCMotor motor1(1,MOTOR12_64KHZ); // set up motors.
AF_DCMotor motor2(2, MOTOR12_8KHZ);
 
void setup() {
  Serial.begin(9600); // begin serial communitication  
  Serial.println("Motor test!");
   pinMode(trigPin, OUTPUT);// set the trig pin to output (Send sound waves)
  pinMode(echoPin, INPUT);// set the echo pin to input (recieve sound waves)
  motor1.setSpeed(105); //set the speed of the motors, between 0-255
motor2.setSpeed (105);  
}
 
void loop() {

   long duration, distance; // start the scan
  digitalWrite(trigPin, LOW);  
  delayMicroseconds(2); // delays are required for a succesful sensor operation.
  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10); //this delay is required as well!
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;// convert the distance to centimeters.
  if (distance < 25)/*if there's an obstacle 25 centimers, ahead, do the following: */ {   
   Serial.println ("Close Obstacle detected!" );
Serial.println ("Obstacle Details:");
Serial.print ("Distance From Robot is " );
Serial.print ( distance);
Serial.print ( " CM!");// print out the distance in centimeters.

Serial.println (" The obstacle is declared a threat due to close distance. ");
Serial.println (" Turning !");
    motor1.run(FORWARD);  // Turn as long as there's an obstacle ahead.
    motor2.run (BACKWARD);

}
  else {
   Serial.println ("No obstacle detected. going forward");
   delay (15);
   motor1.run(FORWARD); //if there's no obstacle ahead, Go Forward! 
    motor2.run(FORWARD);  
  }  
  
}

Obstacle_Avoiding_Robot_Code.ino (1.66 KB)

After installing the library, did you close then re-open the Arduino IDE?

And is "Adafruit_MotorShield.h" in the top-level folder of the library? ie In the "Adafruit_MotorShield" folder, and not in a deeper folder inside that one.

About that...
I Extracted the folder before adding it to the library. After redoing it right, it can find the library now. Unfortunately I can't seem to get the code to work. The Robot is not moving.

Looking back in the overview for the Motor shield I rewrote my code using the parameters i'm supposed to use. But i'm still getting errors when trying to compile.

Obstacle_Avoiding_Robot_Code.ino (1.37 KB)

Exactly what sort of motors are you using?

DC brush motors
I've tinkered a bit and now i've got the thing moving. The thing is that now the sensor isn't really responding well.

yvan905:
DC brush motors
I've tinkered a bit and now i've got the thing moving. The thing is that now the sensor isn't really responding well.

I just thought I'd better ask. Your first code should really have worked.

the sensor isn't really responding well

More information would help. This doesn't tell us much, except that you have a problem.

False readings? Inaccuracy? Something else?

What are you using for a power supply for the motors?
And what size motors? ie Current draw.

The motors are 3V and they're pretty small.
I'm using a HC-SR04 Sonar sensor.
I'm getting pretty inaccurate readings.
Here's my code again to see what could be the problem.

Obstacle_Avoiding_Robot_Code.ino (1.54 KB)

It would be far easier for everyone if you just posted your code rather than attaching it. (Between code tags, of course.)
Then it could be viewed without having to open it in our IDEs, which also involves creating a folder for it to reside in

Your ultrasonic code looks OK. Edit: I missed this initially:-

if (distance > maximumRange)

It won't affect your readings, but it will affect how your robot handles them.
It will only turn if there are no obstacles in the way.

What are you using for a power supply for the motors? I already asked this, but you didn't answer. One of the most common causes of bad readings is spikes on the power supply.

I found that the best way to get good, consistent readings was to use the "NewPing" library, and it's 'ping_median()' method. It averages several readings, rather than just taking individual results.

Also, what sort of surface is giving you the inconsistent readings? Ultrasonic ranging works best with hard surfaces that are directly across the line of sensing. It doesn't work so well, and sometimes not at all, if the obstacle is at an angle, or if it is soft like cloth.
I overcame the angle aspect by having a servo swing the sensor from side-to-side, taking readings at 5 points.

I'm using a 4 AA battery pack.
How would the New Ping code work?

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#define trigPin 12 // define the pins of your sensor
#define echoPin 13
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *Motor1 = AFMS.getMotor(1);
Adafruit_DCMotor *Motor2 = AFMS.getMotor(2);
int maximumRange = 20; // Maximum range needed

long duration, distance; // Duration used to calculate distance

void setup() {
  Serial.begin(9600); // begin serial communitication
  Serial.println("Motor test!");
  pinMode(trigPin, OUTPUT);// set the trig pin to output (Send sound waves)
  pinMode(echoPin, INPUT);// set the echo pin to input (recieve sound waves)
  AFMS.begin();
  AFMS.getMotor(1)->setSpeed(135); //set the speed of the motors, between 0-255
  AFMS.getMotor(2)->setSpeed(135);
}

void loop() {

  long duration, distance; // start the scan
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2); // delays are required for a succesful sensor operation.
  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10); //this delay is required as well!
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration/58.2; // convert the distance to centimeters.
  if (distance > maximumRange) { /*if there's an obstacle 25 centimers, ahead, do the following: */
    AFMS.getMotor(1)->run(FORWARD);  // Turn as long as there's an obstacle ahead.
    AFMS.getMotor(2)->run(BACKWARD);

  }
  else {
    AFMS.getMotor(1)->run(FORWARD); //if there's no obstacle ahead, Go Forward!
    AFMS.getMotor(2)->run(FORWARD);
  }







}

yvan905:
I'm using a 4 AA battery pack.

How are they connected? ie Series, parallel, series-parallel. What is the battery pack output voltage?
And are you powering only the motors with it, or the Arduino and US sensor as well?

How would the New Ping code work?

What do you mean?
Do you mean that you want to know how 'ping_median()' does the averaging, or are you asking for a code example of using it, or something else?

You could start by reading the "NewPing" documentation. It also has a non-blocking 'ping_timer()' method, as well as built-in methods for directly returning cm or inches.
I'd recommend that you check it out - download it, read the documentation thoroughly, then give it a try. Just test it with a separate sketch at first, as you should do with everything before adding them to your main program.

The Battery pack is connected to the motor shield that's stacked on top of the Arduino. It's a V2.3.
I'll attach a picture of it.

Can you provide an example of code that will work the same way with the NewPing?

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#define trigPin 12 // define the pins of your sensor
#define echoPin 13
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *Motor1 = AFMS.getMotor(1);
Adafruit_DCMotor *Motor2 = AFMS.getMotor(2);
int maximumRange = 20; // Maximum range needed

long duration, distance; // Duration used to calculate distance

void setup() {
  Serial.begin(9600); // begin serial communitication
  Serial.println("Motor test!");
  pinMode(trigPin, OUTPUT);// set the trig pin to output (Send sound waves)
  pinMode(echoPin, INPUT);// set the echo pin to input (recieve sound waves)
  AFMS.begin();
  AFMS.getMotor(1)->setSpeed(135); //set the speed of the motors, between 0-255
  AFMS.getMotor(2)->setSpeed(135);
}

void loop() {

  long duration, distance; // start the scan
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2); // delays are required for a succesful sensor operation.
  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10); //this delay is required as well!
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration/58.2; // convert the distance to centimeters.
  if (distance > maximumRange) { /*if there's an obstacle 25 centimers, ahead, do the following: */
    AFMS.getMotor(1)->run(FORWARD);  // Turn as long as there's an obstacle ahead.
    AFMS.getMotor(2)->run(BACKWARD);

  }
  else {
    AFMS.getMotor(1)->run(FORWARD); //if there's no obstacle ahead, Go Forward!
    AFMS.getMotor(2)->run(FORWARD);
  }







}

yvan905:
The Battery pack is connected to the motor shield that's stacked on top of the Arduino. It's a V2.3.
I'll attach a picture of it.

No need for a picture. It's probably adequate for those little 3V motors. I was more concerned with whether you were using the same supply for motors and US sensor, since motor spikes might have been causing your problem with inconsistent ranging results.

Can you provide an example of code that will work the same way with the NewPing?

No. As I suggested, you could read the documentation. You could also test out the examples provided with the library. I shouldn't have to write code for you. The library has perfectly good examples.

And I see you still haven't fixed the problem that I pointed out in reply #8. Don't you read replies?

if (distance > maximumRange) { /*if there's an obstacle 25 centimers, ahead, do the following: */
    AFMS.getMotor(1)->run(FORWARD);  // Turn as long as there's an obstacle ahead. *** No it won't ***
    AFMS.getMotor(2)->run(BACKWARD);
  }
  else {
    AFMS.getMotor(1)->run(FORWARD); //if there's no obstacle ahead, Go Forward! *** No it won't ***
    AFMS.getMotor(2)->run(FORWARD);
  }

With this code, your robot will only turn if there is no obstacle
And it won't turn when there is an obstacle

Yes I Use the same power supply for everything including the motors and Sensors.

And I haven't fixed the problem because I don't understand what you want me to add or change.
That's why I asked for example code.

yvan905:
Yes I Use the same power supply for everything including the motors and Sensors.

Bad move. You should power the Arduino and the ultrasonic sensor from one supply, and the motors from a second supply. Any spikes created by the motors will affect operation of the ultrasonic sensor and possibly even the Arduino. Especially with such a tiny battery pack. Are the cells in series, parallel, series-parallel. What is the battery pack output voltage? I already asked this, but you didn't reply again. There was a very good reason I asked.
Are you using rechargeable batteries, or primary cells?

And I haven't fixed the problem because I don't understand what you want me to add or change.
That's why I asked for example code.

This:-

(distance > maximumRange)

Should be this:-

(distance < maximumRange)

I thought I'd made that very clear already. You had it right earlier, if I remember correctly, then changed it. Dunno why.

So, please answer these questions before we continue:-

  1. What is the battery pack output voltage?
  2. Are you using rechargeable batteries, or primary cells?

The Battery Pack output voltage is 6v. (4 1.5V AA batteries)
They're non-rechargable batteries. So I guess primary cells?

yvan905:
The Battery Pack output voltage is 6v. (4 1.5V AA batteries)
They're non-rechargable batteries. So I guess primary cells?

Yep. At least it's not as bad as rechargeables. I guess you're running the ultrasonic sensor from the Arduino's 5V output?
A problem, besides the fact that you should really use separate supplies, is that 6V is not really high enough for the Arduino's onboard regulator. It should have a minimum of about 6.5V going into the Vin pin. The forward voltage drop of the regulator is 1V to 1.2V, so when the batteries are under high load the Arduino regulator could 'drop out', and the voltage on the 5V rail would dip. That could easily affect the ultrasonic sensor. The problem would be at it's worst each time a motor is turned on, due to the higher than usual inrush current.

Like I said, for now fix that little error in your code so that the robot really turns when an obstacle is too close, then check out the "NewPing" library. If there are spikes on the supply rail, the 'ping_median()' method might well help, since it can average several readings. It defaults to taking the average of 5 readings, but that can be increased or decreased as necessary.

I found that even when using the simple "NewPing" methods, I got better results than doing the ranging using 'pulseIn()'.

I won't write your code for you, it's better if you do that if you're going to learn, but this is the simple sketch I used to test 'ping_median()'. You could easily adapt it to your purpose.:-

/* NewPingMedianTest.ino
*
*  Notes:
*  A test of the 'ping_median()' function of the 'New Ping' Library,
*  using the HC-SR04 ultrasonic ranging module.
*  In this test, the program will light a green LED initially, then
*  turn it off and light a red LED if an object comes within 20cm.
*  It will use 'pingMedian()' to average 5 US range readings each time.
*/

#include "NewPing.h"

#define TRIGGER_PIN     5               // HC-SR04 trigger pin.
#define ECHO_PIN        6               // HC-SR04 echo pin.
#define MAX_DISTANCE    200             // Maximum distance to ping for in cm, 400 max.

// Constants:-
const int THRESHOLD = 20;               // 20cm threshold.
const byte pGreenLED = 2;               // Green LED on pin D2.
const byte pRedLED = 3;                 // Red LED on D3.

// Variables:-
long lDistancecm;                       // Will hold the actual distance to the detected object in cm.
unsigned long mS;                       // Holds millis() value for delays.
unsigned long median_uS;                // Time for distance in microseconds.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup()
{
    pinMode(pGreenLED, OUTPUT);
    pinMode(pRedLED, OUTPUT);
}

void loop()
{
    mS = millis();                              // 50mS between distance checks.
    while (millis() < mS + 50) {}               //  "      "       "       "
    median_uS = sonar.ping_median(5);  // Do 5 pings, discard out of range pings and return median in microseconds.
    lDistancecm = sonar.convert_cm(median_uS);  // Convert microseconds to distance in cm.

    // Light the LEDs according to distance. Green if over 20cm, red if closer:-
    if ((lDistancecm == 0) || (lDistancecm >= THRESHOLD))
    {
        digitalWrite(pGreenLED, 1);
        digitalWrite(pRedLED, 0);
    }
    else
    {
        digitalWrite(pGreenLED, 0);
        digitalWrite(pRedLED, 1);
    }
}

Note: Don't use this though, it was just for the crude test I was doing:-

while (millis() < mS + 50) {}

(It's the same as delay(), and holds up the code for 50mS.)

yvan905:
Well it's 6v since it's 4 1.5v AA Batteries.
They're non-rechargeable so I guess prime cells.
How do I distribute the power? I thought the Motor Shield would do it.

I don't have the motor shield, but I think it has a jumper that's used to power the Arduino from the battery supply. If you had a second power supply, you could disconnect that jumper.

Perhaps you should do yourself a favour and thoroughly read all of the documentation on the Adafruit Motor Shield, rather than me having to look it up myself, just to pass the info on to you.

This is from the Adafruit documentation on your motor shield:-

Its also very much suggested that you set up two power supplies (split supply) one for the Arduino and one for the motors. 99% of 'weird motor problems' are due to noise on the power line from sharing power supplies and/or not having a powerful enough supply! Even small DC motors can draw up to 3 Amps when they stall.

And also this:-

MOST 1.5-3V MOTORS WILL NOT WORK

I guess you're getting away with it because you're powering your 3V motors from 6V.

How's the code looking?

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     13  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *Motor1 = AFMS.getMotor(1);
Adafruit_DCMotor *Motor2 = AFMS.getMotor(2);
const int THRESHOLD = 20;               // 20cm threshold.
long lDistancecm;                       // Will hold the actual distance to the detected object in cm.
unsigned long mS;                       // Holds millis() value for delays.
unsigned long median_uS;                // Time for distance in microseconds.
void setup() {
  Serial.begin(9600); // begin serial communitication
  
  AFMS.begin();
  AFMS.getMotor(1)->setSpeed(135); //set the speed of the motors, between 0-255
  AFMS.getMotor(2)->setSpeed(135);
}

void loop() {

      mS = millis();                              // 50mS between distance checks.
    while (millis() < mS + 50) {}               //  "      "       "       "
    median_uS = sonar.ping_median(5);  // Do 5 pings, discard out of range pings and return median in microseconds.
    lDistancecm = sonar.convert_cm(median_uS);  // Convert microseconds to distance in cm.
  
if (lDistancecm <= THRESHOLD))
    {
     AFMS.getMotor(1)->run(FORWARD);  // Turn as long as there's an obstacle ahead.
    AFMS.getMotor(2)->run(BACKWARD);
    }
    else
    {
      AFMS.getMotor(1)->run(FORWARD); //if there's no obstacle ahead, Go Forward!
    AFMS.getMotor(2)->run(FORWARD);
    }
}

Also How do I go about doing that? Should I put two battery packs then? One connected to the motor shield and the other to the arduino?

yvan905:
How's the code looking?

First problem - as I said, you can't really use that 50mS delay in a 'real' program. It was OK for my test, but the problem is that using delay slows the llop down and nothing else can happen during the 50mS delay.
You really need to use millis()-based timing in a different way to do a reading every 50mS.

You could declare "unsigned long prevMillis;" globally at the top of your program, then use 'millis()' regularly to do the readings. The HC-SR04 datasheet recommends readings > 60mS apart, from memory, but 50mS is fine.
Take a good look at the "BlinkWithoutDelay" example, in the IDE under >File >Examples >Digital. It shows how to use 'millis()' properly to do this type of timing.

Also How do I go about doing that? Should I put two battery packs then? One connected to the motor shield and the other to the arduino?

Yes. Did you read all of the motor shield documentation yet? You really need to do it. You should read all documentation on anything you plan to use, before you use it.

And it's bad manners to PM people asking for personal help. Don't you think I've already spent enough time trying to help you? I've spent a couple of hours today, looking at your code, answering your posts and reading the documentation that you should have read.
You really need to go off and do some reading, to learn how to do the things that you need to do, rather than ask me to provide all of the information.