Welcome! Log In Create A New Profile

Advanced

Questions on driving DC motors with Arduino using PWM

Posted by GeertB 
Questions on driving DC motors with Arduino using PWM
November 10, 2008 08:21PM
I built the DC motor driver kit from rrrf.org, which was straightforward and seems to work as expected. (Thanks, Zack, for your great service in providing these kits!)

As my hope is to build a repstrap using Fischertechnik (FT), I thought I'd start by controlling the FT DC motors I have. As these motors are rated 6V, I used a 7.5V power supply for the DC driver instead of 12V. This gives enough room for the 7805 to produce 5V and gets me close to the required voltage. The motors seem to have about a 40 Ohm resistance (when stalled), and my expectation is that a 0.5W 10 Ohm resistor in series should drop the voltage to about 6V. My initial tests are without the resistors though on faith that the motors won't die from some quick tests.

I expected to be able to use the PWM to drive the motors reliably at low speed, especially with the higher voltage, but this doesn't really seem to be the case. They only start turning when the duty rate exceeds about 40%, before that I only feel vibration on the output shaft. When I first got the FT motors, 25 years ago, I used them with a Fleischmann model railway train controller which both varied voltage and used PWM in some unspecified way, allowing for very good speed control. Of course the main purpose of the train controllers was to allow trains to gradually slow down and speed up, and they lived up to their task.

My question is: how well should I expect to be able to better control the speed of DC motors with the Arduino and my L293D based drivers? Would I maybe need some additional capacitors to smooth out the PWM signal, or would that be counter productive? Can (and should) I change the switching frequency that the Arduino uses? Any other tips?

As the driver already has 100nF capacitors to smooth transients and as the L293D already has diodes to prevent the motor from trying to deliver power to the driver chip during the off-phase, it would seem further fiddling is not really called for. Maybe at low speeds, the switching frequency should be lower, so the motor won't completely stall? Maybe I should even revert to explicitly switching the PWM signal on and off in software based on feedback from a rotary encoder or even by measuring the voltage over my resistor and thus current through the motor?

Anyway, my initial thoughts about using DC motors in a closed-loop system for positioning seem more dubious. Without good speed control there is no hope for fast and accurate positioning.

Please let me know if you have any tips on driving DC motors using PWM, or if you have links to helpful articles on the web.

-Geert
jbb
Re: Questions on driving DC motors with Arduino using PWM
November 12, 2008 11:39AM
Hi Geert

I haven't had anything to do with the DC motor board myself, but I can offer a few hints...

I've noticed this effect before when I was cooking up a quick motor driver - it took a surprising amount of 'voltage' before the thing would start spinning. One thing you could test is to see what happens when you apply a low DC voltage to the motor - some of them just need a bit of a kick to get going even without PWM.

If you want to filter the PWM output into a DC value before applying it to the motor it is certainly possible, but you will need to add some inductance to the system. If you have a look at
[en.wikipedia.org]
you will see that this type of system needs an inductance to operate correctly. Currently the internal inductance inside the motor is doing that for you. One way to think about is that the switching chip provides a controlled DC signal plus a whole lot of high frequency crud. Some form of filter is required to get rid of the high frequency components - and an inductor is perfect for it.

In terms of control response, unless you go to extreme lengths with your control system you +will+ need some form of motor position sensor. It is possible to estimate the speed and torque of a DC motor by measuring its terminal voltage and current, but the motor position is a more difficult matter. One approach is to simply say that the motor position is the integral of the motor speed (i.e. position = speed * time), but this is not practical - a speed error of even 0.1mm/sec linear equivalent will have your repstrap drifting at 6mm per minute.

If you look on the RepRap wiki there are a few position sensor boards that people have developed - magnetic, optical etc. One of these should do the trick.

I'vew run out of time now, but I'll try to come back later with some references on DC motors and PWM.

jbb
jbb
Re: Questions on driving DC motors with Arduino using PWM
November 13, 2008 04:32AM
Hi again.

I had a quick hunt around online, and found a fairly good description from ST Microelectronics:
[www.st.com]
[www.st.com]

Obviously you can implement all of these control functions inside a microcontroller by using an ADC (or two) and a PWM output.

The speed sensing approach they suggest would be quite effective, but has two minor problems: 1) you must drop the motor operating current to zero which will cause a speed ripple and 2) you'd have to modify the motor driver PC slightly to allow you to turn all the switches off.

The basic ELECTRICAL equations of the motor are quite simple:

(1) v = emf + Rm*I + Lm*dI/dt
(2) T = kt*I
(3) emf = w/kt

Where:
v is the motor terminal voltage in Volts
emf is the internal voltage generated inside the motor by the rotor windings cutting through the magnetic field
I is the motor current in Amps
Rm is the motor DC resistance (measure with a multimiter) in Ohms
Lm is the motor inductance in Henries
T is the torque in Newton Meters
kt is the torque constant parameter in Newton Meters per Amp
w is the machine speed in radians per second. To convert to RPM multiply by 30 / pi

Therefore the internal EMF and speed of the motor can be estimated by:
(4) emf ~ v - Rm*I
(5) w = kt*emf

Unfortunately the motor resistance Rm will change by quite a bit as the motor heats up. A 50% increase in resistance would not be unusual. This means that speed estimation techniques are always a bit inaccurate.

However, the interesting result of these equations is that the motor torque can be easily controlled as it is directly proportional to the current.

In order to achieve high performance control of the machine it is very common to implement a set of nested control loops:

INNER LOOP - the innermost loop controls the motor torque by current control. This would be quite fast - response times on the order of single milliseconds. The controller would compare a torque reference signal with the motor current (scaled by kt) and adjust the PWM duty cycle with a Proportional-Integral (PI) controller.

MIDDLE LOOP - the next loop controls the speed of the motor. The controller would compare the motor speed with a reference signal and provide the torque reference signal to the inner loop. Once again this would be a PI controller. If the output of the controller is limited to a suitable value this will limit the motor current and protect it against overcurrent. This control would act in the tens of milliseconds range (subject to machine torque limits).

OUTER LOOP - the outer loop controls the motor position. It would compare the measured position of the axis (however you do it) with the desired position and provide the motor speed reference to the middle loop accordingly. This loop will be responsible for providing advanced functions like constant speed control, ramping etc.

As you can see, the control systems required for precision DC motor control are quite extensive. The design of each control loop is quite important and can be quite tricky to get right until you have some experience and get comfortable with them. That being said, this approach can provide excellent quality motion control (much better than steppers). A modern PIC or AVR would be capable of implementing all these functions, but the overall speed of response will be limited by how rapidly the ADC can take samples.

In case you were wondering, the controls for a Brushless DC (BLDC) motor are quite similar except that the current control loop is a lot more fancy. DC motors actually have slightly better performance though!

If you want to continue along these lines I would suggest a visit to the OpenServo community who have already gotten into this kind of thing.
[www.openservo.org]

Hope this helps.

jbb
Re: Questions on driving DC motors with Arduino using PWM
November 13, 2008 01:26PM
Thanks for the very detailed explanation. It will take me a while to fully digest this as well as the great introductions you linked to.

Regulating current to the motor seems indeed the way to go, so now I'll have to figure out what the best way is to determine how to measure the amount of current my L293D produces on its output channels. A complication is that the current can flow in two directions through my sense resistor. It would be great if I could also use the current sensing to prevent shorts or too large motors from damaging the motor drivers.

In my experimentation so far, I've found that when the PWM duty cycle gets below 60% or so, it is best to use 5ms of 60% PWM and then 15ms of the desired duty cycle. That let's me get down to about 25% and very low RPM without the motor stalling completely. My modified DC motor test program now speeds up and slows down the motor beautifully smiling smiley

-Geert
jbb
Re: Questions on driving DC motors with Arduino using PWM
November 14, 2008 12:25AM
Glad I'm being helpful.

As regards the motor current control, there are a couple of ways you can approach it.
1) You could sense the current from the L293D earth pins, but that won't tell you the direction of current flow through the motor (the H Bridge can also act like a rectifier). Additionally it'd also give you the current for both motors added together, so I think that this approach is a bust.
2) It might be tempting to place a sense resistor in series with the motor and use a differential amplifier to sense the current. THIS WON'T WORK because the voltage across the resistor that you want to sense will be quite small and the _average_ voltage of the resistor (common mode voltage) will be flicking up and down very fast as the L293D does the PWM. This will completely ruin the performance of the differential amplifier.
3) You could replace the two low side transistors with discrete ones and sense their emitter currents, as shown in the first LT publication. More bits but it works well. Note that for rapid switching your base drive circuitry must be able to pull base current OUT of the transistor. A medium value resistor (1k) from base to emitter will usually help here.
4) You could use a fancy pants isolated current sensor such as the ACS712ELCTR-05B-T from Allegro. The magnetic field generated by the current is sensed, scaled and delivered to you as a 0 - 5V signal. They cost around US$2 a unit from digikey.com

I can't really suggest what would be the best way forward here - I am currently doing a PhD in the control of generators with power electronics, so my perspectives on what's easy enough to build are a little skewed... My personal preference would be to design a wee board with a high efficiency MOSFET H Bridge and current sensing on the -ve rails as suggested by LT.

An additional thought I had was that the current control loop could be implemented in all analog electronics so that you don't have to worry about high sampling / control rates inside your MCU. It would also give you some protection against software problems as even if the system crashed an axis the total force/current/torque would be limited.

jbb
Re: Questions on driving DC motors with Arduino using PWM
November 14, 2008 07:06AM
Geert, et al,

I'm not familiar with the FT motors, but I suspect they're geared with a fairly high ratio -- and thus have substantial friction, even without being coupled to a load (which usually adds more friction.) Even with perfect electronics, the friction will still eat much of your torque, ~ 40%! Better torque estimation (e.g. by current measurement) might help, especially if used to model (and compensate for) as much of the friction as possible.

However, you might do well enough by adding a friction/stiction compensation term (starting at/just below 40% of full scale), and adjust the level for best performance that doesn't de-stabilize the motor. (Over-compensating for the friction will result in a motor that can't hold still -- much like an antsy child.) This approach may be more bang/buck than careful (read difficult) measurement of fine electrical issues when the friction is likely the main culprit. (It pains me a bit to say this, having designed/build torque sensors to deal with drivetrain friction in robots, but I don't think a torque sensor is a good fit for this problem -- too big, costly, complex. Sigh....)

IMHO, the unsteady nature of the PWM signal is probably helping (rather than hurting), by providing a de-facto dither (AC) signal superimposed on the DC levels. Dither is often used as a means of mitigating friction.
Googling: dither friction control
brings up lots of hits.

Hope this helps,

-- Larry
Re: Questions on driving DC motors with Arduino using PWM
November 18, 2008 08:47PM
Hi Larry,

Yes, indeed they are geared with a high ration and have a lot of friction. The problem with the Arduino's default PWM seems to be that the switching frequency is too high, and so there never is enough momentum to overcome the friction and stiction. (Great word!) So, adding my own course switching at 50 Hz for low speeds seems to work fine. I am wondering if it is possible to specify the clock used for PWM on the Arduino.

In the mean time I built a little control box for the FT motors that is to be used by my 6-year-old son. I'm stuffing an Arduino, breakout shield, [www.reprap.org] motor driver, potentiometer, on/off switch, push buttons, leds, piezo buzzer, 9V battery and external power connector in a small RS project box. Very tight in there... (need to figure out how to access the USB connector for programming and test output, as there is not enough room for a connector: is it possible to disable the USB interface and use a regular 5V serial connection on the Rx/Tx pins? Or is my only solution software serial?)

For this subproject, motor speed should be proportional to potentiometer setting (smoothly switching between forward and reverse), acceleration and deceleration should be controlled giving the impression of inertia, stalls and overcurrent avoided. Furthermore, agressive power management should turn off the system when it becomes inactive, as well as be generally as frugal as possible during control and in driving the system.

Also, as extra complication, short circuits of the motor outputs must be tolerated (certainly easier than preventing them with a kid). As I found there seem to be no fuses or PTC's that will react anywhere near fast enough to prevent damage to my L293 drivers, I put a shunt resistor of 0.5 ohm in series with the power supply for the drivers. I plan to connect the shunted Vcc through a 10:1 voltage divider to an analogue input. Combined with the internal 1.1v ADC reference, this will allow me to accurately measure current to the drivers. Either through polling, or ideally through an analog comparator and interrupt, high currents should switch off power and sound an alarm.

I'll probably need some additional small resistors in series with the output terminal to limit peak currents in case of a true short. Will the Arduino be fast enough to disable the drivers before they get damaged and before power to the microcontroller itself is compromised? Time will tell. My initial goal will be to detect shorts at startup and detect limited overcurrent during operation. Reacting fast enough to deliberate shorts during operation will be the holy grail.

In the evening hours I'll be playing with the controller and external feedback to experiment with driver software to see how far I can push the motors to quickly and accurately move to target positions at predictable speeds.

-Geert
Re: Questions on driving DC motors with Arduino using PWM
November 19, 2008 06:57AM
Geert, et al,

Low-side current monitoring is easier, but won't catch all shorts. High-side is trickier, dealing with a small delta on a large common voltage. You might see if there's a "current monitor" IC that's simple/cheap enough to try. Allegro makes some, and likely others.

Adding decoupling on the CPU supply (or beefing it up), may give the CPU enough time to disable the PWM channel(s), provided your current sensing can trigger an interrupt. Since the CPU current is small (compared to the motor draw!), an LC filter is a possibility for this -- iff you have any chokes (L) handy.

Your son is a lucky boy. Now I'm feeling some daddy guilt that I haven't made such toys for my kids. I hope to address that with my repStrap, sometime soon.

-- Larry





GeertB Wrote:
-------------------------------------------------------

> Also, as extra complication, short circuits of the
> motor outputs must be tolerated (certainly easier
> than preventing them with a kid). As I found there
> seem to be no fuses or PTC's that will react
> anywhere near fast enough to prevent damage to my
> L293 drivers, I put a shunt resistor of 0.5 ohm in
> series with the power supply for the drivers. I
> plan to connect the shunted Vcc through a 10:1
> voltage divider to an analogue input. Combined
> with the internal 1.1v ADC reference, this will
> allow me to accurately measure current to the
> drivers. Either through polling, or ideally
> through an analog comparator and interrupt, high
> currents should switch off power and sound an
> alarm.
Re: Questions on driving DC motors with Arduino using PWM
November 19, 2008 08:28AM
My short will never be a true short because of the shunt resistor and resistance/inductance in the circuit. I might even put small (1 ohm or less) resistors or chokes in each lead for safety, even though it would waste some battery life. For now I'll assume I'll have a max 4.5A short circuit current.

If I have an ideal 1000 uF capacitor at the CPU circuit, at 9V it could provide 9 milliamp-seconds. So at 4.5 Amps, that is a theoretical 2 milliseconds. Of course, in real life things are way more complicated and I can't even begin to contemplate what the actual dynamics of the system are. I just hope that if I'll manage to have a response time of 100 microseconds or so, I'll be able to shut down the drivers in time.

Experiments with not-quite-shorts and sketches turning on the drivers for fractions of milliseconds at a time will probably teach me wether this may work.

-Geert
Re: Questions on driving DC motors with Arduino using PWM
November 19, 2008 06:12PM
Geert,

I was thinking about caps/decoupling for the CPU, rather than for the motors. Most CPUs are fussy about voltage, so a 1000 uFd cap won't hold the voltage within spec for very long. IHowever, it's still likely to work provided the short causes an interrupt, and your ISR is coded reasonably tightly.

-- Larry
Re: Questions on driving DC motors with Arduino using PWM
November 23, 2008 05:34AM
Larry, I meant decoupling for the CPU. I'd put the capacitor near the CPU, but unless I'd add a diode or so, the rest of the circuit would also be able to draw from the capacitor.

So, I built the hardware and wrote an initial Arduino sketch to check out the current limiting. The main issue I'm confronting now is twofold:
- There is no way to simultaneously sample two inputs
- My supply voltage is not constant, but very much depends on current (internal resistance)

While I see a direct correlation between the voltage (after Rsense) for the DC motor drivers and load of the motor, the result is also influenced by the current draw of the MCU itself and by the internal resistance of the power supply (5 AA batteries in my case). Since a analog-digital conversion takes 100us, measuring the voltage at both sides of Rsense may take too long and cause too much time difference, especially considering currents are switched quickly as result of PWM. I'll do some more measurements to see how the voltage changes as I switch on the motor.

I guess I best use an opamp to measure the voltage over my Rsense, which is 0.5 Ohms and maybe directly drive a digital input to force an interrupt.

-Geert
Re: Questions on driving DC motors with Arduino using PWM
November 23, 2008 09:40AM
Geert,

If you're regulating down for the cpu supply, there's really no reason not to try a diode upstream, to keep the capacitor.

But one thing you might think about is to apply brute force instead of finesse.
Getting a higher current supply might handle multiple motors better. Maybe going up to C cells, or a wall-wart supply. Does an A2D conversion on the Arduino really take 100 microseconds?

-- Larry
Re: Questions on driving DC motors with Arduino using PWM
October 26, 2017 07:09AM
i'm bouncing this very old thread as my questions seemed relevant:

recently i'm thinking about using L293D h-bridge with current sensing for stepper driving
the specs for L293, L293D are here
http://www.ti.com/lit/ds/symlink/l293.pdf

and the pinouts are as follows
1 1,2EN |  VCC1 16 
2 1A    |    4A 15
3 1Y    |    4Y 14
4 GND   |   GND 13
5 GND   |   GND 12
6 2Y    |    3Y 11
7 2A    |    3A 10
8 VCC2  | 3,4EN 9


the trouble is that i want to do *current sensing* for *micro stepping*
i'm initially thinking about measuring current directly off the motor pins with shunt resistors, but the reversing currents makes the design rather difficult
i ran across this innovative solution that uses diodes
http://forum.arduino.cc/index.php?topic=324977.0
but diodes would shutoff when voltages falls to around/below 0.7 volts, this'd create abrupt jumps/drops in the measured currents

of course there is also the l298 h-bridge with built in current sensing pins as well as l293e
http://www.st.com/content/ccc/resource/technical/document/datasheet/82/cc/3f/39/0a/29/4d/f0/CD00000240.pdf/files/CD00000240.pdf/jcr:content/translations/en.CD00000240.pdf

but l293d is considerably cheaper than l298n and l293e on retail sites such as ebay
https://www.ebay.com/sch/i.html?_nkw=l293d&_sacat=0
hence the motivation to stick with l293d

now the questions,
1) are those ground pins separated for each half bridge on the l293d and could i use those ground pins to measure currents relevant to each 1/4 half bridge units on the l293d?
2) if it isn't feasible to measure currents directly off the ground pins for current sensing / chopper control, i'd guess we'd need to fall back to measuring currents in series with the motor outputs pins. the trouble is that this current is reversing. how do we go about measuring that? even with an op amp, it would swing in an opposite polarity when the h-bridge reverses

thanks much in advance
Re: Questions on driving DC motors with Arduino using PWM
October 26, 2017 11:49AM
About 2)
Back in times, when I studied electronics, I've heard of a "precision rectifier" that will show the same value, eliminating diode voltage drop or pos/neg. current.
Re: Questions on driving DC motors with Arduino using PWM
October 26, 2017 01:57PM
ag123, unless you have a passion for retro technology, forget it. For driving stepper motors at the speeds needed in 3D printers, the A4988 and similar drivers are vastly superior to the L293 and L298, and they are inexpensive.

Edited 2 time(s). Last edit at 10/26/2017 01:59PM by dc42.

Delta printer calibration calculator, mini IR Z probe, and colour touch screen control panel: [escher3d.com]

Large delta printer, and other 3D printer blog postings: [miscsolutions.wordpress.com]

Disclosure: I have a financial interest in sales of the Panel Due, Mini IR height sensor, and Duet WiFi/Duet Ethernet [www.duet3d.com].
Sorry, only registered users may post in this forum.

Click here to login