Introduction: Living With Arduino and the L298N H-Bridge for Bi-Polar Stepper Motor Control

The above module is an L298N daughter board I bought off Amazon a week ago, and getting it working has been a rather frustrating journey that is finally seeing some resolution today. This was a major reason I thought I would put together an instructable to allow people to follow in my footsteps. The L298N is an H-Bridge, this is a fancy name for a set of electronic switches that allows you to reverse the polarity of the output without a more complex circuit. If you look up the capabilities of the L298N chip, it's a very powerful and versatile circuit, however there is a ton of information about how to use it to control DC motors for robots, I am only dealing with stepper motors. It breaks down like this: The board (and chip) have 4 inputs shown/labeled as IN1-4 and four outputs OUT1-4. When you apply a positive TTL signal to any pin it will then send positive voltage from the supply line to that output port. However, if you set IN1 and IN2 high, you are creating a dead short, which may damage both the chip and your motor, therefore it's necessary to make sure both pins are never held high.

Step 1: What You Will Need

This project is going to require a few things, if you're reading this, you're likely to already have:

* An arduino of some flavor (I'm using an UNO)

* A stepper motor (go look up it's spec sheet)

* An L298N driver board similar to the one shown in the picture

* Some kind of power supply that provides at least 5V but less than the max of your motor

* Hookup wire, wire strippers, wire clippers, etc (no soldering on this project)

A digital multi-meter may be helpful

Step 2: Wiring the L298N to the Arduino

I described some of this in the last section, but lets get detailed:

There are four pins on the L298N module IN1-4, there are four output connections OUT1-4. There is also a +V and GND in a terminal block on the module. There is also a +5V terminal (we will not be using this).

The IN pins may be connected to any of the control pins on the Arduino. In my case I have an LCD shield on the UNO, so I used the analog pins (A1 through 4 This will be important later). These were then connected as follows:

A1 -> IN1

A2 -> IN2

A3 -> IN3

A4 -> IN4

Importantly, you must also connect a ground pin from the arduino, into the common ground terminal, otherwise this will not work!!!!

I then attached +V to a variable power supply, and again Ground was connected to ground through the terminal.

Step 3: Wiring the Stepper

If you looked up the spec sheet, it should list which wires are A+ A- B+ and B- sometimes, they don't use this specific language, but what you have is a box with 4 wires coming out of it, these are broken up into two sets. You can check with your Multi-Meter by measuring resistance (or connection) to see which two are paired (if you don't have documentation). In order for the motor to actually spin, you need to make sure A+ and B+ are hooked to OUT1 and OUT3 respectively. If you wire up the motor, and it just vibrates, one of your pairs is reversed.

Basically the wiring diagram is:

A+ (Black) -> OUT1

A- (Green) -> OUT2

B+ (Blue) -> OUT3

B- (Red) -> OUT4

Step 4: Programming: Overview and Warnings

So when I first started this odyssey, the documentation was rather poor, and worse still most of the examples depend on using either digitalWrite for handling pin manipulation, or worse still depend on the built in arduino stepper library, which essentially implements the same thing. However, there is a massive problem with doing it this way. The digitalWrite system is ungodly slow, and worse still, if you're executing a digitalWrite followed by another digitalWrite it's really ugly ugly horrible slow kludgy code. DON'T DO THIS!

If you're not already familiar with it, you should read this:

https://www.arduino.cc/en/Reference/PortManipulati...

What this allows us to do is to rather than writing pins high or low one at a time, simply write a whole set of pins high or low just by addressing the register that controls these pins.

So the warning: the L298N H-Bridge is essentially 4 individual switches operating as one, and has one major bad habit if you use it with the existing arduino Stepper library, or if you use the repeated digitalWrite() statements, that is, because of the wait time before setting pins, it's likely you may put IN1 and IN2 high at the same time. This creates a dead short, and after perhaps no more than a minute or two, will likely smoke-check your bridge. It took me several days of debugging to figure out why the bridge was pulling 4 amps, and after about 5 seconds of running, the heat sink became too hot to touch.

Step 5: Programming Example

So, there's some extra stuff in here that you may or may not need, like the code for the LCDShield, or the code that checks the execution time of the main loop.

If you're using the A1-A4 this code should compile (Arduino IDE 1.6.5) and get your motor to spin. Most of this code is my own, with a bit borrowed or altered from the Stepper.h file.

Notes:

The delay on "StepFast" is in microseconds, so 2000 is only 2 milliseconds, most of the time if you try stepping the motor with a delay of less than 1200 it will skip steps, and despite 800 steps being 4 full revolutions for most motors, you may find your motor only makes maybe a quarter turn.

This code is intended as an example, it currently doesn't reverse, nor does it take feedback from the L298, or do a lot of other things I would like. In looking at the existing Stepper.h, I may re-write it in the coming weeks using this method for handling the steps, as the existing method will likely damage the L298 or any other H-bridge configuration.

#include <Arduino.h>
#include <LiquidCrystal.h>

//Keypad Shield LCD pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

long unsigned int lasttime;
long unsigned int timer;
int timeuntil;
float exectime;
int smallcount;


void setup() 
{
  lcd.begin(16, 2);
  lcd.print("Motor Test");
  delay(2500);
  lcd.clear();
}


void StepFast(long int steps,long unsigned wait)
 { 
  DDRC = B00011110; //set arduino ports A1-A4 output remember this works backwards!
  //      ^-pin 7^-pin 0
  int pattern = 0;
  int mydelay = 0;
  for (int i = 0;i < steps; i++)
   {
    switch (pattern) 
     {
      case 0:  // 1010
       PORTC = B00001010; //arduino analog port we're using pins A1-A4 So we're only going to change those
      break;
      case 1:  // 0110
       PORTC = B00001100;
      break;
      case 2:  //0101
       PORTC = B00010100;
      break;
      case 3:  //1001
       PORTC = B00010010;
      break;
     }
    pattern++;
    if (pattern > 3) {pattern = 0; }
    delayMicroseconds(wait);
   }
   PORTC = B00000000; //de-energize to motor
 }

void loop() 
 {
  lasttime = timer;
  timer = millis();
  exectime = (timer - lasttime)/1000;
  if (timeuntil < timer)
  {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Clockwise ");
   lcd.print(exectime);
   lcd.setCursor(0,1);
   lcd.print(timer);
   lcd.print(" ");
   lcd.print(lasttime);
   timeuntil = timer + 1500;
  }
  StepFast(800,2000); //steps,delay in microseconds
  delay(5000);   
 } 

Notes:

This code works fairly well at moderate step speeds of ~300RPM (step rate of 1ms or so) as you try to get more towards 1000RPM, it will start missing steps unless the voltage increases, however if you run the motor at 60RPM (5ms) at >5V the L298N will start to get quite hot.

Step 6: Afterthoughts and Additions

So there are a few things I didn't really address in the original write up that I'm very much in the process of dealing with. Of these, the main issues are:

  • As step speed increases, the supply voltage also must increase
  • Using the pins ENA and ENB as PWM inputs to keep voltage low at low step speeds, and raise it as step speed increases
  • Dealing with Acceleration and Inertia