Control a DC Motor with L9110S Rotary Encoder and Arduino

Got Questions? Click here and post them in the Brainy-Bits Forum to get help!

OVERVIEW

In this tutorial we will use a L9110S dual motor driver to control the speed of a small DC Motor.

At the same time we will learn how to connect a Rotary Encoder and use it to set the speed and direction.

Since we don't want to drive the motor directly from the UNO, we will be using an inexpensive little breadboard power supply that plugs right on our breadboard and power it with a 9V 1Amp power supply.

The Rotary Encoder is connected to the UNO directly since it uses almost no power.



SCHEMATIC

DC Motor control with L9110s and Rotary Encoder

When connecting DC Motors (unless they are brushless) make sure to connect a small capacitor between the leads.  We are using a small 1uF ceramic capacitor in this instance, that will act as suppressor of sparks and surges generated by motor brushes and avoid damaging or resetting the UNO.

As mentioned, we use a breadboard power supply to power the L9110S since motors can draw more current than the UNO can provide.

We will be using an interrupt in our code to read the Rotary Encoder, so we need to make sure we connect the CLK pin of the Rotary encoder to Pin 2 of the UNO which supports interrupts.

 

* The UNO has 2 pins available for interrupts :  Pin 2 and Pin 3.



THE CODE

 

Don't be scared by the size of the code, since most of it is just checking values for Forward and Reverse.

We want to insure that we catch the pulses from our Rotary Encoder when they happen.

It would be very tricky to write a program to do anything else, because the program would need to constantly poll the sensor lines of the encoder, in order to catch pulses when they occurred.

Using an interrupt can free the UNO to get some other work done while not missing the input.

So when we turn the Rotary encoder the interrupt happens, reads the direction, puts the value in the "UP" variable and then resumes our Main Loop.

 

As always you can check out the Tutorial video for more information.

volatile boolean TurnDetected;  // need volatile for Interrupts
volatile boolean up;

const int PinCLK=2;   // Generating interrupts using CLK signal
const int PinDT=3;    // Reading DT signal
const int PinSW=4;    // Reading Push Button switch

// L9110 connections
#define L9110_B_IA 10 // Pin D10 --> Motor B Input A
#define L9110_B_IB 11 // Pin D11 --> Motor B Input B
 
// Motor Speed & Direction
#define MOTOR_B_PWM L9110_B_IA // Motor PWM Speed
#define MOTOR_B_DIR L9110_B_IB // Motor Direction

// Interrupt routine runs if CLK goes from HIGH to LOW
void isr ()  {
 delay(4);  // delay for Debouncing
 if (digitalRead(PinCLK))
   up = digitalRead(PinDT);
 else
   up = !digitalRead(PinDT);
 TurnDetected = true;
}

void setup ()  {
 pinMode(PinCLK,INPUT);
 pinMode(PinDT,INPUT);  
 pinMode(PinSW,INPUT);
 digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
 
 attachInterrupt (0,isr,FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO
 Serial.begin (9600);
 Serial.println("Start");
 pinMode( MOTOR_B_DIR, OUTPUT );
 pinMode( MOTOR_B_PWM, OUTPUT );
 digitalWrite( MOTOR_B_DIR, LOW ); // Set motor to off
 digitalWrite( MOTOR_B_PWM, LOW );
}

void loop ()  {
 static long RotaryPosition=0;    // STATIC to count correctly

 if (!(digitalRead(PinSW))) {   // check if button is pressed
   if (RotaryPosition == 0) {  // check if button was already pressed
   } else {
       RotaryPosition=0; // if YES, then reset position to ZERO
       digitalWrite( MOTOR_B_DIR, LOW ); // turn motor off
       analogWrite( MOTOR_B_PWM, LOW ); 
       Serial.print ("Reset = ");
       Serial.println (RotaryPosition);
   }
 }
 
 // Runs if rotation was detected
 if (TurnDetected)  {
   if (up) {
     if (RotaryPosition >= 100) { // Max value set to 100
       RotaryPosition = 100;
     }
     else {
         RotaryPosition=RotaryPosition+2;
     }
   }
   else {
     if (RotaryPosition <= -100) { 
       // Max value set to -100        
       RotaryPosition = -100;
     }        
     else {          
       RotaryPosition=RotaryPosition-2;
      }
    }    
    TurnDetected = false;  // do NOT repeat IF loop until new rotation detected
    Serial.print ("Speed = "); 
    Serial.println (RotaryPosition);     
    
    // if Rotation is Clockwise    
    if (RotaryPosition > 0 && RotaryPosition < 11) { 
      digitalWrite( MOTOR_B_DIR, LOW ); // turn motor off 
      analogWrite( MOTOR_B_PWM, LOW );
    } 
   if (RotaryPosition > 10 && RotaryPosition < 21) {
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 180 ); // PWM speed = 180
    }
    if (RotaryPosition > 20 && RotaryPosition < 31) {
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 160 ); // PWM speed = 160
    }
    if (RotaryPosition > 30 && RotaryPosition < 41) {
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 140 ); // PWM speed = 140
    }
    if (RotaryPosition > 40 && RotaryPosition < 51) {
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 120 ); // PWM speed = 120
    } 
   if (RotaryPosition > 50 && RotaryPosition < 61) {
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 100 ); // PWM speed = 100 
   } 
   if (RotaryPosition > 60 && RotaryPosition < 71) {
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 80 ); // PWM speed = 80 
   }
    if (RotaryPosition > 70 && RotaryPosition < 81) { 
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 60 ); // PWM speed = 60
    }
    if (RotaryPosition > 80 && RotaryPosition < 91) { 
      digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
      analogWrite( MOTOR_B_PWM, 40 ); // PWM speed = 40
    }
    if (RotaryPosition > 90) { 
     digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
     analogWrite( MOTOR_B_PWM, 20 ); // PWM speed = 20
   }
   
   
// if Rotation is Counter-Clockwise 
   
   if (RotaryPosition < 0 && RotaryPosition > -11) {
       digitalWrite( MOTOR_B_DIR, LOW ); // turn motor off
       analogWrite( MOTOR_B_PWM, LOW );
   }
   if (RotaryPosition < -10 && RotaryPosition > -21) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 40 ); // PWM speed = 40
   }
   if (RotaryPosition < -20 && RotaryPosition > -31) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 60 ); // PWM speed = 60
   }
   if (RotaryPosition < -30 && RotaryPosition > -41) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 80 ); // PWM speed = 80
   }
   if (RotaryPosition < -40 && RotaryPosition > -51) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 100 ); // PWM speed = 100
   }
   if (RotaryPosition < -50 && RotaryPosition > -61) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 120 ); // PWM speed = 120
   }
   if (RotaryPosition < -60 && RotaryPosition > -71) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 140 ); // PWM speed = 140
   }
   if (RotaryPosition < -70 && RotaryPosition > -81) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 160 ); // PWM speed = 160
   }
   if (RotaryPosition < -80 && RotaryPosition > -91) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 180 ); // PWM speed = 180
   }
   if (RotaryPosition < -90) { 
     digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
     analogWrite( MOTOR_B_PWM, 200 ); // PWM speed = 200
   }
 }
}



TUTORIAL VIDEO



DOWNLOAD

Copy and paste the above code in the Arduino IDE to program your Arduino.

Got Questions? Click here and post them in the Brainy-Bits Forum to get help!

Leave a comment

Comments have to be approved before showing up