Go Down

Topic: problems with robot using ultrasonic sensor to avoid obstacles [solved] (Read 2627 times) previous topic - next topic

padawan

Hi!
This is my first Arduino project and I'm having problems. I want to make a robot use an ultrasonic sensor to tell it to back away when it gets within 10 centimeters of something. I'm using an Arduino Uno R3, a Makeblock Me ultrasonic sensor, an OSEPP MTD-01 motor driver, and 2 DC motors. My code is a combination of the ultrasonic sensor example in the IDE and a code for what I want to do from a book. I modified it for the motor driver but I think I'm trying to use the motor driver wrong, since I couldn't find any instructions online. The robot runs fine until right after the LED is on for 5 seconds, then I start having problems. First, both motors are running backwards though they were fine during setup. Then, if I put my hand in front of the sensor, the left motor starts going forwards while the right one just stops. When I move my hand both motors start going backwards again. Here's my code:


 

Code: [Select]
const int pwm1 = 11;//left motor 
const int in1 = 10;//left backward
const int in2 = 9;//left forward
const int pwm2 = 6;//right motor
const int in3 = 5;// right backward
const int in4 = 4;// right forward
const int led = 13;
const int pingPin = 7;

 
void setup() {
  pinMode (pwm1, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(pwm2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(led, OUTPUT);
 
  digitalWrite(in2, HIGH);
  digitalWrite(pwm1, 100);
  digitalWrite(in4, HIGH);
  digitalWrite(pwm2, 100);
  delay(1000);
  digitalWrite(in2, LOW);
  digitalWrite(pwm1, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(pwm2, LOW);
  delay(1000);
  digitalWrite(in1, HIGH);
  digitalWrite(pwm1, 100);
  digitalWrite(in3, HIGH);
  digitalWrite(pwm2, 100);
  delay(1000);
  digitalWrite(in1, LOW);
  digitalWrite(pwm1, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(pwm2, LOW);
 
  digitalWrite(led, HIGH);//LED on for 5 seconds
  delay(5000);
  digitalWrite(led, LOW);
  Serial.begin(9600);// stops doing what i want it to do here
}
void loop(){
  digitalWrite(in2, HIGH);
  digitalWrite(pwm1, 100);
  digitalWrite(in4, HIGH);
  digitalWrite(pwm2, 100);
  uint8_t i;

  long duration, inches, cm;
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin,HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
 
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  cm = microsecondsToCentimeters(duration);
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  if (cm >10){
    digitalWrite(in2, LOW);//left motor, backwards
    digitalWrite(pwm1, LOW);
    digitalWrite(in1, HIGH);
    digitalWrite(pwm1, 100);

  //for (i=0; i<255; i++){
 // delay(10);}
 
  digitalWrite(in4, LOW);// right motor, backwards
  digitalWrite(pwm2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(pwm2, 100);
  for (i=0; i<255; i++){
  delay(10);}
 
digitalWrite(in3, LOW);//start both motors forward again
digitalWrite(in4, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in1, HIGH);
delay(30);
  }
  else{
    digitalWrite(in2, HIGH);
    digitalWrite(pwm1, 100);
    digitalWrite(in4, HIGH);
    digitalWrite(pwm2, 100);
  }
  }
  long microsecondsToCentimeters(long microseconds)
  {
 
    return microseconds / 29/ 2;}
 
 

And here's the one I modified it from:
Code: [Select]
#include <AFMotor.h>
AF_DCMotor motorleft(1);
AF.DCMotor motorright(4);
const int pingPin = 7;
void setup() {
  Serial.begin(9600);
  motorleft.setSpeed(50);
  motorright.setSpeed(50);

}

void loop() {
 uint8_t i;
 long duration, inches, cm;
 pinMode(pingPin, OUTPUT);
 digitalWrite(pingPin, LOW);
 delayMicroseconds(2);
 digitalWrite(pingPin, HIGH);
 delayMicroseconds(5);
 digitalWrite(pingPin,LOW);
 pinMode(pingPin, INPUT);
 duration = pulseIn(pingPin, HIGH);
 cm = microsecondsToCentimeters(duration);
 Serial.print(cm);
 Serial.print("cm");
 Serial.println();
 if (cm>10){
  motorleft.run(BACKWARD);
  for (i=0; i<255; i++){
    motorleft.setSpeed(i);
    delay(10);}
    motorright.run(BACKWARD);
    for (i=0, i<255; i++){
      motorright.setSpeed(i);
      delay(10);
    }
    motorleft.run(RELEASE);
    motorright.run(RELEASE);
    delay(30);
 }
}
long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}
 

I have checked my wiring. Since I'm a noob and don't really know what every single part of the code is doing, I'm probably using it wrong and making some noob mistake, though I have no idea what. Thanks in advance for any help!
-p.

slipstick

So why did you decide to use the Make Me sensor like that instead of using the library and instructions from the website at http://learn.makeblock.com/en/me-ultrasonic-sensor/ ? I would have thought that would be easier. But since you have those serial writes in there, is it actually getting the distances correct?

And then there is the question of why you're running the motors and switching LED on and off in setup() which only runs once when the Arduino is powered on. That routine is usually used just to set up (as the name suggests) some default conditions and do one-off things like enabling Serial, the drivers etc. But since you have all that code in there what EXACTLY do the motors do at that point?

Can you please post a diagram showing exactly how you have the motor driver and sensors wired to the Arduino, including power and ground connections. I'm sure you have checked that it is wired as you intended but unfortunately that may not be how it actually needs to be wired.

Steve




padawan

Thanks for the reply! I just got the sensor on Amazon and didn't realize it had a library. It looks like it is getting the distances right.
That whole weird setup thing was just so I could see exactly how far my sketch got before it started not working like I wanted. The motors run forward for a second, stop for a second, then run backward for a second. That part seems to be working fine.
Here's how it's all wired:
Sorry for the rough diagram! Hope it's not too hard to read.
-p.

TomGeorge

Everything runs on smoke, let the smoke out, it stops running....

slipstick

The diagram is a little confusing because the motors are not shown where the code says they should be.

But I'm guessing that the main problems with your code in loop() are :

1. You're normally only setting half the motor control pins e.g. you set in2 and in4 HIGH but ignore in1 and in3 so leaving their values at whatever they were last set at. The motor driver will throw up its hands in disgust if you set both Go Back and Go Forward to HIGH for a single motor. Basically to use that motor driver safely you have to set both motor pins for each motor every time. You're getting away with it once in setup() but not when it's looping round. You may have spotted this more easily if you'd used more meaningful variable names like leftReverse, rightForward instead of in1, 2, 3 etc.

2. The other thing is that to control motor speed with PWM you use analogWrite() to the PWM pins not digitalWrite(). The 2nd parameter to digitalWrite() is HIGH or LOW so setting it to 100 doesn't make much sense.

Steve

padawan

Thanks for replying! My battery pack is just a 6 AA pack with a switch, and six 1.5 volt batteries.

Should I just use HIGH for PWM or should I replace digitalWrite() with analogWrite()?

So I  need to make sure that I'm not telling my motor driver to go forwards and backwards at the same time? I thought I had checked for that and used digitalWrite(whatever it was, LOW) before turning the opposite pin HIGH. Is there some sort of problem because of the fact that it's looping and I need to digitalWrite everything LOW before starting the loop again? Or are the values only set LOW in a certain function and go back to HIGH when it's over?

Thanks so much for helping!
-p.

slipstick

Thanks for replying! My battery pack is just a 6 AA pack with a switch, and six 1.5 volt batteries.

Should I just use HIGH for PWM or should I replace digitalWrite() with analogWrite()?

So I  need to make sure that I'm not telling my motor driver to go forwards and backwards at the same time? I thought I had checked for that and used digitalWrite(whatever it was, LOW) before turning the opposite pin HIGH. Is there some sort of problem because of the fact that it's looping and I need to digitalWrite everything LOW before starting the loop again? Or are the values only set LOW in a certain function and go back to HIGH when it's over?
If the batteries are alkaline you should be o.k. Carbon-zinc could be a problem delivering enough current.

If you don't use analogWrite() you don't get any PWM so no control over the speed. Just OFF or ON at full speed. If that's what you want then you should be o.k.

As for the rest I simply can't follow what it's trying to do so you may be right that you have it covered. To me it looks as if you go forward then check the sensor and if there's nothing within 10cm you reverse a bit and then go straight forward again. Should that test perhaps have been if (cm < 10)? I also can't see why the last thing in the loop sets it drive forward and then at the start of the loop before any checking you set the same conditions again...but perhaps there is some reason for it that I just haven't noticed.
 
Steve

TomGeorge

Hi,
How are you using your ultrasonic device, you need 4 wires, two for supply and one for  "ping" and the other for "echo".



http://howtomechatronics.com/tutorials/arduino/ultrasonic-sensor-hc-sr04/

Edit. Sorry you are using the Make Sonic unit.

How are you powering your UNO, you only show the battery powering the driver?

Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

TomGeorge

Hi,
If you look at the schematic of the driver,you will see your 6V battery pack is going to L298 to power the motors as well as a 7805 , 5V, regulator.
However the regulator can only output 5V, if the input volts is about 7.5V or higher, your 6V will not be enough and the L298 IC will not be getting 5V to perform properly.

Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

TomGeorge

Hi,
I have put your circuit into a CAD.
Your diag is good, lots of labels which makes it easy to follow, just needs some layout logic, you will find this with practice in your diagram.


Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

padawan

Thanks for all the help, Steve and Tom! I didn't write all of the code so I don't know why it sets conditions at the end of the loop and again at the start without checking. Maybe I should just go back and write the code more or less from scratch.

I have a nine volt battery attached to the Uno by a battery clip, which is how the original project did it.

I don't have much practice reading schematics! So do I need to add more voltage and bring it up to 7.5 volts? If so please advise how. Sorry I'm such a noob!
-p.
Hi,
If you look at the schematic of the driver,you will see your 6V battery pack is going to L298 to power the motors as well as a 7805 , 5V, regulator.
However the regulator can only output 5V, if the input volts is about 7.5V or higher, your 6V will not be enough and the L298 IC will not be getting 5V to perform properly.

Tom... :)

padawan

Hi
My battery pack has 6 1.5v alkaline batteries, which should mean it's outputting 9v, right? So shouldn't that be enough, since it's above 7.5v? I'm probably missing something obvious, but I have no idea what.

I added more comments to my code and changed the digitalWrite(pwm?, 100); to digitalWrite(pwm?, HIGH);. My robot's still doing the exact same thing as before. Here's the new code:
Code: [Select]
[code]
const int in1 = 10;//left backward
const int in2 = 9;//left forward
const int pwm2 = 6;//right motor
const int in3 = 5;// right backward
const int in4 = 4;// right forward
const int led = 13;
const int pingPin = 7;

 
void setup() {
  pinMode (pwm1, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(pwm2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(led, OUTPUT);
 
  digitalWrite(in2, HIGH);//left motor forward
  digitalWrite(pwm1, HIGH);
  digitalWrite(in4, HIGH);//right motor forward
  digitalWrite(pwm2, HIGH);
  delay(1000);
  digitalWrite(in2, LOW);
  digitalWrite(pwm1, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(pwm2, LOW);
  delay(1000);
  digitalWrite(in1, HIGH);// left motor backwards
  digitalWrite(pwm1, HIGH);
  digitalWrite(in3, HIGH);//right motor backwards
  digitalWrite(pwm2, HIGH);
  delay(1000);
  digitalWrite(in1, LOW);
  digitalWrite(pwm1, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(pwm2, LOW);
 
  digitalWrite(led, HIGH);//led on for five seconds
  delay(5000);
  digitalWrite(led, LOW);// led off
  Serial.begin(9600);// stops doing what i want it to do here
}
void loop(){
  digitalWrite(in2, HIGH);//left motor forwards
  digitalWrite(pwm1, HIGH);
  digitalWrite(in4, HIGH);//left motor forwards
  digitalWrite(pwm2, HIGH);
  uint8_t i;

  long duration, inches, cm;
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin,HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
 
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  cm = microsecondsToCentimeters(duration);
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  if (cm >10){
    digitalWrite(in2, LOW);//left motor, backwards
    digitalWrite(pwm1, LOW);
    digitalWrite(in1, HIGH);
    digitalWrite(pwm1, HIGH);

  //for (i=0; i<255; i++){
 // delay(10);}
 
  digitalWrite(in4, LOW);// right motor, backwards
  digitalWrite(pwm2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(pwm2, HIGH);
  for (i=0; i<255; i++){
  delay(10);}
 
digitalWrite(in3, LOW);//start both motors forward again
digitalWrite(in4, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in1, HIGH);
delay(30);
  }
  else{
    digitalWrite(in2, HIGH);//keep going straight
    digitalWrite(pwm1, HIGH);
    digitalWrite(in4, HIGH);
    digitalWrite(pwm2, HIGH);
  }
  }
  long microsecondsToCentimeters(long microseconds)
  {
 
    return microseconds / 29/ 2;}
 
 
[/code]
Should I just go back and write the code from scratch? It might be easier.
-p.

wildbill

A rewrite may not be necessary, but I'd suggest you write a series of much simpler sketches to assure yourself that the hardware's ok. Just run the motors forward for five seconds and then back for example.

slipstick

It may just be me but I would be expecting you always to set BOTH input pins for the motor driver whenever you want a motor to do something. They should be either HIGH-LOW for one direction or LOW-HIGH for the other. And then you set the PWM pin HIGH for full speed. And when you want the motor to stop you set the PWM pin to LOW. There are too many places where you're just relying on pins staying set to sensible values.

There are also places where you set one input pin for a motor then set the PWM pin to LOW then set the other input pin then set PWM to HIGH. I don't understand what that is supposed to do.

And then there are those places where you set the input pins but don't send any PWM command.

Perhaps it is just me being simpleminded but I like 3 digitalWrites (in1, in2 & pwm1 or in3, in4 and pwm2) each time a motor is supposed to run. You may well be able to follow what state everything is in but I'm afraid I get completely confused about what is supposed to be happening.

Late edit: the other thing I've only just spotted is that you are changing direction without stopping the motors whereas in the setup() code that seems to work the motors are stopped and then reversed. I don't know how well that motor driver copes with trying to to change direction while the motors are still going at full speed but that may be another thing worth looking at.

BTW your 6AA batteries should be fine.

Steve

padawan

I'm so sorry I didn't have time to reply sooner.

@wildbill it's late here so I won't run any tests right now but thanks for the idea and I'll do it. If I find any hardware issues I'll post them.

@slipstick So you mean like at the start of void loop() where I only set in2 and in4 I should also set in1 and in3 again even though I already used digitalWrite() in setup? Does it only work within that function and the fact that I didn't reset makes my motor driver "throw up its hands in disgust" and mess up the rest of the code? I went through my code to check for those errors and added comments where I added a line. But since it's really too late to be writing in code or normal English for that matter I probably missed some. I can't test to see if my robot works now because it's kind of loud and everyone else is being smart and sleeping. Sorry if my post is incoherent. I can't even tell because I'm not sure how awake I am. Here's the revised code:
Code: [Select]
const int pwm1 = 11;//left motor 
const int in1 = 10;//left backward
const int in2 = 9;//left forward
const int pwm2 = 6;//right motor
const int in3 = 5;// right backward
const int in4 = 4;// right forward
const int led = 13;
const int pingPin = 7;

 
void setup() {
  pinMode (pwm1, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(pwm2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(led, OUTPUT);
 
  digitalWrite(in2, HIGH);//left motor forward
  digitalWrite(pwm1, HIGH);
  digitalWrite(in4, HIGH);//right motor forward
  digitalWrite(pwm2, HIGH);
  delay(1000);
  digitalWrite(in2, LOW);
  digitalWrite(pwm1, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(pwm2, LOW);
  delay(1000);
  digitalWrite(in1, HIGH);// left motor backwards
  digitalWrite(pwm1, HIGH);
  digitalWrite(in3, HIGH);//right motor backwards
  digitalWrite(pwm2, HIGH);
  delay(1000);
  digitalWrite(in1, LOW);
  digitalWrite(pwm1, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(pwm2, LOW);
 
  digitalWrite(led, HIGH);//led on for five seconds
  delay(5000);
  digitalWrite(led, LOW);// led off
  Serial.begin(9600);// stops doing what i want it to do here
}
void loop(){
  digitalWrite(in1, LOW);//added
  digitalWrite(pwm1, LOW);//added
  digitalWrite(in3, LOW);//added
  digitalWrite(pwm2, LOW);//added
  digitalWrite(in2, HIGH);//left motor forwards
  digitalWrite(pwm1, HIGH);
  digitalWrite(in4, HIGH);//left edit that should be right motor forwards
  digitalWrite(pwm2, HIGH);
  uint8_t i;

  long duration, inches, cm;
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin,HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
 
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  cm = microsecondsToCentimeters(duration);
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  if (cm >10){
    digitalWrite(in1,LOW);//added
    digitalWrite(in2, LOW);//left motor, backwards
    digitalWrite(pwm1, LOW);
    digitalWrite(in1, HIGH);
    digitalWrite(pwm1, HIGH);

  //for (i=0; i<255; i++){ i can't even remember why i commented this out. any ideas?
 // delay(10);}
  digitalWrite(in3,LOW);//added
  digitalWrite(in4, LOW);// right motor, backwards
  digitalWrite(pwm2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(pwm2, HIGH);
  for (i=0; i<255; i++){
  delay(10);}
 
digitalWrite(in3, LOW);//start both motors forward again
digitalWrite(pwm2,LOW);// added is this one of the parts you were talking about?
digitalWrite(in4, HIGH);
digitalWrite(pwm2, HIGH);//added
digitalWrite(in2, LOW);
digitalWrite(pwm1,LOW);//added
digitalWrite(in1, HIGH);
digitalWrite(pwm1, HIGH);//added
delay(30);
  }
  else{
    digitalWrite(in1, LOW);//added
    digitalWrite(pwm1, LOW);//added
    digitalWrite(in2, HIGH);//keep going straight
    digitalWrite(pwm1, HIGH);
    digitalWrite(in3, LOW);//added
    digitalWrite(pwm2, LOW);//added
    digitalWrite(in4, HIGH);
    digitalWrite(pwm2, HIGH);
  }
  }
  long microsecondsToCentimeters(long microseconds)
  {
 
    return microseconds / 29/ 2;}
 
 

I'll test my robot tomorrow or actually today and post the results.
-p.

Go Up