element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • 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 Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • 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
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • 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 17973 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…
  • fmilburn
    fmilburn over 5 years ago in reply to wolsue

    The pin  connections for the encoders are given in the second post of this series: https://www.element14.com/community/community/arduino/blog/2020/01/06/simple-arduino-dc-motor-control-with-encoder-part-2


    Look in the code listing under the PI control header. Sorry, I don’t know what you mean by “result of the rotation”

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

    I wonder where are the encoder connected ??   Where is the result of  the rotation?. The subject says DC Motor Control with Encoder, Part

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • fmilburn
    fmilburn over 5 years ago in reply to bobcroft

    Hi bobcraft,


    Thanks for commenting. There is good reason why Arduino and compatibles are popular.  And good reason not to use them at times.


    The MSP430 is widely used in commercial products, for all I know more so than the ATmega chips. I prefer the MSP430 for a number of reasons and support from TI is good.  I think the use in University settings is also high. There is a free IDE with professional features and tools.

     

    Among the advantage some of the Arduino and compatible boards have for hobbyists is easy to use (many good but some not well written) libraries when used with the arduino IDE. But the basic IDE lacks a debugger and other features.

     

    There is an Arduino fork for some of the TI chips called Energia.

    My use case is not particularly demanding and most microcontrollers, even older 8 bit models could do it. Certainly the newer ARM chips and the ESP32 can. I am not very knowledgeable about motor control industrial use but there are microcontrollers specially made for this with safety features and encoder capabilities not on all ARM chips and perhaps the ESP32.  See comment from Jan Cumps above.

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

    I am not surprised that the view numbers for non Arduino processors are low since some of the others mentioned are not widely used or supported.  I would suggest that the ESP32 would be a good choice as it is more powerful than anything but the latest Arduinos, it has massive support and a very substantial amount of Arduino code can be ported to it.  I would be very interested to know if it is possible to have realistic motor encoder decoding on an ESP32 device.  I guess it would depend on the motor shaft speed.  This is just my personal opinion

    • Cancel
    • Vote Up +1 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
>
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