Your shopping cart is empty!
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:
- 1 x MD10C Rev2.0
- 1 x Arduino Board Uno/Mega
- 1 x Arduino LCD Keypad Shield
- Male to male jumper wires
- Female to male jumper wires
- 1 x DC Geared Motor (SPG20/30 series)
- 1 x Adapter 12V 2A(AD-12-2)
- 1 x Screw Driver Set(TO-SD-803)
- 1 x Potentiometer (5k/10k/20k/100k)
- 1 x Breadboard
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#include
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:
- 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.
- 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.
- 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 tutorial/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 potentiometer. The 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#include //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< Attachment: