Introduction: Tim's I2C Intelligent DC Motor Driver

About: Retired due to health. Oldish. My background is in Structural Engineering. Also smith of many trades. The majority of my project will be what can be made sat in a chair within arm's reach, on a plotter, 3D pri…

I am working on a project, it's a Robotic Arm that needs about six Motors.

  • This Instructable is how to make a Motor Driver to control lots of motors for Robotic type projects using just two GPIO Pins of your microcontroller. The I2C Bus.
  • In theory 127 motors can be controlled using the Arduino I2C Bus library.

There are many DC Motor Drivers available to buy, But.

  • The Motors I am using are DC Motors with Quadrature Encoders.
  • Quadrature Encoders have an A and B output, which need to be connected to a microcontroller that uses the data from the Quadrature Encoder to ascertain the position and direction of a motor. See my Instructable: Wi-Fi Control of a Motor With Quadrature Feedback : 9 Steps (with Pictures) - Instructables
  • This would mean that each motor will have two Encoder connections to the microcontroller, plus the Driver connections.
  • There are I2C Motor Drivers, this would reduce the connections for the Motor Drivers, but these do no more than the normal Motor Drivers do, there is no positional feedback through the I2C connection.
  • The microcontroller I want to use to control the Motors has a limited number of pins.

I also would like to take away a lot of the processing the microcontroller would have to do controlling all the motors.

  • It would be nice if the microcontroller was connected to the Motor Drivers via I2C. Only two wires from the microcontroller connected to all the Motor Drivers.
  • It would be nice if the Motor Driver knew the position of the Motor and could send this data back to the microcontroller via the I2C connection.
  • It would be nice if the microcontroller only had to send a position command to the Motor Driver and the Motor driver did all the work.
  • It would be nice if we could have limit switches attached to the Motor driver so that it would not go beyond them.
  • It would be nice if the Motor driver could be given soft limits to stay within.
  • It would be nice if the Motor driver could be given a known position from a Station, so that it could set a known position when triggered.

I think I have come up with the solution.

  • This Motor Driver is controlled via I2C.
  • The Motor Driver can be configured for many scenarios.
  • The Max Motor voltage is: 30v.
  • The Max Motor current is: 1A, this can be increased by beefing up the traces on the PCB, MOSFETs are rated at 5.8A. (A bit OTT but cheap)
  • The System voltage is: 3.3v. There is an option to add a voltage regulator if power comes from a higher source.
  • The brains is the STM8S103F3P6, as a slave I2C Device.
  • The I2C Address can be set from 0x01 (1) to 0x7F (127). So in theory 127 Motors can be attached to one microcontroller.

Assumptions

This is a device for people that build Robots, Electrically controlled devices using Motors, all controlled by a microprocessor.

  • I assume those that wish to build this has knowledge of electronic components.
  • I assume those that wish to build this has knowledge of the Arduino Architecture and Programming.
  • If you are going to make one, check my notes about fabrication.

Supplies

This project is based on:

  • 1 x STM8S103F3P6. (U1)
  • 1 x The production of a PCB to mount it.

Supporting components are:

  • 2 x SMD MOSFETS, SOT-23-3, (M10, M30) I am using AO3401.
  • 2 x SMD MOSFETS, SOT-23-3, (M20, M40) I am using AO3400.
  • 2 x SMD general-purpose NPN transistor, SOT-23-3, (Q10, Q30) I am using S8050.
  • 1 x 1uF Capacitor SMD 0805 2012Metric (C1 )
  • 1 x 100nF Capacitor SMD 0805 2012Metric (C2)
  • 2 x Blue LED SMD 0805 2012Metric (D1, D4)
  • 1 x Green LED SMD 0805 2012Metric (D2 )
  • 1 x Connector 01x04 Header P2.54mm Vertical (J1)
  • 4 x Connector 01x02 Header P2.54mm Vertical (J2, J3, J4, J5)
  • 1 x Connector 01x06 Header P2.54mm Vertical (J6)
  • 10 x 10k Resistor SMD 0805 2012Metric ( R1, R2, R11, R12, R13, R21, R31, R32, R33, R41)
  • 2 x 100R Resistor SMD 0805 2012Metric (R3, R4)
  • 1 x 150R Resistor SMD 0805 2012Metric (R5)
  • 1 x 68R Resistor SMD 0805 2012Metric (R6)
  • 1 x 200R Resistor SMD 0805 2012Metric (R7)

Optional Components:

  • 1 x AMS1117-3.3 Regulator Linear SOT 223 3 (U2)
  • 2 x Connector 01x02 Header P2.54mm Vertical (J9, J10)
  • 1 x Blue LED SMD 0805 2012Metric (D3)
  • 1 x 1k Resistor SMD 0805 2012Metric ( R100)
  • 1 x 100nF Capacitor SMD 0805 2012Metric (C3)

Tools

Programmer.

There are three files needed:

  • MotorDriver_ProgramMemory.S19
  • MotorDriver_Data.S19
  • MotorDriver_Options.S19

Master I2C Device.

  • For this Instructable I am using an Arduino Nano 33 IoT as a Master I2C device to control the Motor Driver.
  • Any Arduino 3.3v Device will do, I have attached the Arduino Firmware for this demonstration of the motor Driver.
  • The Arduino .ino file will need to be placed in a folder of the same name but without the ".ino" .
  • Any other Master Device can be used as long as it can send/receive text via I2C at 100000 speed. (If using another ST as Master then you may need to pm me)

Motor.

  • A motor with Quadratic Encoder will show the full potential of this Motor Driver.
  • A motor without a Quadratic Encoder can be used but the functions will be basic.

Step 1: Order Your PCB and Components

I have created a Zip of the Plot Files needed to upload to a PCB Manufacture.

If you use KiCad then all the files are on my GitHub

There are many Instructables that show how to add and solder SMD components to a PCB, I don't think there is need to repeat things.

I have done a full list of the components in the Supplies section.

  • All the minor SMDs are 0805 imperial 2012 metric.

The board has an option to fit a Voltage Regulator, should you only have power from a higher voltage than 3.3 volts.

  • This should not be needed, but I try to accommodate other possibilities when designing a PCB, after all it has two side and it is been made out.

When you have all your parts, solder them to the PCB.

  • I designed the PCB to take the standard 2.54mm (10th inch) Headers.
  • It's your choice to use headers or solder cables direct.

If you look at the last image (back).

  • You can see that I have designed it so that boards can be plugged together end to end using using horizontal pin header and sockets.
  • I did not do this with the motor power, as this could be different for each motor.

Note!

When I was making my Driver Boards, I had some issues with the MOSFETs I was using.

  • It was a heat issue.
  • Check temperatures of the MOSFETs in the data sheet.
  • The data sheet shows a soldering flow chart.
  • Heating the MOSFETs over 150 degrees Celsius for to long will kill them.
  • I had to use a lot of heat to solder some of the Through Hole Headers, especially to GND.
  • The PCB has a large copper GND area.
  • I ended up having to add the all the Transistors last using a hot air tool.

Step 2: Programming the STM8S103F3P6

To programme the STM8S103F3P6 you will need:

This is not an Instructable about ST Visual Develop IDE there is just enough for you to upload the firmware to the STM8S103F3P6.

The following instructions is how to upload my firmware to the Motor Driver.

I have just put pads for programming.

  • I have spaced them so that you should be able to hold a row of four 2.54mm male header pins on them.
  • Programming only takes seconds.

Step 3: ST Visual Programmer [Correct Microcontroller ]

When you install "ST Visual Develop IDE" from STMicroelectronics, it will also install "ST Visual Programmer".

  • You will find the shortcut for "ST Visual Programmer" in the "ST Toolset" folder in your Start Menu.
  • Open "ST Visual Programmer".

When you open "ST Visual Programmer", it is important that you have the correct Microcontroller selected.

  • Make sure STM8S103F3 is selected in the dropdown box in the toolbar at the top.
  • This can also be selected on the configuration dialog window.

Step 4: ST Visual Programmer [Configuration]

Click Configure on the toolbar at the top.

  • Choose: "Configure ST Visual Programmer".

This will open the "Configuration" Dialog Window.

  • Select: "Hardware" to ST-LINK.
  • Select: "Port" to USB.
  • Select: "Programming Mode" to SWIM.
  • Select: "Device" to STM8S103F3 (Should be set by previous step)
  • Click "OK" when done.

Step 5: ST Visual Programmer [Program the Motor Driver]

Time to program the Motor Driver.

I assume you have downloaded my firmware and saved it somewhere.

There is three stages (Tabs) to programming the Motor Driver:

  • PROGRAM MEMORY
  • DATA MEMORY
  • OPTION BYTE (This one first, the chip may need unlocking)

Each stage is the same.

  • Select the Tab.
  • Load the file.
  • Program the Motor Driver.

Connecting the programmer to the driver board.

  • I have spaced them so that you should be able to hold a row of four 2.54mm male header pins on them.
  • Programming only takes seconds.
  • If you don't feel confident holding the pins on the pads, you could temporally solder some pins/cable to the pads.

When all programming is done.

  • The motor driver is nearly ready, it just needs resetting.

Step 6: ST Visual Programmer [Program the Motor Driver] OPTIONS BYTE

The first is OPTIONS BYTE.

  • Select the OPTIONS BYTE tab.
  • Click "File" on the Toolbar.
  • Select: "Open".

In the "Open" dialog window:

Connect the "ST-LINK v2" to your USB.

  • Hold the four cables to the pads as shown in the image.
  • Make sure you have the correct cable to the right pad.

When ready:

  • Click: "Program" on the toolbar.
  • Select: "Current tab"

The programming takes a few seconds.

  • You can remove the "ST-LINK v2" cables when done.

Step 7: ST Visual Programmer [Program the Motor Driver] DATA MEMORY

Next is DATA MEMORY.

  • Select the DATA MEMORY tab.
  • Click "File" on the Toolbar.
  • Select: "Open".

In the "Open" dialog window:

Connect the "ST-LINK v2" to your USB.

  • Hold the four cables to the pads as shown in the image.
  • Make sure you have the correct cable to the right pad.

When ready:

  • Click: "Program" on the toolbar.
  • Select: "Current tab"

The programming takes a few seconds.

  • You can remove the "ST-LINK v2" cables when done.

Step 8: ST Visual Programmer [Program the Motor Driver] PROGRAM MEMORY

Then we do PROGRAM MEMORY.

  • Select the PROGRAM MEMORY tab.
  • Click "File" on the Toolbar.
  • Select: "Open".

In the "Open" dialog window:

Connect the "ST-LINK v2" to your USB.

  • Hold the four cables to the pads as shown in the image.
  • Make sure you have the correct cable to the right pad.

When ready:

  • Click: "Program" on the toolbar.
  • Select: "Current tab"

The programming takes a few seconds.

  • You can remove the "ST-LINK v2" cables when done.

Step 9: Motor Driver [Reset]

The reason for having a Motor Driver Reset is:

  • There may be a time if you make a few Motor Drivers, you may forget the I2C address.
  • Rather than connect it to and Arduino programmed to find I2C Devices, or re-program it.
  • It can be reset to the default address of 0x30 (48).

To reset the Motor Driver it needs to be powered (3.3v).

  • Two cables are required attached to ground (GND).
  • One of the cables needs to be held on the "I2C Reset" pad.
  • The other then needs to touch the "NRST" pad.
  • Done.

D1 and D2 should blink on a power up or Reset.

We can now communicate with the Motor Driver on I2C Address 0x30 with an Arduino.

  • The I2C Address can be changed once we can communicate with the Motor Driver.
  • Changing the I2C Address requires a re-boot.
  • The Address is a 7 bit Arduino compatible Address.
  • An STM Microcontroller programmed with ST Visual Develop IDE as Master may have issues communicating.

Step 10: Motor Driver [Commands]

I have tried to come up with enough commands and settings that will cover most scenarios.

  • Commands start with a Capital Letter immediately followed by a number, there are a little like Geometric (G) Code.
  • Some commands may also have a value, this also starts with a Capital Letter immediately followed by a number.
  • A space will separate the two above.
  • Mostly values are the number of ticks from an Encoder or 1 or 0 to represent a Boolean.
  • As these commands are sent over I2C, each Motor will have it's own Address that the Commands are sent to.

'C' Commands (settings):

  • C0 = Reset things to 0 (zero). To Do. Not used at the moment.
  • C1 = Sets the Current Position to 0 (zero). Just use C1.
  • C2 B<value> = Set: Has a Maximum Position. Boolean = 1 or 0 (true or false).
  • C3 P<value> = Set the Maximum Position value. value = a 24+ bit value, Sets maximum Forward position.
  • C4 B<value> = Set: Has a Minimum Position. Boolean = 1 or 0 (true or false).
  • C5 P<value> = Set the Minimum Position value. value = a 24+ bit value, Sets maximum Reverse Position.
  • C6 B<value> = Set: Has a Station Position. Boolean = 1 or 0 (true or false).
  • C7 P<value> = Set the Forward Station Position value. value = a 16 bit value, Sets the Station Position while moving Forward.
  • C8 P<value> = Set the Reverse Station Position value. value = a 16 bit value, Sets the Station Position while moving in Reverse.
  • C10 A<value> = Set I2C Address. value = 1 (0x00) to 127 (0x7F). This is to change the I2C Address of the device.
  • C11 P<value> = Motor Slowdown Point. value = a 16 bit value, Sets the number of tick before at target stop point, the motor will reduce speed.
  • C12 P<value> = Motor Speed Reduction. A Percentage, 0 to 100% reduction of current speed.
  • C13 B<value> = Set I2C Speed. Boolean; Is it 400k. value = 1 or 0 (true or false). 1 = 400000, 0 = 100000.

All setting are saved in non volatile memory.

  • no need to apply settings every time power it connected.

'S' Command (Speed):

  • S<Value> = Set the Speed 0 to 1000. This is a PWM value. So 500 would be 50% on 50% off square wave.

'F' Commands (Forward):

  • F0 = Stop. Can just use 'F' as the buffer will be full of zeros.
  • F1 = Forward at a current Speed.
  • F1 S<value> = Forward at a set Speed.

'R' Commands (Reverse):

  • R0 = Stop. Can just use 'R' as the buffer will be full of zeros.
  • R1 = Reverse at a current Speed.
  • R1 S<value> = Reverse at a set Speed.

'G' Commands (Go to):

  • G0 = Stop. Can just use 'G' as the buffer will be full of zeros.
  • G1 P<value> S<value> = Move to an absolute Position Forward (Positive) of zero at a Speed.
  • G2 P<value> S<value> = Move to an absolute Position Reverse (Negative) of zero at a Speed.

The 'G' code P<value> can be negative values. So why have G1 and G2?

  • To keep options open.
  • All positions are relative to a zero.
  • When writing your own code to control the Motors you may only have the option of Unsigned Integers.
  • You may want to only use Unsigned Integers to save memory.

Step 11: Scenarios [Basic]

The basic scenario would be to use it as a normal Motor Driver.

  • I2C versions of Motor Drivers can be found on the web.

In this Scenario:

  • Only the Motor would be connected to the Motor Driver.

Commands used would be:

  • S<Value> = Set the Speed 0 to 1000.
  • F0 = Stop.
  • F1 = Forward at a current Speed.
  • F1 S<value> = Forward at a set Speed.
  • R0 = Stop.
  • R1 = Reverse at a current Speed.
  • R1 S<value> = Reverse at a set Speed.

These commands can be used with all Scenarios.

  • I won't list them in the following Scenarios.
  • In these Scenarios I will only be showing two motors, in theory 127 motors can be on one I2C bus.

Note!

The power used for the Driver is 3.3 volts.

Step 12: Scenarios [Quadrature Encoder]

Adding a Quadrature Encoder to the Motor enables you to position the Motor to any position you chose.

The resolution of your Quadrature Encoder determines how accurate your movements are.

  • To make this Motor driver more compatible, I have made all positions a number of Ticks from the Quadrature Encoder.
  • All Ticks are changes from the Quadrature Encoder in one direction only, I was not able double up the Ticks by reading the change in both directions.
  • The Maximum and Minimum count is quite high. I have made the numbers 24+ Bit values.

What is a 24+ Bit value?

I made it up.

  • I wanted to use a 32 bit integer, but I ran out of memory.
  • A 24 bit Integer is quite big if there was such a thing in C compiler, if there was one it would be: -8388607 to 8388607.
  • Because all numbers are sent on I2C in 1 byte (8 bit) chunks, and I am storing several different values in 1 byte chunks. I have put the Negative Bits on a separate Byte, the separate Byte can hold the Negative Switches for 8 numbers. Therefore the Numbers can use all 24 Bits.
  • Using all 24 bit and a separate Negative bit gives a range of: -16777215 to 16777215.

In this Scenario:

  • The Motor would be connected to the Motor Driver.
  • The Motor will have Quadrature Encoder fitted to them.

The additional commands used would be:

  • G0 = Stop. Can just use 'G' as the buffer will be full of zeros.
  • G1 P<value> S<value> = Move to absolute Position Forward of zero at a Speed.
  • G2 P<value> S<value> = Move to absolute Position Reverse of zero at a Speed.

You can use the G commands without the speed value, it will use the current set speed.

Because there is a Quadrature Encoder attached to the motor.

  • We can set and activate Soft Limits.
  • With Soft Limits set and activated the motor will not move beyond these values.

The setting commands used would be:

  • C2 B<value> = Set: Has a Maximum Position. (Activate)
  • C3 P<value> = Set the Maximum Position value.
  • C4 B<value> = Set: Has a Minimum Position. (Activate)
  • C5 P<value> = Set the Minimum Position value.

To make the Motor Driver not move beyond a set Position, the Motor Driver needs the relevant Limit activating.

  • The Maximum value must be lager than the Minimum value.
  • The Minimum value must be smaller than the Maximum value.
  • Having an Activation setting enable you turn stops on or off without having to reset the value.
  • Do not Activate the stops if the Minimum and Maximum are both set to 0 (zero) or the same value, the motor will not move.

The Current Position can be read by the Microcontroller, see Master Microcontroller Code.

Step 13: Scenarios [Hard Stops]

Adding hard stops will prevent the Motor from moving when a Hard Stop is Triggered.

  • Hard Limits do not require Activating.
  • Hard Stops just need connecting.
  • The Hard stop pins are held HIGH and are triggered when pulled to GND.

In this Scenario:

  • The Motor would be connected to the Motor Driver.
  • Minimum, Maximum Stops require connecting.

There are no settings for the Hard stops.

  • The Maximum Hard Stop will stop the Motor if Triggered when the motor is moving Forward.
  • The Minimum Hard Stop will stop the Motor if Triggered when the motor is moving Backward.
  • The motor can be restarted in the opposite direction it was stopped.

Depending on what you are making, Hard stops can be used as obstacle sensors.

  • For instance, if you are making a remote controlled vehicle, they could be attached to bumpers.

Hard Stops can be read by the Microcontroller, see Master Microcontroller Code.

Step 14: Scenarios [Station]

What is a Station?

Put simply a Station is a place, a position, a coordinate that is known.

Adding a Station (switch) will give you a know position that can be set when Triggered.

  • The value of the Position can be set in Settings.

In this Scenario:

  • The Motor would be connected to the Motor Driver.
  • A Station will be connected.

Settings used would be:

  • C6 B<value> = Set: Has a Station Position.
  • C7 P<value> = Set the Forward Station Position value.
  • C8 P<value> = Set the Reverse Station Position value.

Why two Position values?

As with most micro switches, the position it turns on is not always the same position it turns off.

  • If not using micro switches and using an IR switch with a shutter.
  • The shutter used with an IR switch has a minimum width to block the light to the sensor.
  • So the position will be different closing the shutter from each direction.
  • Having the ability to set both positions that can Trigger the Station makes it more accurate.

Step 15: Testing / Example

I have done an Arduino Sketch to enable you to set up a Motor Driver. (In supplies above)

  • This requires an Arduino to to communicate with the Motor Driver.
  • The Sketch will allow you to send and receive data to and from the Motor Driver.
  • The Sketch uses the USB Serial to transfer your commands via a serial monitor to the Motor Driver.
  • This is the type of code you would use in your own projects to control your motors.

The Sketch uses an "X" command, similar to what we have for the Motor Driver.

  • The "X" command does not go to the Motor Driver, it is used to tell the Arduino to get data from the Motor Driver.
  • The Arduino will then use the data received to show the information we need.
  • When writing code for your own project, you will use the code within the "X" command to get information.

To show the best potential of the Motor Driver I will be Using the Scenario [Quadrature Encoder]

  • You can wire up the other Scenarios if you like.
  • All can be wired.
  • I will be using my next partially built project, I have been working on the Motor Driver before going further with it.(We have to make sure something is going to work before the next stage, right!)

I have made a flow chart to show a typical setup.

Step 16: In Action on a Project I Am Making [Motors]

I will be doing an Instructable for the Robotic Arm once it is completed, but there is so much to it, some of the things I am making are projects in them selves.

This is the first stage of my Robot Arm.

  • At this stage I was testing out my New Motor Drivers to make sure all worked as I hoped.
  • In the video the first 16 minutes is testing the Drivers.
  • After 16 minutes I just added some information about some difficulties I found about the "Arduino NANO 33 IoT", It will only be of interest to those that have an "Arduino NANO 33 IoT".

Step 17: Some Progress of My Robot Arm [First Section]

I thought I would just add this video so that you could visualize where this is going.

Robotics Contest

Participated in the
Robotics Contest