Code issue? Only one motor spins (instead of both)

Building my first robot and I put together a test code to see if my components are working together and I'm not sure what is wrong with it.

Arduino Uno - powered with 9v battery
L298N Motor Driver board - powered with 5v 700mA wall adapter.
TowerPro SG90 servo motor
Tamiya dual gearbox motors (type 130 brushed dc motors)

I didn't notice any wires hooked up incorrectly, so I am wondering if the problem is in my code. The code is supposed to spin the motors, then rotate a servo, then spin the motors again, then blink the onboard LED.

What actually happens: only one motor spins, the servo moves but is jerky instead of smooth and the onboard LED seems to blink during the test instead of once its completed.

Any ideas what is tripping me up?

#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
                // twelve servo objects can be created on most boards
 
int pos = 0;    // variable to store the servo position 

// 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;


// the setup function runs once when you press reset or power the board
void setup()
{
  myservo.attach(11);  // attaches the servo on pin 11 to the servo object
    
  // 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);

  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
}

void demoOne()
{
  // 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, HIGH);
  digitalWrite(in4, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now change motor directions
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH); 
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}

void demoTwo()
{
  // this function will run the motors across the range of possible speeds
  // note that maximum speed is determined by the motor itself and the operating voltage
  // the PWM values sent by analogWrite() are fractions of the maximum speed possible 
  // by your hardware
  // turn on motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH); 
  // accelerate from zero to maximum speed
  for (int i = 0; i < 256; i++)
  {
    analogWrite(enA, i);
    analogWrite(enB, i);
    delay(20);
  } 
  // decelerate from maximum speed to zero
  for (int i = 255; i >= 0; --i)
  {
    analogWrite(enA, i);
    analogWrite(enB, i);
    delay(20);
  } 
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);  
}

void ServoTest() 
{ 
  for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(20);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 180; pos>=0; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(5);                       // waits 15ms for the servo to reach the position 
  } 
} 

void Blinky() {
  for(int i = 0;i<=15;i+=1)
  {
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);              // wait for a second
    digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);  // wait for a second
  }
}


// the loop function runs over and over again forever
void loop()
{
  demoOne();
  delay(1000);
  ServoTest();
  delay(1000);
  demoTwo();
  delay(1000);
  Blinky();
  delay(7000);
}

Please show us a schematic.

int enA = 10;

The servo library disables PWM (analogWrite) on pins 9 and 10. I would put the servo on pin 10 and motor A enable on 11 (PWM). If pin 9 is used for digitalWrite only, then it is OK.

1 Like

I wonder are your power supplies adequate.

A PP3 type of 9v battery cannot produce enough current to drive an Arduino. Try a pack of 6 AA cells.

The L298 is very inefficient and will waste maybe 2 of your 5 volts. As well as which 700mA is probably not enough for 2 DC motors and a servo. I suggest a power supply that can output at least 2 Amps.

...R

I haven't learned how to draw more than very basic circuit schematics yet, so I apologize for my crayon diagram here:

Robin2, how do I calculate exactly how much voltage and current I need? Add up all the datasheets and do the basic formulas or is there a better way?

You drawing is clearer than many I have seen. Actually the simplest - paper and pencil - is usually the most easily understood.

Just add up the datasheets.

And don't power your servo from the Arduino 5v pin. Servos usually require more current than the 5v pin can provide. That may damage the Arduino and may also cause the Arduino 5v to fall too low which makes the Arduino reset and often seems like a software bug.

...R

I used DC power supply this time since I currently do not have batteries equal to the task.
Arduino - 9v 800mA
L298N Motor Driver - 12v 2A

I switched enA to pin 11 and the servo to pin 10. I also used the recommended power levels (powered the servo from the L298N +5V supply instead of the Arduino +5v pin). Both motors spun this time and seemed to do fine, but now I am wondering if the servo code is missing something. The servo rotated one direction smoothly then started back the other way before getting stuck, at which point I shut it down.

Is this an issue with the servo code?

You have +5V connected to the +12V input of the motor module. Is that really okay?

If you supply 7 or more volts to the motor driver you can use the +5v output. Must be related to what was said previously about the L298N wasting 2 volts.

Referring to Reply #6 ...

Post the latest wiring diagram and the latest code.

...R

The servo did seem to zero itself though (or rather it zeroed at the middle first, then moved to -90 degrees before smoothly swinging in the opposite direction. However, it gets stuck on the second code loop from what I can tell. It smoothly swings the arm on the first loop, then on the way back it reaches the original starting position until it gets stuck and acts like it wants to keep going instead of stopping. Maybe the servo and the servo code snippet are confusing each other regarding zero and -90 degrees, and then 180 vs 90 degrees. Anyways, it's got me confused, clearly.

#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
                // twelve servo objects can be created on most boards
 
int pos = 0;    // variable to store the servo position 

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

// the setup function runs once when you press reset or power the board
void setup()
{
  myservo.attach(10);  
  // attaches the servo on pin 10 to the servo object
  // The servo library disables PWM (analogWrite) on pins 9 and 10.  
  // I would put the servo on pin 10 and motor A enable on 11 (PWM).  
  // If pin 9 is used for digitalWrite only, then it is OK. 
    
  // 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);

  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
}

void demoOne()
{
  // 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, HIGH);
  digitalWrite(in4, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now change motor directions
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH); 
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}

void demoTwo()
{
  // this function will run the motors across the range of possible speeds
  // note that maximum speed is determined by the motor itself and the operating voltage
  // the PWM values sent by analogWrite() are fractions of the maximum speed possible 
  // by your hardware
  // turn on motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH); 
  // accelerate from zero to maximum speed
  for (int i = 0; i < 256; i++)
  {
    analogWrite(enA, i);
    analogWrite(enB, i);
    delay(20);
  } 
  // decelerate from maximum speed to zero
  for (int i = 255; i >= 0; --i)
  {
    analogWrite(enA, i);
    analogWrite(enB, i);
    delay(20);
  } 
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);  
}

void ServoTest() 
{ 
  for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(20);                       // waits 15ms for the servo to reach the position 
  } 
  for(pos = 180; pos>=0; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(5);                       // waits 15ms for the servo to reach the position 
  } 
} 

void Blinky() {
  for(int i = 0;i<=15;i+=1)
  {
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);              // wait for a second
    digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);  // wait for a second
  }
}


// the loop function runs over and over again forever
void loop()
{
  demoOne();
  delay(1000);
  demoTwo();
  delay(1000);
  ServoTest();
  delay(1000);
  Blinky();
  delay(7000);
}

I would also ground the servo on the motor board instead of the Arduino.

I don't immediately see anything wrong with the servoTest() function. Maybe it would help to increase the delay() between steps - try delay(50) or delay(100).

Does it work properly if you comment-out the calls to demoOne() and demoTwo() ?

Does it help to increase the delay()s between the calls to the different functions - maybe increase them each to 5 secs ?

The trick is to find some scenario that works and then slowly and methodically work back to where you want to be, testing at each stage.

...R

KalELonRedkryptonite:
If you supply 7 or more volts to the motor driver you can use the +5v output. Must be related to what was said previously about the L298N wasting 2 volts.

Actually no, the 2V overhead is for the voltage regulator, a separate chip to the L298. Linear voltage
regulators often have 1.5V or more of voltage overhead required, although LDO versions can live with 0.5V or less.
The overhead is required for stable analog amplification (voltage regulators are actually special purpose
amplifiers)

Good MOSFET H-bridges can have << 0.1V of waste since its only operating as a switch,
not an amplifier, the L298 is however a darlington driver which intrinsically have >= 1.0V waste per
switching device. We only use darlington H-bridges because they are cheap!

Thanks for the info Mark. And that is indeed why I bought mine :slight_smile:

EDIT: so with the L298N driver you would want to supply 4 extra volts on top of your target voltage?