I'm working on a 2-wheeled Arduino bot with the following setup:
- Motors: 2 N20 DC motors (one on each side of the bot)
- Motor Driver: Adafruit DRV8833
- Microcontroller: Arduino Nano ESP32
I’m trying to decide the best approach for defining the motor spin directions, as the motors need to spin in opposite directions to move the bot forward (one clockwise and one counterclockwise, since they're mounted on opposite sides).
From what I understand, there are two common ways to handle this:
-
Define Spin Direction in Wiring:
Swap the polarity of one motor by switching the wires on the motor driver outputs (e.g., swapping OUT1 and OUT2 for one motor). With this approach, the same logic signal (e.g.,HIGH
for AIN1 and BIN1) makes one motor spin clockwise and the other counterclockwise. -
Define Spin Direction in Code:
Keep the wiring identical for both motors and adjust the control logic in code. For example, to drive forward, you’d sendHIGH
/LOW
to one motor andLOW
/HIGH
to the other.
Here’s an example of how the driveForward() function might look in the two approaches:
Wiring Approach (Motors pre-wired to spin correctly):
@rhammell The code should read correctly otherwise reading and debugging will give you a headache. Then to make it work, You reverse the wiring on one side. I never even considered a different approach.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, 360, fairly knowledge in PC plus numerous MPU's & MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
I use your first suggestion:
"Swap the polarity of one motor by switching the wires on the motor driver outputs.'
// Motor A const int enA = 11; const int in1 = 10; const int in2 = 9; // Motor B const int in3 = 7; const int in4 = 6; const int enB = 5; void forwardA(int rate){ digitalWrite(in1, HIGH); digitalWrite(in2, LOW); analogWrite(enA, rate); } void forwardB(int rate){ digitalWrite(in3, HIGH); digitalWrite(in4, LOW); analogWrite(enB, rate); } void reverseA(int rate){ digitalWrite(in1, LOW); digitalWrite(in2, HIGH); analogWrite(enA, rate); } void reverseB(int rate){ digitalWrite(in3, LOW); digitalWrite(in4, HIGH); analogWrite(enB, rate); } void turnOffMotorA(){ digitalWrite(in1, LOW); digitalWrite(in2, LOW); } void turnOffMotorB(){ digitalWrite(in3, LOW); digitalWrite(in4, LOW); }
@robotbuilder One of us is confused, if you swap the wires, shouldn't the code then be both motors get the same signal, i.e. both HIGH for forward.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, 360, fairly knowledge in PC plus numerous MPU's & MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
There are two terminals outputs for each motor. I swap the output terminals of the L298 connections of one of the motors.
https://dronebotworkshop.com/dc-motors-l298n-h-bridge/
This link includes the schematic of the ic h bridges and their gate control.
Actual wiring. Note the motor (red and black wire) connections are the reverse of each other.
The other wires from the motor are from hall effect encoders. The encoders also have a connection I haven't used that gives the direction of rotation.
Encoders are important as they enable you to control the speed of the motors. The speed for different motors can vary even if the same PWM value used. Encoders can signal that the motor have stalled (due to say hitting an obstacles).
@robotbuilder And?
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, 360, fairly knowledge in PC plus numerous MPU's & MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Hi @rhammell
I prefer wiring the polarity of the two motors differently. Here is a circuit of a PCB that I'm currently work with. I'm using the same motors as you but with a Pico to pull it all together.
https://forum.dronebotworkshop.com/raspberry-pi/pico-robotics-main-board/#post-50526
Tom
To err is human.
To really foul up, use a computer.
@robotbuilder And?
Maybe I missed your quesion? Rather than a text description I have given exactly how I do it with images and a version of Bill's code example.
Encoders can signal that the motor have stalled (due to say hitting an obstacles).
Not necessarily, in my experience when a robot runs into an obstacle the wheels just spin in place. A better approach would be to use a current sensor, like this one https://www.pololu.com/category/312/acs71240-current-sensor-carriers
Place it in series on a motor’s negative wire and connect the sensor’s output to an analog pin and you’re off to the races.
Encoders are important as they enable you to control the speed of the motors.
As I recall you are working on some type of controller that directs the motors in a straight line via encoder output. Can you share that code?
Also, I’d like to add that you can use the DRV8833 to control the speed of a robot by varying the PWM’s duty cycle or by using digital high/low signals. In @rhammell case it looks as if he is using a digital signal.
It’s been a while since I programmed an Arduino board, but don’t they provide some PWM library?
Tom
To err is human.
To really foul up, use a computer.
Good points made Tom. I will respond in my own thread when I get time. Now the xmas break is over I should have time to play around again with the robot project and will share code. Always interested in your experiments and ideas.
John
Thanks for the replies so far, here is some further explanation for clarification.
I have two options to make my two motors spin in the correct directions opposite from eachother to drive my bot forward.
Option 1:
Wiring:
Code:
void forward() { // Drives left motor digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); // Drive right motor digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); }
Here the motors are wired the same, with motor M1 pins and M2 pins going to the A/B 1/2 pins respectively.
With this wiring, to get the motors to spin in the correct directions, the writing of HIGH/LOW is opposite on two AIN* and BIN* pins.
Option 2:
Code:
void forward() { // Drives left motor digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); // Drive right motor digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); }
Here the motor M1 and M2 pins of the left motor going to the A 1/2 pins respectively, but this connection is flipped for the right motor pins.
With this wiriing, to get the motors to spin in the correct directions, the writing of HIGH/LOW is the same on the two AIN* and BIN* pins.
Both of these options successfully do what I want, which is to drive the motors that are placed on opposite sides of my bot in the correct directions (opposite direction of eachother) to drive the bot forward.
My question was to see if either option is preferred or recommended.
Option 1: Having each motor's M1 and M2 pins go to the input 1 and 2 pins seems logical. However, the having the digitalWrite() HIGH/LOW order feels off.
Option 2: Flipping the motors M1 and M2 pins on the right motor feels off, but having the digitalWrite() HIGH/LOW match between the motors feels better.
From the responses here it sounds like Option two is what others have used.
Option 2: Flipping the motors M1 and M2 pins on the right motor feels off, but having the digitalWrite() HIGH/LOW match between the motors feels better.
From the responses here it sounds like Option two is what others have used.
This is a really a matter of style.
My 2 cents are that the code and the physical behavior should correspond. Per force, the motors rotate in opposite directions to move forward or backward. Thus, the code should reflect that. This is how someone new to the code (or you in 6 months) will most likely view the algorithm, trying to match the motor movement to the code.
Unless I'm wrong, turning left and right will also corresponds in the code.
The principle is you want the least amount of surprise in the code.
The one who has the most fun, wins!
@tfmccarthy As Tim said, code should reflect the real physical world as closely as possible. The closest analogy I can think of is a conventional skid steer vehicle. Both levers forward to go forward both back to reverse and right forward to turn right left to turn left. In vehicles with a single motor, the reverse wiring happens in the gearing.
I think I will add this to my 'helping filter'. Anyone who wants option 1 is not someone I want to deal with.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, 360, fairly knowledge in PC plus numerous MPU's & MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.