Help with code for NanoATMega328 / 2 x DC Motors / 9g Micro Servo / HCSR04 Ultrasonic Detector

Hi;

I have built an obstacle avoidance bot for a School Robotics Club I had the motors running using a demo mode (spin left the right) but have just connected a servo and an HCSR04 Ultrasonic Detector and I need some help with the code to get it up and running.

The Bot uses:

Chassis with 2 x Geared DC Motors

L298N Dual Motor Controller

Arduino Clone Nano v3.0 ATMega328 (CH340G Chip)

Micro Servo (3 Wire)

HCSR04 Ultrasonic Detector (4 Pin Gnd, VCC, Echo, Trigger)

I connected up the motors and got them running using this web page and although I can find info on code for the servo and detector I cannot work out how to link it all together and download it to the Nano.

 

The detector is mounted on the servo , so I need the servo to pan left and right and avoid obstacles when detected. 

Any help would be appreciated as I want to be able to show my Club members what it does and how it does it, they are about to start building their own using the same parts.

Thanks

 

 

Search for “servo sweep” arduino

There’s an example on the arduino playground. Then just modify to gather info from hcsr04 at 60°, 90°, 120°; store it in three variables, compare and head the robot toward longest reading; go forward until obstacle detected.

Ok;With the help here and a

Ok;

With the help here and a little more research I have managed to cobble together the following code which sweeps the servo from 0 to 180 degrees constantly, and also sends and recieves an ultrasonic ping and prints the results to a serial monitor.

This has been tested and works.

How do I:

1. Change the sweep to less of an angle and take results at 60, 90 and 120 as stated by silux above and store them in a varible.

2. Add code to drive the DC motors forward and react when an obstacle is detected based on the distance in the variable and move toward the longest heading?

 

#include <Servo.h> //Servo Sweep 

 

 

#define trigPin 11 //Ultrasonic Dsitance Sensing 

#define echoPin 12

 

Servo myservo;

 

int pos = 0;

 

void setup()

{

  myservo.attach(4); //attaches the servo to pin 4

  Serial.begin (9600);

  pinMode(trigPin, OUTPUT);

  pinMode(echoPin, INPUT);

}

 

void loop()

{

  for(pos = 0; pos < 180; pos += 1) // sends servo from 0 to 180 degrees

  {

    myservo.write(pos);

    delay(15);

  }

  for(pos = 180; pos>=1; pos-=1)

  {

    myservo.write(pos);

    delay(15);

  }

{

  int duration, distance;

  digitalWrite(trigPin, HIGH);

  delayMicroseconds(1000);

  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  distance = (duration/2) /29.1;

  Serial.print(distance);

  Serial.println(" cm");

  delay(500);

 

}

}

Your code can not produce the output you are expecting.

Your code, as posted, sweeps the servo from 0 to 180 and back to 0, then, it takes a reading via the code you, for no reason, placed in a block all by itself. The code to do what you are currently attempting to code follows.

 

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <Servo.h> //Servo Sweep 

#define trigPin 11 //Ultrasonic Dsitance Sensing
#define echoPin 12

Servo myservo;

int pos = 0;

void setup() {
myservo.attach(4); //attaches the servo to pin 4
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop() {
int rangeToTarget;
for(pos = 0; pos < 180; pos += 1) {// sends servo from 0 to 180 degrees
rangeToTarget = getReading();
myservo.write(pos);
delay(15);
}
for(pos = 180; pos>=1; pos-=1) {
rangeToTarget = getReading();
myservo.write(pos);
delay(15);
}
}

int getReading() {
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) /29.1;
Serial.print(distance);
Serial.println(" cm");
delay(500);
return distance;
}


To do what you are asking I would probably do something like:

 

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <Servo.h> //Servo Sweep 

#define trigPin 11 //Ultrasonic Dsitance Sensing
#define echoPin 12

Servo myservo;

int pos = 0;

void setup() {
myservo.attach(4); //attaches the servo to pin 4
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop() {
int rangeToTarget;
for(pos = 60; pos < 120; pos += 30) {// sends servo from 0 to 180 degrees
rangeToTarget = getReading();
myservo.write(pos);
}
for(pos = 120; pos >= 60; pos-= 30) {
rangeToTarget = getReading();
myservo.write(pos);
}
}

int getReading() {
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) /29.1;
Serial.print(distance);
Serial.println(" cm");
delay(500);
return distance;
}

birdmun;Thanks for your

birdmun;

Thanks for your assistance, as a beginner its is really helpful.

The reason for the error was that I followed this tutorial to get a reading from the sensor and a different tutorial to sweep the servo :slight_smile:

I tried each piece of code separately first the detctor code to print to the Serial Monitor and this worked great, however I then created a new Sketch screen and entered the code to sweep the servo, this also worked.

I then put the two sets of coded together but did not test it :frowning: LOL 

I’ll copy in your code and give it a go.

What I am looking for / working on now is adding code to drive the motors and avoid obstacles based on what the sensor sees.

I am using an L298N Motor Driver Board and an Nano ATMega228 processor.

Just uploaded it to the Nano

Just uploaded it to the Nano and although the Sweep is a little Jerky it works fine.

Your a start,now to combine the Motors :slight_smile:

Sadly,

I was a bit too fast to post the second batch of code. The reason it is “Jerky” is because it of the i += 30. The other issue with the second batch of code is there is really no storing of the data coming back from the sensor. I could spend some time with my second batch and get it working better for you, but, how are you supposed to learn?

Fully understand, making

Fully understand, making mistakes expands the mind, that’s what we keep telling our pupils (positive motivation).

I am playing with the code now, having some problems getting the sensors and the motors to run at the same time.

 

Here’s my latest code, when

Here’s my latest code, when run the servo moves to the front, does a sweep and then only one motor drives.

When I download a different code to test just the motors both motors run fine.

However I have just amended my motor test code and added the Servo Sweep bit, only one of the motors run, I am starting to think this may be a power issue.

At the moment I have the Nano, Motor Driver, 2 x DV motors, servo and the detector all running from +5v supplied from a PP3 9v battery regulated to 5v using the L298N motor driver board.

With the kits that I am putting together there is a 4 x AA (6v) battery holder, should I add that and drive the servo separately?

#include <Servo.h> //Add the Servo library 

 

//Set the constants for the Left and Right Motor pins to avoid using non sensical names

#define LeftMotorSpeed 10

#define LeftMotorForward 9

#define LeftMotorBackward 8

#define RightMotorSpeed 5

#define RightMotorForward 7

#define RightMotorBackward 6

//Set the sensor trigger and echo pins

#define trigPin 11 

#define echoPin 12 

 

Servo myservo; //Name the servo

 

//int pos = 0; 

 

//Set unsigned integer variables to be used

unsigned int duration;

unsigned int distance;

unsigned int FrontDistance;

unsigned int LeftDistance;

unsigned int RightDistance;

unsigned int Time;

unsigned int CollisionCounter;

 

void setup() //This block happens once at startup

{

  Serial.begin (9600); //Included serial communication to show distances in serial monitor for demonstration purposes

  //Below set all the pin modes as OUTPUT as they will all be outputting data 

  pinMode(trigPin, OUTPUT);

  pinMode(echoPin, INPUT);

  pinMode(LeftMotorSpeed, OUTPUT);

  pinMode(LeftMotorForward, OUTPUT);

  pinMode(LeftMotorBackward, OUTPUT);

  pinMode(RightMotorSpeed, OUTPUT);

  pinMode(RightMotorForward, OUTPUT);

  pinMode(RightMotorBackward, OUTPUT);

  myservo.attach(4); //Attaches the servo to pin 4

}

 

void loop() 

{

  //int rangeToTarget;

  //for(pos = 60; pos < 120; pos += 30) {// sends servo from 30 to 120 degrees

    //rangeToTarget = getReading();

    //myservo.write(pos);

  myservo.write(90); //Set the servo to face front

  scan(); //Call the Scan() procedure to check for obtacles to the front

  FrontDistance = distance; //Whatever distance is returned by the Scan() procedure is set to the vaiable FrontDistance

  Serial.println(“Front distance = “); //Print routines for debugging

  Serial.print(distance); //Print routines for debugging 

  Serial.println(” cm”); //Print routines for debugging

  if(FrontDistance > 40 || FrontDistance ==0) //If anything in front is less than 40cm away move forward 

  {

   Forward();

  } 

   else //If there is an obstacle less than 40cm away stop and select a safe path

  {

    CollisionCounter = CollisionCounter +1;

    Stop();

    Select_Path();

   }

 

}

//  for(pos = 120; pos >= 60; pos-= 30) {

//    rangeToTarget = getReading();

//    myservo.write(pos);

//  }

//}

 

void Forward()                                    //This function tells the robot to go forward 

{

  Serial.println("");

  Serial.println(“Moving forward”);

  digitalWrite(LeftMotorForward, HIGH);

  digitalWrite(LeftMotorBackward, LOW);

  analogWrite(LeftMotorSpeed, 200);    //Set left motor speed to 200 out of 0-255

  digitalWrite(RightMotorForward, HIGH);

  digitalWrite(RightMotorBackward, LOW);

  analogWrite(RightMotorSpeed, 200);     //Set right motor speed to 200 out of 0-255

}

 

void Backward()                                  //This function tells the robot to move backward

{

  Serial.println("");

  Serial.println(“Moving backward”);

  digitalWrite(LeftMotorForward, LOW);

  digitalWrite(LeftMotorBackward, HIGH);

  digitalWrite(RightMotorForward, LOW);

  digitalWrite(RightMotorBackward, HIGH);

}

 

void Left()                                      //This function tells the robot to turn left

{

  Serial.println("");

  Serial.println(“Moving left”);

  digitalWrite(LeftMotorForward, LOW);

  digitalWrite(LeftMotorBackward, HIGH);

  digitalWrite(RightMotorForward, HIGH);

  digitalWrite(RightMotorBackward, LOW);

 

 

}

 

void Right()                                    //This function tells the robot to turn right

{

  Serial.println("");

  Serial.println(“Moving right”);

  digitalWrite(LeftMotorForward, HIGH);

  digitalWrite(LeftMotorBackward, LOW);

  digitalWrite(RightMotorForward, LOW);

  digitalWrite(RightMotorBackward, HIGH);

}

 

void Stop()                                     //This function tells the robot to stop moving

{

  Serial.println("");

  Serial.println(“Stopping”);

  digitalWrite(LeftMotorBackward, LOW);

  digitalWrite(LeftMotorForward, LOW);

  digitalWrite(RightMotorForward, LOW);

  digitalWrite(RightMotorBackward, LOW);

}

 

void scan() //This function tells the robot to scan for obstacles and set the variable distance  

{

  Serial.println("");

  Serial.println(“Scanning”);

  //int duration, distance; //Removed as these varoiables are set as global variable at the start of the program  

  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10); //Scan for 10 milliseconds?

  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  distance = (duration/2) /29.1;

  Serial.print(distance);

  Serial.println(" cm");

  delay(500);

  //return distance; //Removed as it was causing a problem

}

 

void Select_Path() //This procedure is called if there is an object directly ahead, it moves the servo left and right, calls the scan procedure and selects a safe path

{

  Serial.println(“There’s an obstacle!”);       //Obstacle deteced by the initial forward scan

  myservo.write(120);                           //Move the servo to the left 

  delay(1000);                                  //Wait half a second for the servo to get there, may need adjusting

  scan();                                       //Call the scan procedure 

  LeftDistance = distance;                      //Set the variable LeftDistance to the distance returned from the scan

  Serial.println("Left distance = ");

  Serial.print(distance);

  myservo.write(60);                            //Move the servo to the right

  delay(1000);                                  //Wait half a second for the servo to get there, may need adjusting

  scan();                                       //Call the scan procedure

  RightDistance = distance;                     //Set the variable RightDistance to the distance returned from the scan

  Serial.println("Right distance = ");

  Serial.print(distance);

  if(abs(RightDistance - LeftDistance) < 5)     //Some sort of safety routine

  {

    Backward();                                 //Go to the moveBackward function

    delay(200);                                 //Pause the program for 200 milliseconds to let the robot reverse

    Right();                                    //Go to the moveRight function

    delay(100);                                 //Pause the program for 200 milliseconds to let the robot turn right

  }

  else if(RightDistance < LeftDistance)         //If the distance to an obstacle on the right is less than that on the left then…

  {

    Left();                                      //Go to the moveLeft function

    delay(100);                                  //Pause the program for half a second to let the robot turn

  }

  else if(LeftDistance < RightDistance)         //Else if the distance on the left is less than that on the right then…

  {

    Right();                                     //Go to the moveRight function

    delay(100);                                  //Pause the program for half a second to let the robot turn

  }

}

 

I have checked and double

I have checked and double checked the wiring and made a few adjustments to the power, the Nano now gets 9v from an alkaline PP3 to VIn and the Motor Driver (and 2 x DC Motors) gets 10.5v from 7AA Alkaline Batteries.

The servo now operates correctly i.e it scans forward initially and if nothing is in front it tells the motors to go forward but still only 1 x motor is operating. When it detects an obstacle forwad (my hand as its on the bench with the wheels off of the ground) it stops the motor and scans left and right.

The motor that operates is whizzing round at a rapid rate of knots as well (a lot faster than before) so there is plent of power (I guess).

Here is the code, I have commented out the turn left and right bits but the forward and backward should still spin both motors? I have also commented out some of the code that used names for pins and inserted pin assignment names for debugging. 

If anyone can help sort this out I would appreciated it, I just want to see it work before I go and spend £30 on rechargables and a charger!!


#include <Servo.h> //Add the Servo library 

//Set the constants for the Left and Right Motor pins to avoid using non sensical names (Commented out to check pin outs)

//#define LeftMotorSpeed 10

//#define LeftMotorForward 9

//#define LeftMotorBackward 8

//#define RightMotorSpeed 5

//#define RightMotorForward 7

//#define RightMotorBackward 6

//Set the sensor trigger and echo pins

 

#define trigPin 12 

#define echoPin 13 

int enA = 10; 

int in1 = 9; 

int in2 = 8; 

// motor two 

int enB = 5; 

int in3 = 7; 

int in4 = 6;

 

Servo myservo; //Name the servo

 

//int pos = 0; 

 

//Set unsigned integer variables to be used

unsigned int duration;

unsigned int distance;

unsigned int FrontDistance;

unsigned int LeftDistance;

unsigned int RightDistance;

unsigned int Time;

unsigned int CollisionCounter;

 

void setup() //This block happens once at startup

{

  Serial.begin (9600); //Included serial communication to show distances in serial monitor for demonstration purposes

  //Below set all the pin modes as OUTPUT as they will all be outputting data 

  pinMode(trigPin, OUTPUT);

  pinMode(echoPin, INPUT);

  pinMode(enA, OUTPUT);   

  pinMode(enB, OUTPUT);   

  pinMode(in1, OUTPUT);   

  pinMode(in2, OUTPUT);   

  pinMode(in3, OUTPUT);   

  pinMode(in4, OUTPUT); 

 

  //pinMode(LeftMotorSpeed, OUTPUT);

  //pinMode(LeftMotorForward, OUTPUT);

  //pinMode(LeftMotorBackward, OUTPUT);

  //pinMode(RightMotorSpeed, OUTPUT);

  //pinMode(RightMotorForward, OUTPUT);

  //pinMode(RightMotorBackward, OUTPUT);

  myservo.attach(4); //Attaches the servo to pin 4

}

 

void loop() 

{

  //int rangeToTarget;

  //for(pos = 60; pos < 120; pos += 30) {// sends servo from 30 to 120 degrees

    //rangeToTarget = getReading();

    //myservo.write(pos);

  myservo.write(90); //Set the servo to face front

  scan(); //Call the Scan() procedure to check for obtacles to the front

  FrontDistance = distance; //Whatever distance is returned by the Scan() procedure is set to the vaiable FrontDistance

  Serial.println(“Front distance = “); //Print routines for debugging

  Serial.print(distance); //Print routines for debugging 

  Serial.println(” cm”); //Print routines for debugging

  if(FrontDistance > 40 || FrontDistance ==0) //If anything in front is less than 40cm away move forward 

  {

   Forward();

  } 

   else //If there is an obstacle less than 40cm away stop and select a safe path

  {

    CollisionCounter = CollisionCounter +1;

    Stop();

    Select_Path();

   }

 

}

//  for(pos = 120; pos >= 60; pos-= 30) {

//    rangeToTarget = getReading();

//    myservo.write(pos);

//  }

//}

 

void Forward()                                    //This function tells the robot to go forward 

{

  Serial.println("");

  Serial.println(“Moving forward”);

  // turn on motor A   

  digitalWrite(in1, HIGH);   

  digitalWrite(in2, LOW);   

  // set speed to 200 out of possible range 0~255

  analogWrite(enA, 200);   

  // turn on motor B   

  digitalWrite(in3, LOW);   

  digitalWrite(in4, HIGH);   

  // set speed to 200 out of possible range 0~255   

  analogWrite(enB, 200);   

  delay(2000);

  //digitalWrite(LeftMotorForward, HIGH);

  //digitalWrite(LeftMotorBackward, LOW);

  //analogWrite(LeftMotorSpeed, 200);    //Set left motor speed to 200 out of 0-255

 

 

  //digitalWrite(RightMotorForward, HIGH);

  //digitalWrite(RightMotorBackward, LOW);

  //analogWrite(RightMotorSpeed, 200);     //Set right motor speed to 200 out of 0-255

}

 

void Backward()                                  //This function tells the robot to move backward

{

  Serial.println("");

  Serial.println(“Moving backward”);

  Serial.println("");

  Serial.println(“Moving forward”);

  // turn on motor A   

  digitalWrite(in1, LOW);   

  digitalWrite(in2, HIGH);   

  // set speed to 200 out of possible range 0~255

  analogWrite(enA, 200);   

  // turn on motor B   

  digitalWrite(in3, HIGH);   

  digitalWrite(in4, LOW);   

  // set speed to 200 out of possible range 0~255   

  analogWrite(enB, 200);   

  delay(2000);

 

 

  //digitalWrite(LeftMotorForward, LOW);

  //digitalWrite(LeftMotorBackward, HIGH);

  //digitalWrite(RightMotorForward, LOW);

  //digitalWrite(RightMotorBackward, HIGH);

}

 

void Left()                                      //This function tells the robot to turn left

{

  Serial.println("");

  Serial.println(“Moving left”);

 

 

 

  //digitalWrite(LeftMotorForward, LOW);

  //digitalWrite(LeftMotorBackward, HIGH);

  //digitalWrite(RightMotorForward, HIGH);

  //digitalWrite(RightMotorBackward, LOW);

 

 

}

 

void Right()                                    //This function tells the robot to turn right

{

  Serial.println("");

  Serial.println(“Moving right”);

 

 

 

  //digitalWrite(LeftMotorForward, HIGH);

  //digitalWrite(LeftMotorBackward, LOW);

  //digitalWrite(RightMotorForward, LOW);

  //digitalWrite(RightMotorBackward, HIGH);

}

 

void Stop()                                     //This function tells the robot to stop moving

{

  Serial.println("");

  Serial.println(“Stopping”);

   // now turn off motors   

  digitalWrite(in1, LOW);   

  digitalWrite(in2, LOW);     

  digitalWrite(in3, LOW);   

  digitalWrite(in4, LOW);

 

 

  //digitalWrite(LeftMotorBackward, LOW);

  //digitalWrite(LeftMotorForward, LOW);

  //digitalWrite(RightMotorForward, LOW);

  //digitalWrite(RightMotorBackward, LOW);

}

 

void scan() //This function tells the robot to scan for obstacles and set the variable distance  

{

  Serial.println("");

  Serial.println(“Scanning”);

  //int duration, distance; //Removed as these varoiables are set as global variable at the start of the program  

  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10); //Scan for 10 milliseconds?

  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);

  distance = (duration/2) /29.1;

  Serial.print(distance);

  Serial.println(" cm");

  delay(500);

  //return distance; //Removed as it was causing a problem

}

 

void Select_Path() //This procedure is called if there is an object directly ahead, it moves the servo left and right, calls the scan procedure and selects a safe path

{

  Serial.println(“There’s an obstacle!”);       //Obstacle deteced by the initial forward scan

  myservo.write(120);                           //Move the servo to the left 

  delay(1000);                                  //Wait half a second for the servo to get there, may need adjusting

  scan();                                       //Call the scan procedure 

  LeftDistance = distance;                      //Set the variable LeftDistance to the distance returned from the scan

  Serial.println("Left distance = ");

  Serial.print(distance);

  myservo.write(60);                            //Move the servo to the right

  delay(1000);                                  //Wait half a second for the servo to get there, may need adjusting

  scan();                                       //Call the scan procedure

  RightDistance = distance;                     //Set the variable RightDistance to the distance returned from the scan

  Serial.println("Right distance = ");

  Serial.print(distance);

  if(abs(RightDistance - LeftDistance) < 5)     //Some sort of safety routine

  {

    Backward();                                 //Go to the moveBackward function

    delay(200);                                 //Pause the program for 200 milliseconds to let the robot reverse

    Right();                                    //Go to the moveRight function

    delay(100);                                 //Pause the program for 200 milliseconds to let the robot turn right

  }

  else if(RightDistance < LeftDistance)         //If the distance to an obstacle on the right is less than that on the left then…

  {

    Left();                                      //Go to the moveLeft function

    delay(100);                                  //Pause the program for half a second to let the robot turn

  }

  else if(LeftDistance < RightDistance)         //Else if the distance on the left is less than that on the right then…

  {

    Right();                                     //Go to the moveRight function

    delay(100);                                  //Pause the program for half a second to let the robot turn

  }

}

 

First up

Learn how to post code here. You can not just reasonablly just copy and paste code in to the text box. I or anyone else will spend minutes of time (or they won’t and probably will not even assist) getting rid of all the extraneous whitespace that is shoved in to the code.

Different note. You have mentioned only one motor turning. Maybe I have missed the complete comment, but, do you mean only the left or right motor will turn at any given time, or, only the right motor for example will turn no matter what the program is telling the motor driver?

Sorry about the code, the

Sorry about the code, the layout on this forum is very different to others that I use especilly for code, just tried to edit previous posts but I can only edit the very top level, I cannot edit any repiles that I have submitted?

Ref the motor, I am working on a car at the moment (Austin Mini Restoration) so i’ll check whether its the left or the right motor, but to clarify on one of the two motors is turning, it appears to be functioning correctly, i.e it spins forward then if I block the sensor the same motor stops the sensor sweeps left and right and the motor backs up (if I keep my hand in front of the sensor) when I remove my hand and the sensor has done the Check_Path() procedure again the same motor spins forward again.

What I also thought of doing was (in the code) to change the In pins around and see if the other motor spins instead of the one that is?  

 

Ok so physically the motor

Ok so physically the motor that is running is the right motor and its the one connected to the right hand side of the Motor Driver if you have the Heatsink furthest away from you. The Motor Driver outputs connected to the motor are in3 and in4, I have just commented out in1 and in2 in the code (which are annoated as Motor A) and re-uploaded the code to the Nano and then switched it on. The RH Motor still runs.

I then commented out in3 and in4 to see if this would allow Motor A the LH Motor on in1 and in2 to operate, it did not?


Link for learning how to post code

https://www.robotshop.com/letsmakerobots/node/33446

If you hook up the motor
If you hook up the motor that is not running to about 2-6v directly (2-4 NiMH alkaline batteries) without the motor controller, does the motor run then?

As for commenting out in3 and in4, does the motor run or not?

If I upload a motor demo

If I upload a motor demo program that is designed to just run both motors forwards and backwards then both motors run fine. Its my obstacle avoidance code that is the problem, maybe some conflict with the Nano running 2 x motors, 1 x servo and a detector, it should be capable of this?

 

 

**Made Some Progress De-Bugging **

OK so I have been doing some de-bugging, I have found the problem but cannot fix it.

I started fresh and setup some code to run the motors and detector without the servo, the detector checks front distance only and is nothing in front or more that 50cm BOTH motors spin forward, if I put my hand in front of the detector the motors spin backwards.

So up to now all is fine.

I then added the code to include the servo, it is declared as myservo and attached to pin 4 on the Nano, all I have done is set the servo to the forward position (90). When I upload and run this code only the RH motor turns!!

So the problem appears to be when the servo is added, when it is it stops one of the motors (the LH one) from working.

The first piece of code works (without the servo), the second code introduces the servo and causes the LH motor to stop workiing.

 

#define trigPin 11 
#define echoPin 12

// connect motor controller pins to Arduino digital pins 
// motor one 
int enA = 10;
int in1 = 9;
int in2 = 8;
// motor two 
int enB = 5;
int in3 = 7;
int in4 = 6;

void setup()
{   
// set all the motor control pins to outputs   
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
//Do the ultrasonic
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

void loop()
{   
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) /29.1;
  Serial.print(distance);
  Serial.println(" cm");
  delay(500);
  if(distance >= 50)
   {
   Forward();   
   }
   else
   {
   Backward();   
   }
}

void Forward()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

void Backward()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

NEXT PROGRAM

#define trigPin 11 
#define echoPin 12
#include <Servo.h>

// connect motor controller pins to Arduino digital pins 
// motor one 
int enA = 10;
int in1 = 9;
int in2 = 8;
// motor two 
int enB = 5;
int in3 = 7;
int in4 = 6;
Servo myservo;

void setup()
{   
// set all the motor control pins to outputs   
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
//Do the ultrasonic
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  myservo.attach(2);

void loop()
{   
  myservo.write(90);
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) /29.1;
  Serial.print(distance);
  Serial.println(" cm");
  delay(500);
  if(distance >= 50)
   {
   Forward();   
   }
   else
   {
   Backward();   
   }
}

void Forward()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

void Backward()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

Motor Problem

Hi,

I think that you're motor problem is caused by a conflict with the servo library.

Quoted from the Servo library documentation

On boards other than the Mega, use of the library disables analogWrite() (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins.

You need another pin for the PWM for that motor.

You are an absolute diamond,

You are an absolute diamond, from your suggestion I moved the Inputs from D9 and D10 and moved them to D3 and D4.

WIth my test code that I created both motors now run :slight_smile: but with my more complex code whilst both motors now run, the LH one is very very slow. Maybe the power is still an issue? Its now running off of a 9v 500mA mains transformer, I thought it was 12v, may have another to test.

Here is a pic of the circuit (never used Fritzing before but what a fantastic product).

Obsracle_Avoidance.png

Here's the amended code for the test that works and below is the code that I am having trouble with:
#define trigPin 11 
#define echoPin 12
#include <Servo.h>

// connect motor controller pins to Arduino digital pins 
// motor one 
int enA = 3;
int in1 = 4;
int in2 = 8;
// motor two 
int enB = 5;
int in3 = 7;
int in4 = 6;
Servo myservo;

void setup()
{   
// set all the motor control pins to outputs   
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
//Do the ultrasonic
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  myservo.attach(2);

void loop()
{   
  myservo.write(90);
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) /29.1;
  Serial.print(distance);
  Serial.println(" cm");
  delay(500);
  if(distance >= 50)
   {
   Forward();   
   }
   else
   {
   Backward();   
   }
}

void Forward()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

void Backward()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);

HERES THE SECOND PROGRAM THAT IS CAUSING TROUBLE:


#define trigPin 11 
#define echoPin 12 
#include <Servo.h> //Add the Servo library

//Connect motor controller pins to Arduino digital pins
//Right Motor 
int enA = 3;
int in1 = 4;
int in2 = 8;
//Left Motor 
int enB = 5;
int in3 = 7;
int in4 = 6;
Servo myservo;

//Set unsigned integer variables to be used
unsigned int duration;
unsigned int distance;
unsigned int FrontDistance;
unsigned int LeftDistance;
unsigned int RightDistance;
unsigned int Time;
unsigned int CollisionCounter;

void setup() //This block happens once at startup
{
//Below set all the pin modes as OUTPUT as they will all be outputting data 
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
//Included serial communication to show distances in serial monitor for demonstration purposes
  Serial.begin (9600);
  myservo.attach(4); //Attaches the servo to pin 4
}

void loop()
{
  myservo.write(90); //Set the servo to face front
  scan(); //Call the Scan() procedure to check for obtacles to the front
  FrontDistance = distance; //Whatever distance is returned by the Scan() procedure is set to the vaiable FrontDistance
  Serial.println(“Front distance = “); //Print routines for debugging
  Serial.print(distance); //Print routines for debugging
  Serial.println(” cm”); //Print routines for debugging
  if(FrontDistance > 40 || FrontDistance ==0) //If anything in front is less than 40cm away move forward
  {
   Forward();
  } 
   else //If there is an obstacle less than 40cm away stop and select a safe path
  {
    CollisionCounter = CollisionCounter +1;
    Stop();
    Select_Path();
   }    
}

void Forward() //This function tells the robot to go forward
{
  Serial.println("");
  Serial.println(“Moving forward”);
  // turn on left motor
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  // set speed out of possible range 0~255
  analogWrite(enA, 200);
  // turn on right motor
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  // set speed out of possible range 0~255
  analogWrite(enB, 200);
  delay(200);
}

void Backward() //This function tells the robot to move backward
{
  Serial.println("");
  Serial.println(“Moving backward”);
  // turn on left motor
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  // set speed out of possible range 0~255
  analogWrite(enA, 200);
  // turn on right motor
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  // set speed out of possible range 0~255
  analogWrite(enB, 200);
  delay(200);
}

void Left() //This function tells the robot to turn left
{
  Serial.println("");
  Serial.println(“Moving left”);
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
// set speed out of possible range 0~255
  analogWrite(enA, 100);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
// set speed out of possible range 0~255   
  analogWrite(enB, 100);
  delay(200);
}

void Right() //This function tells the robot to turn right
{
  Serial.println("");
  Serial.println(“Moving right”);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
// set speed out of possible range 0~255
  analogWrite(enA, 100);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  analogWrite(enB, 100);
}

void Stop() //This function tells the robot to stop moving
{
  Serial.println("");
  Serial.println(“Stopping”);
// now turn off motors   
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}

void scan() //This function tells the robot to scan for obstacles and set the variable distance
{
  Serial.println("");
  Serial.println(“Scanning”);
//int duration, distance; //Removed as these varoiables are set as global variable at the start of the program  
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); //Scan for 10 milliseconds?
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) /29.1;
  Serial.print(distance);
  Serial.println(" cm");
  delay(500);
}

void Select_Path() //This procedure is called if there is an object directly ahead, it moves the servo left and right, calls the scan procedure and selects a safe path
{
  Serial.println(“There’s an obstacle!”); //Obstacle deteced by the initial forward scan
  myservo.write(120); //Move the servo to the left
  delay(150); //Wait half a second for the servo to get there, may need adjusting
  scan();                                       //Call the scan procedure
  LeftDistance = distance;                      //Set the variable LeftDistance to the distance returned from the scan
  Serial.println("Left distance = ");
  Serial.print(distance);
  myservo.write(60); //Move the servo to the right
  delay(100); //Wait half a second for the servo to get there, may need adjusting
  scan();                                       //Call the scan procedure
  RightDistance = distance;                     //Set the variable RightDistance to the distance returned from the scan
  Serial.println("Right distance = ");
  Serial.print(distance);
  if(abs(RightDistance - LeftDistance) < 5) //Some sort of safety routine
  {
    Backward();                                 //Go to the moveBackward function
    delay(200); //Pause the program for 200 milliseconds to let the robot reverse
    Right();                                    //Go to the moveRight function
    delay(100); //Pause the program for 200 milliseconds to let the robot turn right
  }
  else if(RightDistance < LeftDistance) //If the distance to an obstacle on the right is less than that on the left then…
  {
    Left();                                      //Go to the moveLeft function
    delay(100); //Pause the program for half a second to let the robot turn
  }
  else if(LeftDistance < RightDistance) //Else if the distance on the left is less than that on the right then…
  {
    Right();                                     //Go to the moveRight function
    delay(100); //Pause the program for half a second to let the robot turn
  }
}

No smoke detector batteries!
Please do not use 9v smoke detector batteries for motors!

Second, measure the voltage across each of the motors when they are running. I don’t know the stars on those motors, but I think they would need more than a half amp per motor to run, ehich means the Arduino is starved.

I believe it was mentioned before that 5-6 AA NIMH batteries or one 2S LiPo would be a much better choice I would use two packs, one for the batteries and one for the motors. I don’t know the details of powering an Arduino nano, but you can look it up in www.Arduino.cc as well as I can. If the pack can produce a decent amount of power at any given time, than one pack should suffice.