====== Bidirectional motor control with Arduino ======
Most Arduino motor shields and the MsMot minishield from Didel use pins 4 to 7 for controlling two motors, with PWM outputs only on pins 5 and 6. Motor's drivers inputs are connected to pins 4,5 and 6,7.
| {{:motor:arduino_motor1.png?200|Arduino with Motor Shield}} | //Examples of Arduino Boards with Motor driver shields.// | {{:motor:arduino_motor2.png?200|Freeduino with MsMot Shield}} |
===== Driving the motor =====
Let's have a motor or [[http://shop.boxtec.ch/ultrabright-redgreen-color-leds-diffused-p-40758.html|bicolor LED]] connected to pins 4 and 5. Pin 4 is set a LOW and pin 5 receive an 8-bit PWM value ( //analogWrite(value)// ).
Now if one wish to reverse the rotation, one need to put a HIGH on pin 4 and set the PWM value on pin 5 to be the complement of what we need.
That is, if one need a low speed, a high "analog" value is required, so the difference with the HIGH of the other pin is small. The complement, 255-value , must be used as shown in next picture.
| {{:motor:arduino_motor_diagram1.png?330|25% of PWM forward and backward}} |{{:motor:arduino_motor_diagram2.png?330|Accelerate and slow down, forward and backward}} |
| 25% of PWM forward and backward | Accelerate and slow down, forward and backward |
===== How to drive a robot with two motors =====
You have a robot with two motors? Make sure you understand how to control the motors with digitalWrite (on all pins) and then with analogWrite (only on pins 5 and 6). Wire you motors and define the pins with the following lines: \\
#define BackLeft 4
#define ForwLeft 5
#define ForwRight 6
#define BackRight 7
Define several functions to make it move: \\
Forward, Backward, TurnLeft, TurnRight with only one parameter. Turn left is turn on itself here. It could be turn on one wheel – test. PWM value, 0..255 must be sent on pins 5 and 6, with the good state on pins 4 and 7, depending on direction.
void Forward (int ss) // 0-255
{
analogWrite(ForwLeft, ss);
digitalWrite(ForwLeft, LOW);
analogWrite(ForwRight, ss);
digitalWrite(RecD, LOW);
}
void Backward (int ss)
{
analogWrite(ForwLeft, 255-ss);
digitalWrite(RecG, HIGH);
analogWrite(ForwRight, 255-ss);
digitalWrite(RecD, HIGH);
}
void TurnRight (int ss)
{
analogWrite(ForwLeft, ss);
digitalWrite(RecG, LOW);
analogWrite(ForwRight, 255-ss);
digitalWrite(RecD, HIGH);
}
This is not the best way to do it though.
There are too many functions, and one cannot make smooth turns. Lets define a single function, Move(). We let the function have two parameters, the positive and negative speed for the two motors. Stop is Move (0,0), full speed backward is Move (-255,-255), etc.
| //Move(left,right)// function has two parameters of type int 16 bits signed. Valid values are between –255 and +255. \\ The function test with an if statement if speed is positive or negative. Positive is easy. Local variable for left speed is named ls. \\ \\ For a negative speed, ls is negative, one need first to take the absolute value, -ls (-ls is positive now) and then we need to take the complement since the other side of the motor must be set at high level. \\Value is hence 255-(-ls) = 255+ls. \\ \\ What happens if one tries //Move(500,-400);// ? \\ This will be accepted, but a speed higher than 255 will be replaced by its modulo 256 value. A solution could be to saturate the received values at the beginnng of the procedure: if (rs>255) rs= 255;
if (rs<-255) rs= -255;
Same for ls. | // pwm between –255 et +255
void Move (int ls, int rs) {
if (ls > 0)
{
analogWrite(ForwLeft, ls);
digitalWrite(RecG, LOW);
}
else
{
analogWrite(ForwLeft, 255+ls);
digitalWrite(RecG, HIGH);
}
if (rs > 0)
{
analogWrite(ForwRight, rs);
digitalWrite(RecD, LOW);
}
else
{
analogWrite(ForwRight, 255+rs);
digitalWrite(RecD, HIGH);
}
}
|
It is easy now to write a ballet for your robot:
Move(200,-200);
delay (100); // turn right for 0.1s
Move(0,0);
delay (500); // stop 0.5s
etc.
The loop to accelerate, slowdown and come back is also quite simple. Add the definitions, the set-up and the function Move() and test it.
You can use a [[http://shop.boxtec.ch/ultrabright-redgreen-color-leds-diffused-p-40758.html|bicolor LED]] in place of a real motor for testing.
The speed of change depends on the delay. Here PWM is modified by one every 8 ms. Acceleration phase lasts 256 x 8 = 2048 ms, about 2 seconds.
int v;
void loop()
{
for (v=0; v<255; v++) { Move (v,v); delay (8); }
for (v=255; v>-255; v--) { Move (v,v); delay (8); }
for (v=-255; v<=0; v++) { Move (v,v); delay (8); }
delay (2000) ;
}
Have fun - JDN.
----
This Howto has been kindly provided by JDN from [[http://didel.com|Didel SA]].