Arduino – Controlling MDS40A

Introduction

SmartDrive40 (MDS40A) is one of the latest smart series motor drivers designed to drive medium to high power brushed DC motor with current capacity up to 80A peak and 40A continuously. Furthermore, its MOSFETs are switched at 16 KHz to ensure quiet operation and no annoying whining sound. Apart from that, it also equipped with a microcontroller unit to provide some smart features such as multiple input mode (RC, analog/PWM, simplified serial, packetized serial), current limiting and thermal protection. As shown in the Figure 1, there are 1 motor terminal block, 1 power source terminal, 1 error indicate LED, 1 status LED, 4 input terminals, 8 DIP Switches and so forth.

 Figure 1: MDS40A Overview

Recently, the Arduino main boards such as Arduino-Deumilanove (Arduino-Deu) (Obsolete, replace with CT-UNO) which embedded with Atmel microcontrollers are quite popular due to its easy-to-use programming environment. Therefore, by interface Arduino main board with MDS40A, we easier to control the DC motors if compare to PIC microcontroller. In addition, further adding an Arduino-LCD Keypad Shield can help us to control the DC motor that connected to MDS40A with the 6 momentary push buttons (built-in push buttons on LCD keypad shield including 1 Reset button) and also display some useful message by programming. LCD keypad shield is special designed for Arduino main board which we can only just plug onto it and use without soldering. But, in this tutorial, I just use the jumper wires to connect the important pins to use the LCD since there are some ports in Arduino-Due need to be reserved and used for interface MDS40A.

In this tutorial, I will explain how to interface MDS40A with Arduino-Deu and LCD keypad shield. Thus, some guide to drive the DC motors in PWM single channel, sign-magnitude mode and simplified serial mode will be explained in separate parts.

 

Requirements

Main hardware list:

(i) SmartDrive40 (MDS40A): 2 Units                          (ii) Arduino Deumilanove (Arduino-Deu): Replace with CT-UNO 1 Unit

                                     111712_0914_ArduinoBuyi5

(iii) Arduino-LCD Keypad Shield (Arduino-LCD): 1 Unit       (iv) DC motors: 2 Units

                                                dc-geared-motor-107-800x800

Main Accessories list:

(i) Male-to-Female Jumper Wire (WR-JW-MF10)       (ii) Male-to-Male Jumper Wire (WR-JW-MM65)

                                                        

(iii) 12V/7.0Ah Lead Acid (SLA-12-70): 1 Unit           (iv) Adapter 12V 2A (AD-12-2): 1 Unit    

                      

(v) USB MicroB Cable: 1 Unit (CT-UNO)                       (vi) Screw drivers (‘+’ and ‘-’): 1 Unit Each

     WR-USB-UB-280x373                                     

Main Softwares List:

(i) Arduino IDE – download from the Arduino download page

(ii) USB Driver – download from FTDI driver page if you are using Duemilanove or CT-UNO. If you are using Arduino UNO, the driver comes with the Arduino IDE. 

Methodologies

In this tutorial, we will actually demonstrate different wheels movement in combat robot. By using 2 units of MDS40A, we can control 2 DC motors which represent the left wheel and right wheel of the combat robot. Thus, we can vary the speed and direction of the DC motors by interfacing with Arduino-Due. In addtion, we will use a LCD keypad shield to display the important instruction and control the DC motors in different functions with different LCD’s push buttons.

Therefore, we will discuss some basic ideas and connections to connect the Arduino-LCD with Arduino-Due and interface MDS40A with Arduino-Due in two mode which is PWM single channel, sign-magnitude mode, and simplified serial mode. After that, some simple source code with Arduino IDE and some programming ideas will be discussed to control the DC motors with LCD’s push buttons.

Connection between Arduino-Due and LCD Keypad Shield

Since we need interface Arduino-Due with MDS40A, we need to reserve 4 digital pins (2 usual digital, 2 PWM ) and 2 ground terminals for MDS40A. Therefore, we cannot simply plug-in the LCD shield into Arduino-Due. One way we can use is to connect some important pins for Arduino-LCD into Arduino-Due first until we can use it. After that, the remaining ports are leave it no connected so that we can connect it to the other peripheral such as MDS40A as explained in this tutorial. Now, let me introduce first a little bit about the Arduino-LCD:

LCD Keypad Shield or navigation shield which comes with 6 momentary push buttons for menu navigation and also a 2×16 LCD. It use total of 6 pins to control the LCD display which is pin 4, 5, 6, 7, 8, and 9. Pin 4, 5, 6, and 7 are used for LCD data and pin 8 and 9 are used for enable pin. Pin 10 is also be used for LCD backlight contrast control but it is no important to make it works. Apart from that, we connect push buttons to the analog input of Arduino-Due to sense the analog value from push button. Each button will have different analog value because it read from 5 different stages of voltage divider. The schematic of Arduino 2×16 LCD is as shown in Figure 2:

 

Figure 2: Arduino 2×16 LCD schematic diagram 

 The following table shows the important pin allocations of LCD shield for Arduino-Due and its corresponding function:

Pins Function
Analog Pin 0Push Button (Select, Up, Right, Down, Left)
Digital Pin 4DB4
Digital Pin 5DB5
Digital Pin 6DB6
Digital Pin 7DB7
Digital Pin 8RS (Data or Signal Display Selection)
Digital Pin 9Enable
Digital Pin 10Backlight Control

Figure 3: LCD shield important pins that need to be connected to make it function

As shown in Figure 3, the connection of LCD shield to Arduino-Due is simple which we only need to connect Arduino-Due’s digital pin 4, 5, 6, 7, 8, and 9, Gnd and also 5V with LCD shield’s corresponding pins since there are already designed in same sequence of I/O pins for both of LCD shield and Arduino-Due.This is because we need to reserve some digital pins to connect with MDS40A. In addtion, to enable the reset button on LCD shield, we need also to connect RESET pin.

**Notes:

1. Please use Male-to-Female jumper wires to connect them.

2. For further information of LCD shield, please refer to the LCD shield User manual or Tutorial: PROJECT1 – “Hello World” ON LCD.

Therefore, after we have done connect the LCD shield with Arduino-Due, we now can start to interface with MDS40A in PWM and Serial mode as shown in the project 1 and project 2 below.

Let’s start the discussions of project! 🙂

 

PROJECT 1: Interface MDS40A with Arduino-Due in PWM mode

 Connection Diagram

Figure 4: Completed Working Connection Overview

Here are the connection diagram that should be made for this project by Fritzing: 

 

Figure 5: Completed Working Connection Diagram in Fritzing 

 

 Descriptions

To control the DC motors, we firstly need to adjust the DIP switch so that it operate in PWM mode. There are some different mode that can further be set by user under PWM mode such as single channel mode, exponential mode, sign-magnitude mode, left mix and right mix mode. In this tutorial, I will explain how to control the DC motors in single channel and sign-magnitude mode and its DIP switch level is as shown in Figure 6.

Figure 6: DIP switch levels for PWM single channel, sign-magnitude mode 

**Note: Please refer to MDS40A User Manual for more information.

The following table shows the connection between MDS40A side and Arduino-Due side, please refer to this table to check whether the connection is correct:

MDS40A sideArduino-Due side
IN1 (Left)Digital pin 3 (PWM)
IN1 (Right)Digital pin 2
IN2 (Left)Digital pin 11 (PWM)
IN2 (Right)Digital pin 12
Both +5VNo connection needed
Both GNDGnd

**Notes:

1.  Please use the Male-to-Male jumper wires to connect them.

2. The +5V in MDS40A is the output supply, so please do not connect to another 5V source and just leave it no connected.

3. To power up the MDS40A, connect 12V battery to the Dean-T connector properly. Make sure the polarity of the battery is correctly connected to avoid damage on MDS40A.

4. To power-up the Arduino-Due, connect 12V power adapter to it or connect USB cable to computer. Please do not connect both supply at the same time, it may damage the Arduino-Due.

5. To view the full connection, please refer to Figure 5.

   

 How to program the Arduino-Due to make PWM mode works?

Basically, the IN1 of MDS40A is connected to PWM pins of Arduino-Due so that we can generate different value of PWM to vary the speed of the DC motors. By programming, we can assign the PWM value from 0 to 255 to comes up with different speed. Thus, 0 value to stop the motor and 255 value for full speed. Besides that, the IN2 of MDS40A is connected to usual digital pins of Arduno-Due because we need only set it LOW or HIGH to rotate the DC motor whether in Clockwise (CW) direction or Counter-clockwise (CCW) direction. Here the procedure to write sample source code for this project:

1. Firstly, we need open the Arduino IDE and configure some setting which we set the board (under tools) as Arduino Deumilanove w/ ATmega328.

2. After that, we start write the code by calling the “LiquidCrystal.h” library as shown below:

#include <LiquidCrystal.h>

**Note: this library is used for calling the functions for LCD shield.

3. Then, we define the constant or set the constant variable. Also, we define the LCD pins by using calling function. The sample code is as shown below:

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//Keypad Button Numbering
#define RG 0
#define UP 1
#define DW 2
#define LF 3
#define SEL 4
//constant variable
const int mtr1_In1 = 3;
const int mtr1_In2 = 2;
const int mtr2_In1 = 11;
const int mtr2_In2 = 12;
int analogPin = A0;
int adc_key_old;
int adc_key_in;
int NUM_KEYS = 5;
int adc_key_val[5] ={30, 150, 360, 535, 760};

4. Next, we write the setup code to set the pins as input or output. Also, we display some startup message on LCD. The sample code is as shown below:

void setup ()
{
//Set the mode for each digital pins whether input or output
pinMode(mtr1_In1, OUTPUT);
pinMode(mtr1_In2, OUTPUT);
pinMode(mtr2_In1, OUTPUT);
pinMode(mtr2_In2, OUTPUT);
lcd.begin(16, 2); // set the lcd dimension
lcd.clear(); // LCD screen clear
lcd.setCursor(0,0);
lcd.print("MDS40A"); // display the text
lcd.setCursor(0,1); // set lcd.setCursor (column,row)
lcd.print("PWM Mode Demo");
delay(5000); // delay for 5000ms
adc_key_old = analogRead(analogPin); // store the unpress key value
}

5. Now, we can write the main program inside the loop() function. By following sample code below, it will have 4 functions on DC motors which are controlled by 4 push buttons (Up, Down, Left and Right).  Just imagine that the 2 DC motors that connected to MDS40A are the wheel motors for a combat robot, then we control it to move forward, backward, rotate left and right by push buttons. The sample code is as shown below:

void loop()
{
adc_key_in = analogRead(analogPin); // read ADC value
adc_key_in = get_key(adc_key_in);
lcd.clear();
if(adc_key_in == UP) // Check whether Up button pressed
{ // Move forward
analogWrite(mtr1_In1, 220);
digitalWrite(mtr1_In2, HIGH);
analogWrite(mtr2_In1, 220);
digitalWrite(mtr2_In2, LOW);
lcd.setCursor(0, 1);
lcd.print("Move Forward");
delay(200);
}
else if(adc_key_in == DW) // Check whether Down button pressed
{ // Move backward
analogWrite(mtr1_In1, 220);
digitalWrite(mtr1_In2, LOW);
analogWrite(mtr2_In1, 220);
digitalWrite(mtr2_In2, HIGH);
lcd.setCursor(0, 1);
lcd.print("Move Backward");
delay(200);
}
else if(adc_key_in == LF) // Check whether Left button pressed
{ // Rotate to left
analogWrite(mtr1_In1, 150);
digitalWrite(mtr1_In2, LOW);
analogWrite(mtr2_In1, 220);
digitalWrite(mtr2_In2, LOW);
lcd.setCursor(0, 1);
lcd.print("Rotate to Left");
delay(200);
}
else if(adc_key_in == RG) // Check whether Right button pressed
{ // Rotate to right
analogWrite(mtr1_In1, 220);
digitalWrite(mtr1_In2, HIGH);
analogWrite(mtr2_In1, 150);
digitalWrite(mtr2_In2, HIGH);
lcd.setCursor(0, 1);
lcd.print("Rotate to Right");
delay(200);
}
else
{ // Display button navigation for each movement
lcd.setCursor(0,0);
lcd.print("UP=FW DW=BW");
lcd.setCursor(0,1);
lcd.print("LF=LF RG=RG");
delay(200);
analogWrite(mtr1_In1, 0);
analogWrite(mtr2_In1, 0);
}
}

6. Here are the important functions to check which push buttons pressed during run time. The sample code is as shown below:

int get_key(unsigned int input)
{
int k;
for (k = 0; k < NUM_KEYS; k++)
{
if (input < adc_key_val[k])
{
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}

**Note: The sample code that explained in above will be attached at the end of this tutorial.

By follow up the given sample code, we will have 4 functions on DC motors as shown in the table below:

Push Buttons (pressed)Motor 1 DirectionMotor 1 Speed (PWM value)Motor 2 DirectionMotor 2 Speed (PWM value)Function
UpCCW220CW220Move Forward
DownCW220CCW220Move Backward
LeftCW150CW220Rotate Left
RightCCW220CCW150Rotate Right
 **Note: CW=clockwise, CCW=counter-clockwise

Figure 7: Left and Right Wheel DC motors placement

**Note: Two DC motors are placed as shown in Figure 7 to demonstrate that these two DC motors are the wheel motors of the combat robot.

 

PROJECT 2: Interface MDS40A with Arduino-Due in Serial mode

Connection Diagram

Figure 8: Completed Working Connection Overview

Here are the connection diagram that should be made for this project by Fritzing:

Figure 9: Completed Working Connection Diagram in Fritzing

   

 Descriptions

To control the DC motors, we need to adjust the DIP switch so that it operate in serial mode. There are two type of serial mode which is simplified serial and packetized serial. In this tutorial, I will explain how to control the DC motors in simplified serial mode and its DIP switch level is as shown in Figure 10.

Figure 10: DIP switch levels for Simplified serial mode with 9600 baud rate

Note: Please refer to MDS40A User Manual for more information.

For Simplified Serial mode, SmartDrive40 is controlled by using UART interface (Universal Asynchronous Receiver/Transmitter). This, Input 1 (IN1) is the UART Rx pin and Input (IN2) is the Slave Select pin. To make the UART works, we must set Slave Select (IN2) of MDS40A in HIGH logic level (Vcc) in order to receive the command through UART. Otherwise, if we set it in LOW logic level,  the UART data will be ignored. This feature allows multiple SmartDrive40 to be connected together to a single microcontroller UART port. As shown in Figure 10, the baud rate can be set by adjust the last three DIP switches. For this tutorial, I set the baud rate as 9600 by set the last three DIP switches’  logic level as 011.

The following table shows the connection between MDS40A side and Arduino-Due side, please refer to this table to check whether the connection is correct:

MDS40A sideArduino-Due side
IN1 (Left)Digital pin 1 (TX)
IN1 (Right)Digital pin 2
IN2 (Left)Digital pin 1 (TX)
IN2 (Right)Digital pin 12
Both +5VNo connection needed
Both GNDGnd

**Notes:

1.  Please use the Male-to-Female jumper wires to connect them except for digital pin 1 (TX) which need to connect to two IN1 from MDS40A. To connect it, we can use single coil jumper wires to connect it or another ways as long as these two wires are connected to same port (digital pin 1).

2. The +5V in MDS40A is the output supply, so please do not connect to another 5V source and just leave it no connected.

3. To power up the MDS40A, connect 12V battery to the Dean-T connector properly. Make sure the polarity of the battery is correctly connected to avoid damage on MDS40A.

4. To power-up the Arduino-Due, connect 12V power adapter to it or connect USB cable to computer. Please do not connect both supply at the same time, it may damage the Arduino-Due.

5. To view the full connection, please refer to Figure 9.

 

How to program the Arduino-Due to make the serial mode works?

Basically, to control the speed and direction of the DC motors, we need to send single byte of data to the MDS40A from Arduino-Due. Thus, to stop the DC motors, we need to send 127 (about half of 1 byte). Besides that, to rotate the DC motors in clockwise direction, we need to set the byte in between 127 and 255. Sending byte 255 will drive the DC motor in full speed and clockwise direction and decrease from 255 to 127 will slow down the motors. Also, to rotate the DC motors in anticlockwise direction, we need to set the byte in between 0 and 127. Sending byte 0 will drive DC motor in full speed and counter-clockwise direction and increase from 0 to 127 will slow down the motor. Therefore, all these things can be manipulated by programming. Basically, the procedure to write the sample code is similar to Project 1. The procedure to do this is as shown below:

1. Firstly, we just follow the step 1 and step 2 as discussed in Project 1 which is the Arduino IDE configuration and include the important library.

2. Then, we define some constant variable. The sample code is similar to Project but only with some modification on digital pin declaration as shown below:

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//Keypad Button Numbering
#define RG 0
#define UP 1
#define DW 2
#define LF 3
#define SEL 4
//constant variable
const int Tx = 1;
const int mtr1_In2 = 2;
const int mtr2_In2 = 12;
int analogPin = A0;
int adc_key_old;
int adc_key_in;
int NUM_KEYS = 5;
int adc_key_val[5] ={30, 150, 360, 535, 760};

3. Next, we write the setup code. The sample code is similar to Project 1 but only with some modification on baud rate setting and LCD startup message as shown below:

void setup ()
{
//Set the mode for each digital pins whether input or output
pinMode(Tx, OUTPUT);
pinMode(mtr1_In2, OUTPUT);
pinMode(mtr2_In2, OUTPUT);
Serial.begin(9600); // set serial baud rate as 9600
Serial.flush(); // Waits for the transmission of outgoing serial data to complete
lcd.begin(16, 2); // set the lcd dimension
lcd.clear(); // LCD screen clear
lcd.setCursor(0,0);
lcd.print("MDS40A"); // display the text
lcd.setCursor(0,1);
lcd.print("Serial Mode Demo");
delay(5000); // delay for 5000ms
adc_key_old = analogRead(analogPin); // store the unpress key value
}

4. Now, we can write the main program inside the loop() function. By following sample code below, it will have 2 functions on DC motors which are controlled by 2 push buttons (Up and Down).  Sending the valid byte to IN1 of MDS40A to control the speed and direction. The IN2 of MDS40A must be set as HIGH to make this mode works.  The sample code is as shown below:

void loop()
{
digitalWrite(mtr1_In2, HIGH);
digitalWrite(mtr2_In2, HIGH); // The Slave Select (IN2) for MDS40A set HIGH
adc_key_in = analogRead(analogPin); // read ADC value
adc_key_in = get_key(adc_key_in);
lcd.clear();
if(adc_key_in == UP) // Check whether Up button pressed
{ // both motors rotate clockwise (CW)
Serial.write(220);
lcd.setCursor(0, 0);
lcd.print("Both motors");
lcd.setCursor(0, 1);
lcd.print("Clockwise");
delay(200);
}
else if(adc_key_in == DW) // Check whether Down button pressed
{ // both motors rotate counterclockwise (CCW)
Serial.write(35);
lcd.setCursor(0, 0);
lcd.print("Both motors");
lcd.setCursor(0, 1);
lcd.print("Anticlockwise");
delay(200);
}
else
{ // Display button navigation for each movement
lcd.setCursor(0,0);
lcd.print("CW - Press Up");
lcd.setCursor(0,1);
lcd.print("CCW - Press Down");
delay(200);
Serial.write(127);
}
}

5. Here are the important functions to check which push buttons pressed during run time. The sample code is same in Project 1 as shown below:

int get_key(unsigned int input)
{
int k;
for (k = 0; k < NUM_KEYS; k++)
{
if (input < adc_key_val[k])
{
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}

**Note: The sample code that explained in above will be attached at the end of this tutorial.

By follow up the given sample code, we will have 2 functions on DC motors as shown in the table below: 

Push Buttons (Pressed)Motor 1 DirectionMotor 2 DirectionFunction
UpCWCWBoth motors rotate clockwise
DownCCWCCWBoth motors rotate counter-clockwise

**Notes:

1. CW=clockwise, CCW=counterclockwise

2. Since the same byte is being send to both MDS40A, so they will do the same thing. It means that if one motor rotate in clockwise and full speed, another motor will also do like that.

In a nutshell, SmartDrive40 is a quite flexible for the users because it provide several input modes which we can change so that it can interface with microcontroller such as Arduino and PIC to drive the DC motors. But, there are some limitation on SmartDrive40 which we cannot change the input mode during the MDS40A is power on. Meanwhile, we need to power off first the MDS40A and power on it back only after we already change the input mode. Thus, we need to think what mode is suitable to be used before we power on it. Apart from that, the error indicate LED can let us know what error is happening during power on. So, we can identify the errors once something wrong in our connection.

That’s all from me, THANK YOU! See you again next time 😮

 

Attachments

1. Project 1 completed sample code, download here.

2. Project 2 completed sample code, download here.

Buy

, , ,

Related Post

Getting Started with Colour Sensor Module (SN-COLOUR-MOD)

Getting Started with Tilt Sensor (SN-TILT)

Getting Started with Vibration Sensor Module (Normally Off) (SN-VIBRATE-MOD)

Getting Started with IR Distance Click

13 thoughts on “Arduino – Controlling MDS40A

  1. Im using only 2 smartdrive 40 and arduino duemilanove to drive 2 motors, do u have a code for that?

  2. Thanks for info, is there any way i can reach u like an email or phone number because i have more questions to ask

  3. PWM means Pulse Width Modulation where we change the duty cycle of the signal to change certain parameter of control, in this case the speed and some cases, speed and direction.

    Serial mode is to send serial command to the driver. Please do study more 🙂 Do continue the discussion in our technical forum as we seldom check the comment section in this site.

  4. Hey guys, I’m using arduino microcontroller and voice recognition, arduino based.. But I’m bit confuse about the coding..

  5. hello there.. need some idea.. how to connect this two smartdrive40 with arduino controlled by using rc reciever .. can u show the connection between the reciever with arduino and the motor driver .. and with programme too .. I have make some research.. none of them helped

  6. Hello, can we interface ultrasonic sensor with this same project? I want to use keypad interface with project but instead of simply moving forward, I want to use if, else if statements to specify ultrasonic range when moving forward and if obstacle detected vehicle stops, then again forward command is required to move. If you can help me a little bit with the coding, I would really appreciate that.

Leave a Reply

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