Controlling MD10C with Arduino

1.0 Introduction:

Enhanced 10Amp DC Motor Driver (MD10C) is an enhanced version of the MD10B which is designed to drive high current brushed DC motor up to 13A continuously (for Rev2.0). It offers several enhancements over the MD10B such as support for both locked anti-phase and sign-magnitude PWM signal as well as using full solid state components which result in faster response time and eliminate the wear and tear of the mechanical relay.

Arduino main boards such as Arduino Uno are quite popular these days due to its easy-to-use programming environment. Therefore, by interfacing Arduino main board with MD10C, we gain easier control of DC motors. In addition, further adding an Arduino LCD Keypad Shield can help us to control the DC motor that connected to MD10C with the 6 momentary push buttons (built-in push buttons on LCD keypad shield including 1 Reset button) and also display some useful message or information.

In this tutorial, I am going to show several simple ways to drive DC brush motor using MD10C and Arduino.


How does MD10C work?

One of the features of MD10C is it supports both sign-magnitude and locked anti-phase PWM signal, means you can control motor in 2 different ways!

  • Sign-magnitude mode
    You require 2 separate signals to control the motor, one is for direction (counterclockwise or clockwise) and another is for the speed. To control motor direction, DIR pin is connected to HIGH or LOW for different direction, whereas PWM pin is fed with PWM signal to control the motor speed.
  • Locked anti-phase mode
    In this mode, only 1 signal is required to control both speed and direction of motor. PWM pin of MD10C is always connected to HIGH (5V), while DIR pin is fed with d to PWM signal. The direction of motor depends on whether the duty cycle of PWM signal is less than or more than 50%. The motor will run in one direction if the duty cycle is less than 50% and another direction if more than 50%. The motor stops if duty cycle is 50% (approximately). The speed depends on the percentage of duty cycle.

Sign-magnitude VS Locked anti-phase

The videos below show some demonstration on how to control motor in sign-magnitude mode and locked anti-phase mode.

Sign Magnitude Mode

Locked anti-phase Mode

Main advantage of using locked anti-phase mode compare to sign-magnitude mode in motor controlling is it reduces number of I/O pins used since it uses only 1 signal for controlling both the speed and direction of motor. However, if locked anti-phase is used, in the beginning motor will run at maximum speed (as you can see in the video) when there is no PWM signal. Users will have to provide PWM signal at 50% duty cycle to DIR pin or set PWM pin (MD10C) to LOW state in the beginning. In terms of programming, the algorithm will be more complex because in locked anti-phase mode, motor speed changes with increment or decrement of PWM value depends on the direction which the motor is at. Motor becomes slower with increment of duty cycle if duty cycle of PWM signal is less than 50% or otherwise if duty cycle is more than 50%.

What will you learn from this tutorial?

  • Control motor in sign-magnitude and locked anti-phase mode using programming, push button and potentiometer
  • Create PWM signal using other pins instead of predefined PWM pins from Arduino board.

So, what are we waiting for? Let’s get started!

2.0 Quick Setup

Components you should need:

In this tutorial, Arduino Board Uno is used. However it is fine if you use Arduino Mega because in this tutorial there is not many pins needed.

Okay, first we stack up the Arduino board with Arduino LCD Keypad Shield. For boards other than Arduino Uno, just make sure the pins (RST to Vin) match the pins on the LCD Keypad Shield. You can also check the analog pins(A1-A5) too to see whether they are matching.

                   

Second, all we need to do is to do wiring according to figure below. Of course, the connections will be slightly different as the motor is operated at different modes. These connection will be shown later as we proceed.

The motor used in this tutorial is SPG20 series, in which the rating is 12Vdc. To power up the motor, there are several ways to do so. You can connect Arduino board with 12V 2A DC adapter to power supply, then wire Vin pin on Arduino board to Power positive pin on MD10C to fed 12Vdc to the motor.

OR you can connect external 12V battery to power pins + and -. MAKE SURE that the terminals are connected accordingly and correctly or else the components will be DAMAGED!

 

What if I want to use different dc motor? Yes, you can. But first you need to know clearly the rating of your motor. What is the maximum voltage that the motor can support? It is not advisable to run your motor with voltage supplied exceeding the voltage rating because it can spoil your motor eventually or instantly. In this tutorial, SPG20 motor rating is 12VDC, thus 12VDC is supplied to power it up.

 


Okay, we are done with the basic connection! Let’s move to programming stage!

3.0 Programming:

Let us start the code with first 2 lines below to include necessary library files.

#include <LiquidCrystal.h>
#include <LCD_Key.h>

LiquidCrystal library is for LCD display while LCD_Key is for controlling the push buttons on LCD Keypad Shield.

**Note: Make sure these 2 libraries exist in your library directory in Arduino folder.



Then, we can proceed with variables and libraries declaration and pin assignments.

//define keycode for LCD push button
#define None 0
#define Select 1
#define Left 2
#define Up 3
#define Down 4
#define Right 5
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
LCD_Key keypad;
//define pin name
#define diy_pwm A2
#define pwm 3
#define dir 2
#define pot A1

This is where you assign pin name for your selected pins. For this tutorial, digital pin 3 is connected to PWM pin on MD10C, digital pin 2 for DIR pin,analog pin 1 (A1) to potentiometer and analog pin 2 (A2) is for PWM generation purpose. This configuration is for sign-magnitude mode. As for locked anti-phase mode, connection and configuration will be changed slightly. This will be discussed later.

**Note:

  1. Notice that pin 4 to 9 has been used for LCD display purpose. Therefore if you are using LCD, pin 4 to 9 cannot be used.
  2. For your information, these pin assignments are just for reference in this tutorial. User can connect PWM pin from MD10C to other I/O pins other than digital pin 3 as long as they are PWM pins are are not assigned to any other tasks.To know which pin is PWM pin, please refer to datasheet.
  3. For easy plug-in, analog pin 2(A2) is used for creating PWM signal as analog pins can be used as digital pins. User can use other available digital or analog pins for this purpose as long as they are easy for users to configure.

Next, we proceed to pin and LCD initialization and configuration, this is where we start to determine which pin is input and which pin is output, and also initialize LCD display.

void setup(){
lcd.begin(16, 2);
lcd.clear();
pinMode(pwm,OUTPUT);
pinMode(dir,OUTPUT);
pinMode(diy_pwm,OUTPUT);
pinMode(pot,INPUT);
}

The code below is where you will write your own program. Remember the program written in void loop()will repeat endlessly unless you add some codes to terminate the loop. This will be discussed later.

void loop(){
//write your program here
}

Mode 1: Sign-Magnitude PWM

As mentioned above, Sign-Magnitude PWM requires 2 separate control signals for speed and direction. Thus the basic idea of programming is to control these 2 signals. Check the connections first.

Connection in sign-magnitude mode

Below are the sample codes written in Arduino to control speed and direction of motor.

i) Controlling motor speed with program set

Program concept:

This program runs the motor from rest to maximum speed, increasing PWM value from 0 to 255 in every 0.1 sec. User can modify delay time to control speed change. To see motor direction change, user can digitalWrite dir HIGH or LOW.

void loop(){
int pwm_value=0;
lcd.setCursor(0,0);
digitalWrite(dir,HIGH);                                          // set DIR pin HIGH or LOW
for(pwm_value=0;pwm_value<256;pwm_value++){
analogWrite(pwm,pwm_value);                               //increase PWM in every 0.1 sec
delay(100);
lcd.clear(); //display status of motor on LCD
lcd.setCursor(0,0);
lcd.print("PWM:");
lcd.print(pwm_value);
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(digitalRead(dir));
}
while(1) continue;                                               //continue,terminate loop;
}

ii) Controlling motor speed with push button

Program concept:

This utilizes the push button from LCD keypad shield to control motor. LEFT button is for toggling motor direction, UP button for increasing value of PWM and DOWN button for decrement.

void loop(){
int localKey; //initialize
int pwm_value;
while(1){
localKey = keypad.getKey();            //scanning for which button on keypad shield being pressed
if(localKey==Left){                            //toggle motor direction if LEFT button pressed
digitalWrite(dir,!digitalRead(dir));
delay(200);
}
if(localKey==Up){                   //increase motor speed if UP button pressed
pwm_value++;
delay(200);
lcd.clear();
}
else if(localKey==Down){                              //decrease motor speed if DOWN button pressed
pwm_value--;
delay(200);
lcd.clear();
}
if(pwm_value>255)                         //ensure speed limit as PWM value ranges from 0 to 255
pwm_value= 255;
else if(pwm_value<0)
pwm_value= 0;
analogWrite(pwm,pwm_value);
lcd.setCursor(0,0);                            //LCD display
lcd.print("PWM:");
lcd.print(pwm_value);
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(digitalRead(dir));
}
}

 

iii) Controlling motor speed with potentiometer

Program concept:

This program generates PWM signal with value directly taken from analog value from analog pin. Average of 5 consecutive analog values is taken and converted from 10 bit to 8 bit before being fed to PWM pin. By tuning the potentiometer, analog value changes thus PWM signal changes, which results in change of motor speed. LEFT button on LCD Keypad shield is still used for toggling motor direction. 

void loop(){
int localKey;                         //initialization
int pwm_value;
int reading = 0;
int prev_reading = 0;
int output = 0;
lcd.setCursor(0,0);                //LCD display on beginning
lcd.print("PWM:");
lcd.print(output);
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(digitalRead(dir));
while(1){
localKey = keypad.getKey();
if(localKey==Left){
digitalWrite(dir,!digitalRead(dir));  //toggle and display motor direction if LEFT button pressed
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(digitalRead(dir));
delay(200);
}
reading = 0;               //get average five consecutive analog readings from A1 pin (pot)
for(int i =0;i<5;i++)
reading += analogRead(pot);
reading/=5;
output=reading*0.2493;          //convert from 10 bit to 8 bit, 0.2493 = 255/1023
if(reading!=prev_reading){  //update LCD data if only the reading changes to prevent reading on
//LCD blinking
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("PWM:");
lcd.print(output);
prev_reading = reading;
}
analogWrite(pwm,output);
}
}

 

 

 

Mode 2: Locked anti-phase PWM

Locked anti-phase PWM requires only 1 control signal for both motor speed and direction. Thus the basic idea of programming is to control this 1 signal. Before going to do some programming, let’s make some modification on connections.

Connection in Locked anti-phase mode


Everything remains the same except for digital pin 2 is connected to PWM pin on MD10C while pin 3 is connected to DIR pin.

For programming, remember to redefine the pins in void setup()with following code. Now PWM pin on MD10C is connected to digital pin 2 and DIR to pin 3.

//define pin name
#define diy_pwm A2
#define pwm 2
#define dir 3
#define pot A1

Below are the sample codes written in Arduino to control speed and direction of motor in locked anti-phase mode. The program concept is almost the same, just that digital pin connected to PWM pin of MC10C is always in HIGH state.

**Note: You may notice that the codes for both modes are almost the same, just that LEFT push button is not needed to change direction of motor. 

i) Controlling motor speed with program set

void loop()
{
// LOCKED ANTI-PHASE MODE
//control motor with program set
int i=0;
lcd.setCursor(0,0);
digitalWrite(pwm,HIGH);        // always set PWM to HIGH
for(i=0;i<256;i++){        // increase speed in every 0.5 sec
analogWrite(dir,i);
delay(500);
lcd.clear();                //display status of motor on LCD
lcd.setCursor(0,1);
lcd.print("DIR:");lcd.print(i);
lcd.setCursor(0,0);
lcd.print("PWM:");
lcd.print(digitalRead(pwm));
}
while(1) continue;        //continue,avoid loop;
}

ii) Controlling motor speed with push button

void loop()
{
// LOCKED ANTI-PHASE MODE
//Control motor with push button
int localKey;                        //initialize
int pwm_value;
digitalWrite(pwm,HIGH);        // always set PWM to HIGH
while(1){
localKey = keypad.getKey();        //scanning for which button on keypad shield being pressed
if(localKey==Up){            //increase PWM if UP button pressed
pwm_value++;
delay(200);
lcd.clear();}
else if(localKey==Down){        //decrease PWM if DOWN button pressed
pwm_value--;
delay(200);
lcd.clear();}
if(pwm_value>255)            //ensure speed limit as PWM value ranges from 0 to 255
pwm_value= 255;
else if(pwm_value<0)
pwm_value= 0;
analogWrite(dir,pwm_value);
lcd.setCursor(0,0);            //LCD display
lcd.print("PWM:");
lcd.print(digitalRead(pwm));
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(pwm_value);
}
}

iii) Controlling motor speed with potentiometer

void loop()
{
// LOCKED ANTI-PHASE MODE
//Control motor with potentiometer
int localKey;                          //initialization
int pwm_value;
int reading = 0;
int prev_reading = 0;
int output = 0;
lcd.setCursor(0,0);            //LCD display on beginning
lcd.print("PWM:");
lcd.print(digitalRead(pwm));
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(output);
while(1){
localKey = keypad.getKey();
reading = 0;                                //get average five consecutive analog readings
for(int i =0;i<5;i++)                //from A1 pin (pot)
reading += analogRead(pot);
reading/=5;
output=reading*0.2493;           //convert from range 1024 to 256
if(reading!=prev_reading){        //update LCD data if only the reading changes
lcd.print("       ");        //prevent reading on LCD blinking
lcd.setCursor(0,0);
lcd.print(“PWM: “);
lcd.print(digitalRead(pwm));
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(output);
prev_reading = reading;
}
analogWrite(dir,output);
}
}

 

Understanding and creating your own PWM

What if you are running out of PWM pins but you still want to use PWM signals to do something else? Never mind, you still can create your own PWM signal using other pins. You can use timer interrupt function or delay function to create PWM signal. However in this tutorial, we will be using timer interrupt.

To make learning easier, it is advisable to know the basic concept of PWM. To learn more about PWM, visit this following link http://tutorial.cytron.com.my/2012/01/14/basic-pulse-width-modulation-pwm/.

Timer interrupt or delay function?

Both methods can be used to do same purpose. The main disadvantage of using delay function is you cannot do anything else once you generate PWM signal. As for timer interrupt, you can do other tasks even though you are generating PWM signal. However in programming simplicity, delay function is simpler to use and requires less configuration. Both methods can be used, but it is application-dependent.

Connection

In this tutorial, sign-magnitude mode is used. Figure below shows the connection. PWM pin on MD10C is connected to A2 pin and DIR to pin 2.


Below is the sample code using timer interrupt – controlling motor with potentiometerThe following code implement the Timer0 compare match interrupt

**Note: Using Timer0 for PWM generation will change the setting of delay(),millis() and micro() functions. If you want to use those functions, it is considerable to use Timer1 or Timer2 instead. For further configuration of Timer1 or Timer2 of Arduino, users can visit the following link

http://letsmakerobots.com/node/28278

Program concept:

Initially Timer0 is configured and A2 pin (OUTPUT pin) is set HIGH. In the main program, desired PWM_value is obtained directly from analog value from A1 pin. There are 3 conditions after the interrupt is called.

Condition 1:

If user set PWM value is 0, A2 always gives LOW value, meaning 0% duty cycle.

Condition 2:

It also gives HIGH value if user set PWM value is 255, giving 100% duty cycle.

Condition 3:

If the set PWM_value is between 0 and 255, then counter ( in program referred as byte count) will increase by 1 each time the Timer0 interrupt routine is called. If counter reaches the desired PWM value, A2 signal will toggle to LOW. If the counter hits 255, A2 will toggle back to HIGH state and start a new period. As the counter increases, it will recycle from 0 to 255, then immediately jump to 0 and start over again as it is a byte.

#include <LiquidCrystal.h>
#include <LCD_Key.h>
//define keycode
#define None     0
#define Select   1
#define Left     2
#define Up       3
#define Down     4
#define Right    5
//define pin name
#define diy_pwm  A2
#define pwm      2
#define dir      3
#define pot      A1
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
LCD_Key keypad;
byte count = 0;
int pwm_val = 0;        //global variable for DIY PWM purpose
void setup(){
lcd.begin(16, 2);
lcd.clear();
pinMode(pwm,OUTPUT);
pinMode(dir,OUTPUT);
pinMode(diy_pwm,OUTPUT);
pinMode(pot,INPUT);
cli();                       //stop interrupts
TCCR0A = 0;              // set entire TCCR0A and TCCR0B register to 0
TCCR0B = 0;
TIMSK0 &= ~(1<<TOIE0);      //disable timer overflow interrupt
OCR0A  = 0;              //initialize counter value to 0
TCCR0A |= (1 << WGM01);    // no prescaler
TCCR0B |= (1<<CS00);
TIMSK0 |= (1 << OCIE0A);    // enable timer compare interrupt
sei();                      //enable interrupt
}
void loop()
{
//DIY PWM
digitalWrite(dir,HIGH);               //set direction of motor
while(1){
pwm_val = analogRead(pot)*0.2493;    //read and convert analog value from
// from 10 bit to 8 bit
lcd.home();                          //LCD display
lcd.setCursor(0,0);
lcd.print("PWM:");
lcd.print(pwm_val);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("DIR:");
lcd.print(digitalRead(dir));
}
}
ISR(TIMER0_COMPA_vect){            //interrupt routine
//PWM generation
if(pwm_val ==0)
digitalWrite(diy_pwm,LOW);
else{
count++;
if(count==255){
digitalWrite(diy_pwm,HIGH);
count = -1;
}
else if(count==pwm_val)
digitalWrite(diy_pwm,LOW);
}
}

Attachment:

, , , ,

Related Post

Getting Started with Encoder Sensor Module (SN-ENC-MOD)

Getting Started with 3A Motor Driver Shield and Arduino Uno

Controlling 10A DC Motor Driver Using Arduino Nano

Peak Current vs Continuous/Rated Current

11 thoughts on “Controlling MD10C with Arduino

  1. Hi,
    I liked your project. And admire your enthusiasm. Quite interesting. Congrats. Unfortunately, I’m too old to learn programming languages​​, but the desire to make something someone reported the same has not been passed. I want to make a single-phase motor Speed ​​controller with IGBT, everything I have, I just need to source Arduino Uno to generate PWM 16kHz. Here, I see, you would use the same frequency, but I need a simple, direct one-on Pin to generate a 16kHz frequency. To make it, I lack the experience and knowledge of the instrument, to see what the frequency is generated. Can you pick out the few lines which are responsible for this function, and then, as the engine revs will try to adjust the buttons on the same build.
    Heartfelt thanks in advance.
    With respect. Evaldas

  2. This is really helpful for me. I just have one question, I want to use optocoupler as a safety measures for my arduino board, so, is it possible to connect this type of motor driver to a microcontroller? Thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *