Adding sg90 servo to arduino nano stops l298n from working

I started to build a two motor robot car using a NANO, BLE HM10 and L298N motor control. I got the robot to work well using the bluetooth serial app. There was a minor issue with how I was parsing the Serial communication but that is now history.
Now I want to add obstacle avoidance so I added an SG90 servo and an HC-SR04 sonar module. For now, I am switching between two modes A) control car with BLE and B) run obstacle avoidance. These are kind of working though I'm encountering an issue when I attach the servo to pin 3. Let me explain just a little more; I'm almost done....

Originally, I had the ENA on pin 10 and ENB on pin 11. The car works fine in this set up. As soon as I add "myservo.attach(3);" to my project, the servo will work, however, one of the motors stop working entirely.

So I read that Timer 1 in the NANOis feeding pins 9 and 10 and that Timer 2 feeds pins 3 and 11. Ultimately, the idea is that by attaching the servo to pin 3, it takes over the Timer so that one of the motors stops working. I updated the code so that ENA and ENB are on pins 9 and 10 respectively. The original robot car functionality works with that single change. Again, as soon as I attach the servo to pin 3 the l298n has problems. In fact, the motors stop working entirely, both of them. The servo works fine. To summarize:

scenario 1: ENA (10), ENB (11), servo (3) = one motor works, servo works
scenario 2: ENA (9), ENB (10), servo (3) = both motors don't work, servo works

I've read that I can try the SoftwareServo library and I'm looking into that now. But it would be great to understand what is happening as I think there is knowledge to be gleaned. If you have any suggestions on things to try or topics to brush up on please let me know. I think that the NANO can be used to power a robot car via BLE and also do obstacle avoidance (via servo and sonar).

Below I'm posting the code of scenario 2. A quick note on power. I thought that maybe I had too many modules connected to the NANO so I did the following:

  • feeding 8V to the L298N
  • enabled the 5V-EN output on the L298N so I'm getting 5V out of that one
  • powering the NANO via the VIN pin that is connected to L298N 8V
  • NANO 5V output powers the HM10 BLE
  • L298N 5V is powering the SG90 servo and HC-SR04 sonar module
  • GND from L298N is made common to NANO, BLE, SG90 and HC-SR04 modules
/*
Using ena 9 and enb 10 (which share timer 1) works. However, if I attach servo to pin 3, servo works but motors dont.
Using ena 10 and enb 11 (which use different timer) works, however, when I attach servo to pin 3, servo works and only one motor works
*/

#include <Arduino.h>
#define IN1 7
#define IN2 8
#define IN3 11 
#define IN4 12 
#define ENA 9 // must be pwm
#define ENB 10 // must be pwm
#define Speed 120

int ledPin = 13;    // Define the LED pin
signed int direction = 0;  // 2 back, 0 stop, 1 forward. Help with turning while moving

// define Servo setup 
#include <Servo.h>
#define SERVO_PIN 3
Servo myservo;
const int D = 30;                 // delay per small increment in servo
const int I = 2;                  // angle increment
const int delay_per_cycle = 50;   // this is the delay after the servo has swept left and right

void Backward() {
  Serial.println("In Backward");
  direction = -1;
  analogWrite(ENA, Speed);
  analogWrite(ENB, Speed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}
void Forward() {
  Serial.println("In Forward");
  direction = 1;
  analogWrite(ENA, Speed);
  analogWrite(ENB, Speed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}
void Stop() {
  Serial.println("In Stop");
  direction = 0;
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}
void Left() {
  Serial.println("In Left");
  analogWrite(ENA, Speed);
  analogWrite(ENB, Speed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  delay(100);  
  if (direction == -1) {
  Backward();
  }
  if (direction == 0) {
  Stop();
  }   
  if (direction == 1) {
  Forward();
  } 
}
void Right() {
  Serial.println("In Right");
  analogWrite(ENA, Speed);
  analogWrite(ENB, Speed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  delay(100);
  if (direction == 1) {
  Forward();
  }
  if (direction == 0) {
  Stop();
  }   
  if (direction == -1) {
  Backward();
  } 
}
void UltraSonic() {
  Stop();
  myservo.write(90);  // 90 is the center line, 0 to the right, 180 to the left
  delay(delay_per_cycle);
  
  // turn to the right
  for (int i = 90; i >= 0; i -= I) {
    if (i % 10 == 0)
    myservo.write(i);
    delay(D);
  }

  // turn to the left
  for (int i = 1; i <= 180; i += I) {
    if (i % 10 == 0)
    myservo.write(i);
    delay(D);
  }

  // turn to center from the left
  for (int i = 180; i >= 90; i -= I) {
    if (i % 10 == 0)
    myservo.write(i);
    delay(D);
  }
}

void setup() {
  pinMode(ledPin, OUTPUT); // Set the LED pin as an OUTPUT
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  Serial.begin(9600);    // Initialize Serial communication with a baud rate of 9600
  Stop();
  Serial.print("Attaching Servo to pin ");
  Serial.println(SERVO_PIN);
  myservo.attach(SERVO_PIN);  // this is what makes the motors not/stop working
  myservo.write(90);// move servos to center position -> 90°    
}

void loop() {
  if (Serial.available() > 0) { // Check if data is available to read from Bluetooth
    char receivedChar = Serial.read(); // Read the incoming character from Bluetooth
    if (receivedChar == 'F' || receivedChar == 'f' || receivedChar == '4') {
      Forward();   
    } 
    else if (receivedChar == 'b' || receivedChar == '5') {
      Backward();
    } 
    else if (receivedChar == 'L' || receivedChar == 'l' || receivedChar == '3') {
      Left();
    } 
    else if (receivedChar == 'R' || receivedChar == 'r' || receivedChar == '0') {
      Right();
    } 
    else if (receivedChar == 'S' || receivedChar == 's' || receivedChar == '6') {
      Stop();
    } 
    else if (receivedChar == 'O' || receivedChar == 'o' || receivedChar == '1') {
      UltraSonic();
    }    
  }
}

On Arduino boards other than the Mega, the Servo library disables analogWrite() (PWM) functionality on pins 9 and 10, even if there isn't a Servo on those pins.

Could that be part of the problem ?

1 Like

Thank you very much UKHeliBob, you are spot on. I changed the pin assignment as follows and it is working now. As always an answer sometimes begets more questions. If anyone has any worthwhile resources on the following please feel free to send through, no worries otherwise:

  1. What would be the purpose of disabling PWM on those pins? Inside of Servo/src/Servo.h line 26 states what it does but not why: " Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached."

  2. I think that I have a rudimentary understanding of Timers and PWM. To me it seems that PWM is a construct of triggering a pin for the exact amount of time hence giving the PWM effect. I assume that the "exact amount of time" is accomplished with the clock or perhaps a timer. Not sure why pins 9/10 are attached to timer 1 and pins 3/11 attached to timer 2 but then pins 5/6 aren't attached to a timer or are they? Why/when does a PWM pin need to have a timer?

  3. Somewhat off topic. Throughout the various uploads I noticed at times that I would turn on the car and it would start to run a bunch of stuff as if there were a buffer with old commands. Pressing reset would usually solve it but at times I would press the 'stop' button a bunch of times until it stopped. Anyone know what would cause this?

Please note that the HC-SR04/Sonar ECHO and TRIG inputs do NOT need PWM. I had them on 5 and 6 but now 2, and 4 work just fine

// define L298N motor control setup 
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 12
#define ENA 3 // must be pwm
#define ENB 11 // must be pwm
// define HC-SR04 Sonar setup 
#define TRIG_PIN 2
#define ECHO_PIN 4
// define SG90 servo setup 
#define SERVO_PIN 5

A quick and dirty explanation.

Arduino pins 9 and 10 are connected to the 328P B register pins 1 and 2. If you look at the datasheet you will see that PB1 and PB2 have alternate functions as OC1A and OC1B, those are the Output Compare Match for Timer 1. AnalogWrite uses the timer Output Compare to PWM clock the associated pins.

The pin to timer allocation is fixed in hardware and hence cannot be changed. When you enable the servo library it takes over Timer one and thus effectively disable PWM for its associated output pins 9 and 10.

Tyvm Willem43 for the explanation. I think that I follow superficially; I asked chatGPT to expand on what you said and it came back with something plausible. Will dig into it. Much appreciated!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.