element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Blog Simple Arduino DC Motor Control with Encoder, Part 1
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: fmilburn
  • Date Created: 2 Jan 2020 5:26 AM Date Created
  • Views 20503 views
  • Likes 11 likes
  • Comments 24 comments
  • dc motors
  • adafruit feather
  • motor drivers
  • encoder
  • adafruit m4 express
  • motor
  • arduino
  • dual motor control
Related
Recommended

Simple Arduino DC Motor Control with Encoder, Part 1

fmilburn
fmilburn
2 Jan 2020

Updated 2 Jan 2020:  Embedded 2nd video

 

I am starting to plan ahead for a robot that will have image recognition using a Raspberry Pi.  Image recognition being computationally intensive, the plan is to offload the Pi with microcontrollers connected with I2C.  In previous post an I2C template for connecting a Raspberry Pi with Python to a microcontroller with the Arduino IDE is described.  This post is the first of two parts describing how a microcontroller can be used for motor control over I2C.

 

Introduction

 

While there are motor driver hats for the Raspberry Pi I plan to develop a separate board with microcontroller and motor controller connected to the Pi with I2C.  This should unload the Pi and keep pins and other resources available for other duties.  In any event microcontrollers are well suited to the task and easy enough to implement.   Encoders will be used to obtain more accurate speed control and estimation of distance travel and turning angle.  This accruacy is desirable for example when making a pen bot.

image

In this first post the motors, encoders, and motor driver board will be tested.  In a future post proportional and integral control will be added along with connection to the Raspberry Pi.

 

Encoders

 

The small geared brushed DC motors used in these tests have rotary encoders attached to the shafts and are included in the Arduino Engineering KitArduino Engineering Kit. In the view below, the encoder disk is attached to a shaft extension at the bottom of the motor.  A piece of tape has been attached to the main shaft to make rotation more visible.

image

The end view below looks directly at the encoder disk from the back.  The encoder uses hall effect sensors to detect the passage of four magnets which are encased in the disk as seen in the photo.

image

Power to the motor is provided by the red and black wires on the right.  The brown (Vcc) and green (GND) provide power to the two hall effect sensors.  The blue and purple wires are the output for the two hall effect channels of the encoder.  This type encoder is incremental - that is it reports changes in position but not absolute position.  From it the rotational speed and direction of the motor shaft can be determined.  Knowing the gear ratio and size of the wheels on the robot (plus a little math) the RPM of the wheel and distance travelled over time can be determined.

 

Simple Motor Test

 

The goal of the test is to make sure the motors and encoders are performing as expected.  Somewhat unusual for these small motors, a motor performance curve is available.  The motor is rated for up to 12 V but the plan is to use it at 6 V.  Power during the tests will be provided by a bench power supply set at 6V and current limited to 100 mA.  Encoder output is sent to the oscilloscope.

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

The motor and encoder perform as expected.

 

Motor Driver

 

The motor driver used is a Toshiba TB6612FNG capable of controlling two brushed DC motors and came on a small board from Pololu.  It is installed on a bit of Veroboard and was used on the first robot I designed about four years ago.  The controller can provide sustained current up to 1.2 A per channel and voltages up to 15 V.  Functions include forward and reverse direction, braking, thermal shutdown, and standby power saving mode.  Speed is individually controlled to the motors with PWM.  Motor power supply comes in to the connectors bottom left and output to the two motors is bottom right.  Input to the motor controller is on the 0.1" header here and is described in the microcontroller section below.

image

 

Microcontroller

 

For these tests an Adafruit M4 Feather Express will be used.  This is way more microcontroller than needed but it is a simple task to substitute something else.  The following code tests all of the functions available on the Toshiba TB6612FNG and was written in the Arduino IDE.  Only pins need be modified to run on another Arduino capable microcontroller with sufficient pins and PWM.

 

/*
 * Robot_SimpleMotorDrive
 * 
 * Adafruit Feather M4 using Pololu TB6612FNG motor controller
 * 
 * Motor Control Table
 * XIN1   XIN2    Effect
 * Low    Low     Brake
 * Low    High    Forward
 * High   Low     Reverse
 * 
 * Free to use for all
 * F Milburn, January 2020
 */
// Pins used to control motors
const uint16_t PWMA = 5;         // Motor A PWM control     Orange
const uint16_t AIN2 = 6;         // Motor A input 2         Brown
const uint16_t AIN1 = 9;         // Motor A input 1         Green
const uint16_t BIN1 = 10;        // Motor B input 1         Yellow
const uint16_t BIN2 = 11;        // Motor B input 2         Purple
const uint16_t PWMB = 12;        // Motor B PWM control     White
const uint16_t STBY = 13;        // Standby                 Brown
// Constants
const uint16_t ANALOG_WRITE_BITS = 8;
const uint16_t MAX_PWM = pow(2, ANALOG_WRITE_BITS);
const uint16_t MIN_PWM = MAX_PWM / 3;    // Make sure motor turns
void setup(){
   initMotors();
 }
void loop(){
   uint16_t pwm = 0;
   // test forward
   for (pwm = MIN_PWM; pwm <= MAX_PWM; pwm += 20){
     forwardA(pwm);
     forwardB(pwm);
     delay(2000);
   }
   // brake
   brakeA();
   brakeB();
   delay(500);
   // test reverse(){
   for (pwm = MIN_PWM; pwm <= MAX_PWM; pwm += 20){
     reverseA(pwm);
     reverseB(pwm);
     delay(2000);
   }
   // brake
   brakeA();
   brakeB();
   delay(500);
 }
void forwardA(uint16_t pwm){
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, HIGH);
  if (pwm > MAX_PWM){
    pwm = MAX_PWM;
  }
  if (pwm < MIN_PWM){
    pwm = MIN_PWM;
  }
  analogWrite(PWMA, pwm);
}
void forwardB(uint16_t pwm){
  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, HIGH);
  if (pwm > MAX_PWM){
    pwm = MAX_PWM;
  }
  if (pwm < MIN_PWM){
    pwm = MIN_PWM;
  }
  analogWrite(PWMB, pwm);
}
void reverseA(uint16_t pwm){
  digitalWrite(AIN1, HIGH);
  digitalWrite(AIN2, LOW);
  if (pwm > MAX_PWM){
    pwm = MAX_PWM;
  }
  if (pwm < MIN_PWM){
    pwm = MIN_PWM;
  }
  analogWrite(PWMA, pwm);
}
void reverseB(uint16_t pwm){
  digitalWrite(BIN1, HIGH);
  digitalWrite(BIN2, LOW);  
  if (pwm > MAX_PWM){
    pwm = MAX_PWM;
  }
  if (pwm < MIN_PWM){
    pwm = MIN_PWM;
  }
  analogWrite(PWMB, pwm);
}
void brakeA(){
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, LOW);
}
void brakeB(){
  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, LOW);
}
void standbyMotors(bool standby){
  if (standby == true){
    digitalWrite(STBY, LOW);
  }
  else{
    digitalWrite(STBY, HIGH);
  }
}
void initMotors(){
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
  pinMode(PWMB, OUTPUT);
  pinMode(STBY, OUTPUT);
  analogWriteResolution(ANALOG_WRITE_BITS);
  standbyMotors(false);
}

 

Lines 6 - 10:  The motor control table documents how to control the direction of the motors.  This table has been coded into functions that control direction and speed by the way of PWM.

Lines 24-26:  Various microcontrollers have different ADC resolution and that is addressed here along with maximum and minimum allowable values.

Lines 31-52:  This is the heart of the program.  It ramps up speed of the motors, pauses, and then ramps them down before starting over again.

Lines 53-112: Functions that control the capabilities of the motor driver - e.g. forward, reverse, stop.  Range is checked on RPM.

Lines 113-122: Initializes the pins used, sets the analog write resolution, and takes the motor out of standby.

 

Motor Controller Test

 

After finding a bug in the code associated with not being able to see the pin labels on the Feather (or for that matter the pin map) the motor control tests went fine.

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

The screenshot below was taken on the oscilloscope during the motor controller test.  Channel A from the encoders on the two separate motors is displayed.  While it would be possible to use both channels on a motor it is probably not necessary.  The motor direction is known since it is set in code and the resolution from a single hall sensor should be adequate to control motor speed.

image

 

Next Steps

 

The last robot I made was during the RoadTest of the Texas Instruments RSLK which used the MSP432.  Since I am familiar with the TI microcontrollers, especially the MSP430 models, I am tempted to use it but have noted that posts I make on those microcontrollers don't get near as much attention as Arduino related material.  Since part of my objective with this hobby is to encourage others to get started with electronics and engineering in general maybe I should stick with Arduino.  In any event, the next step is to implement Proportional and Integral control so as to better control motor speed.  I have been jumping around on this project and should also lay out a plan with objectives and a roadmap.  Committing those things in writing where others can see it tends to keep me better focused.

 

The follow-up blog is here and demonstrates successful use of PID control to match the two motor speeds.

 

As always comments, suggestions, and corrections are appreciated.

 

LInks

Simple Arduino DC Motor Control with Encoder, Part 2

Creating Multi-Purpose I2C Devices with Arduino for use with a Raspberry Pi

Raspberry Pi and Arduino I2C Communication

TI RSLK RoadTest

 

  • Sign in to reply

Top Comments

  • Andrew J
    Andrew J over 5 years ago +4
    I shall follow along with interest - I’d like to have a go at a simple robot and motor drive this year.
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to fmilburn +4
    There are a number of controllers around that have quadrature decode support in their timers, or have a dedicated decoder peripheral. They support the functionality with little software and little CPU…
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to fmilburn +4
    fmilburn wrote: ... I am reflecting on what I thought were innovative posts I made on TI FRAM chips that did not receive much attention (example, 120 views) but a post on hooking an Arduino up to a toaster…
Parents
  • robogary
    robogary over 5 years ago

    I'm very interested in how it goes for you. All the commercially available Raspberry Pi robot kits use a I2C interface board for h bridges , encoders, and aux IO.

    Donkey Car, Dexter, etc....ad naseum

    Donkey car is the vision based autonomous driving using Raspberry pi.

     

    Myself, it thought it would be easier to hardwire an H bridge control from GPIO, but move all the other sensors to I2C. At the end, I2C is probably better for everything to avoid discrete GPIO.

    I have built some bigger vehicles using Power Wheel Cars as the chassis, using generic  50A H bridges.

    I do want any i2C board to provide external analog outputs to allow me to drive bigger H bridges  with direction bits and PWM :-)  

     

    I am especially interested how you design the I2C and code the PI for it. I wanted to do a similar project to yours, and include commercially available sensors, but havent got past the point of asking the Pi for all the I2C drop numbers.

     

    good Luck, we all are watching with great interest.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dubbie
    dubbie over 5 years ago in reply to robogary

    Gary,

     

    This sounds very similar to a dual DC motor driver I have used in the past (Sabretooth Dual 32A Motor Driver) which had RC PWM inputs for control, as well as variable resistance (potentiometers), plus TTL and all sorts of setup parameters. I wanted to make some electric carts to race on University Open Days, plus I wanted a swarm of decent sized mobile robots for my research. We used old wheel chair motors, dual 12V car batteries and various lumps of metal. They were a hoot to play with:

     

    https://www.youtube.com/watch?v=vRgBUq0CPHI 

     

    https://www.youtube.com/watch?v=L8VqO9qxHgA 

     

    Dubbie

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • robogary
    robogary over 5 years ago in reply to dubbie

    Thanks Dubbie - I am familiar with the Sabertooth modules, they are a hoot.

    I was first introduced to Sabertooth several years ago by the Carolina Combat Robots .  They use Sabertooth modules for their battlebots, and they also have a robot football/soccer team with a traveling arena they install at some maker fairs, allowing the kids to drive the football robots in battle. This group uses a bunch of sabertooths :-)

     

    I am a stereotypical engineer, that is I am cheap  :-)  the Sabertooth modules are robust and awesome but expensive for everyday hacking.

    I developed my own piecemeal assembly using low cost Flysky RC controllers, feeding the desired signal channel into an Arduino Nano. With just a few simple lines of code, the Nano reads the receiver PWM signal ( 1 ms = full reverse, 1.5 ms = nuetral, 2 ms = full fwd , once every 20 msec) spits out a direction logic bit (forward or Reverse)   and a translated PWM Duty Cycle that can control any generic H bridge.  

     

    I keep L298N H bridges on hand for spontaneous projects

    https://www.instructables.com/id/Arduino-Modules-L298N-Dual-H-Bridge-Motor-Controll/ 

    and also have used cheap H bridges found on ebay ,  add in my own upstream power distribution and fusing. I've used these higher amp modules on power wheels cars driving motors, not one failure yet.

    https://www.ebay.com/itm/IBT-4-5-15V-50A-H-bridge-High-power-Motor-High-Current-Driver-Module/264294431720?hash=item3d89…

    https://www.ebay.com/itm/50A-Dual-Channel-H-Bridge-Motor-Driver-Module-for-Arduino-Robot-Chassis-Servo/111873397923?hash…

     

    I usually stick to 12V systems, but can do whatever I want using generic H bridges.  I always though bigger was better, until the robot cars got too big to fit in my Mazda CX5 to transport. :-)

    The external H bridges usually include the gating deadband and bridge lockout , so you cant fire both reverse bridge and forward bridge at the same time. 

     

    Ramping the PWM Duty cycle gating a bit avoids DC motor stall currents at zerospeeds.

    Luckily the radio controllers have internal speed ramps as well on the throttle channel.

    The FlySky FS-GT3B in fact has S curve ramps, which I love !!!   It allows easing the motor into taking up the gearing backlash, reduces slamming the gearbox big time.  

    Saves motor stress, motor fuse stress, and battery stress. I dont have to write S curve ramp code, either :-)  that would be a tough time consuming project for me.

     

    Thanks Dubbie - keep the good suggestions coming. Gary

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • robogary
    robogary over 5 years ago in reply to dubbie

    Hi Dubbie - One thing I thought was hilarious on the videos - the ESTOP button was never in a spot where the operator / driver could reach it !!!!

     

    Even on my smaller robots, I always include flashing LED beacons to show the bridge power is enabled, and at least one main fuse. 

    I usually have a shrouded LED lighted on-off switch to act as a ESTOP on any robot bigger than 12 inches or so.

    image

    the larger robots/cars always have a secondary power switch or more that also act as ESTOP/ kill switches.

    I always worry about letting the smoke out at inopportune times.

    I usually put a small fuse for all the control electronics when feed from a battery bigger than 1000mAhr. 

    Stepping down from soapbox now :-)

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dubbie
    dubbie over 5 years ago in reply to robogary

    Gary,

     

    We initially wanted to use RC PWM to control the Sabretooth which I was generating from an Arduino for some reason I cannot remember now, but the Health & Safety people started getting a bit twitchy about that as the system had a fail mode that meant it would zoom off uncontrollably - not a good idea for something weighing over 40 kg. I pooh-poohed their timidness - until it failed and zoomed off! Fortunately, no-one was injured.

     

    The stop switch was really there for testing when the chassis was up on 'bricks'. As you say, there was no way to access it when the chassis was moving. The stand on chassis in the video had a safety-cutoff switch on the base plate so if you stepped off (or fell off - it nearly happened!) the motors cutout. Later versions had a pull cutout on a rope although that didn't help as no-one could catch the rope.

     

    I was busy elsewhere so didn't have much to do with it, but eventually it all ended up in a robot called Trolley Rage for the BBC Robot Wars. Regretfully it was not really competitive. The axe motor was accidentally destroyed before the filming and I think it lasted 40 seconds before it was ripped to pieces. It's in Series 9 Episode 5 and 17 minutes and 51 seconds into the show, Trolley Rage took one hit from Carbide which ripped out the motor drivers and that was that!

     

    Dubbie

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • dubbie
    dubbie over 5 years ago in reply to robogary

    Gary,

     

    We initially wanted to use RC PWM to control the Sabretooth which I was generating from an Arduino for some reason I cannot remember now, but the Health & Safety people started getting a bit twitchy about that as the system had a fail mode that meant it would zoom off uncontrollably - not a good idea for something weighing over 40 kg. I pooh-poohed their timidness - until it failed and zoomed off! Fortunately, no-one was injured.

     

    The stop switch was really there for testing when the chassis was up on 'bricks'. As you say, there was no way to access it when the chassis was moving. The stand on chassis in the video had a safety-cutoff switch on the base plate so if you stepped off (or fell off - it nearly happened!) the motors cutout. Later versions had a pull cutout on a rope although that didn't help as no-one could catch the rope.

     

    I was busy elsewhere so didn't have much to do with it, but eventually it all ended up in a robot called Trolley Rage for the BBC Robot Wars. Regretfully it was not really competitive. The axe motor was accidentally destroyed before the filming and I think it lasted 40 seconds before it was ripped to pieces. It's in Series 9 Episode 5 and 17 minutes and 51 seconds into the show, Trolley Rage took one hit from Carbide which ripped out the motor drivers and that was that!

     

    Dubbie

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube