58 posts / 0 new

## Pages

Author
Message

Hello,
I'm controlling a 6V DC motor using a microcontroller (Atmega328) that creates a PWM signal that is fed to a H-bridge (L293D), the problem is that the motor only moves when I set the PWM with a duty cycle of 45% or higher, if it has a lower duty cycle it doesn't move and makes a noise. For duty cycles between 40%-45% if I give it a push with my hand it rotates. I've tried all PWM frequencies that the microcontroller can create and the higher the frequency the higher the duty cycle has to be to make the motor rotate.
But if I use a power supply, directly connected to the motor, it works perfectly, for any voltage.
I noticed that the L293D circuit drops some voltage, and instead of receiving 6V the motor was receiving a bit over 3V, so I fed the L293D with 9V instead of 6V and the motor was receiving around 5.8V, but it made no difference (beside moving faster). I even changed the L293D for a L298N that has lower voltage drops (I fed it with 6V and the motor was receiving the 6V) and is capable of driving higher currents, but it also made no difference.
The power supply I used shows the current aswell and the motor needs around 0.4A (measured when the motor is directly connected to the power supply) to start rotating but when driving the motor through the h-bridge and giving it a PWM with a duty cycle below 45% the motor doesn't move and the power supply shows around 0.13A.

Motor Datasheet:
http://ecksteinimg.de/Datasheet/MO01069/Datenblatt.pdf

What's the reason for this to happen and how can I make the motor to move at slower speeds if I can't use low values? I'm trying to make a PID controller to control the motor position and I need those small values.

What you describe is logical and probably expected.

In a DC motor, the torque is proportional to the average current through the motor. As you decrease the duty cycle, the current also drops. You will reach a point where the torque is not even sufficient to overcome friction, and it no longer moves. The current will be a bit higher when it is not rotating since there is no back EMF. But, the static friction is also higher. So, in some range, if you give it a little push, it might turn. All pretty normal, as far as I know.

Noise will come from a PWM frequency that is too low. You probably want the PWM frequency above 20KHz (to maKe it harder to hear).

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

So it's not possible to make the motor run at low speeds? I know that there is a limit but isn't 45% too high?

The noise isn't a problem at the moment but I don't think the noise (that I'm talking) is because of the PWM, it's sounds more like the gearbox trying to overcome the friction.

Noise may, indeed, be gearbox.

You mention drop through the driver IC. How do you measure that? What is the stalled current of the motor at some known motor voltage? (In other words, connect it to your power supply, measure the current with the shaft locked and measure the voltage across the motor terminals.) This is a key parameter for brushed DC motors.

The spec sheet says that an L293D will drop about 1.4V on the positive side at 0.6A and about 1.3V on the ground side. So, right off, you loose about 2.7V. Clearly, in low voltage systems, you have a major problem with this driver.

IF you had a higher supply voltage, you would be able to run it to a lower duty cycle. BUT (and this is important) it would still stop at the same shaft speed. All you would gain is more duty cycle range (and higher shaft RPM at 100% duty cycle).

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

I measured the voltage between the output pins of the IC when the duty cycle is 100%, without the motor connected. I increased the voltage to make sure that the motor receives 6V but it only made a motor run faster, the duty cycle range was the same.

The stall current is 2.8A at 6V, according to the datasheet. I changed the H-bridge (for one capable of driving higher currents) thinking that it could be limiting the current but the results were the exact same.

The L293D is only rated at 0.6A.

According to those numbers, the motor resistance is 6V/2.8A = 2.15ohms. Thus, even at 3V, you will exceed the driver current rating when the motor starts. And it will be exceeded by possibly enough to damage the driver over an extended time.

I would suggest that the L293D is simply not a good match for your motor and power supply voltage. I do not have any alternatives to suggest.

Does the motor need to turn both directions? If not, you can use a single power FET with PWM to control it more efficiently.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

But I've used a different IC, the L298N, capable of DC current up to 4A, according to the datasheet, and it made no difference. And even if the motor doesn't has a heavy load, will it reach the stall current anyway?

I thought about building a h-bridge with transistor but after trying the L298N I thought that the current wasn't the problem, but I might built one anyway. About that, I've read that darlington transistor are the best for a h-bridge, does it make a significant change?

What is the frequency o your PWM? And what is the voltage oyu are supplying the Bridge chip?  The L293 needs at least 5v to operate properly.  Your Vmotor_supply should be at least 9v/3A due to stall current and the loss in the IC.  AS Jim W noted the one you are using is not well suited for your motor, but as long as you do not stall the motor you should be able to get it spinning.  Also try using phase correct PWM.

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

I'm using a 16 bit timer with 1024 of prescaler in phase correct mode, wich gives 122Hz of frequency wich allows me to use OCR values above 30000.

I started supplying 6V to the bridge chip but because of the voltage drop I set up to 9V wich made no difference beside increasing velocity.

I've tried using a different bridge (L298N) capable of higher current and it made no difference.

The motor is spinning faster because it is getting the proper operating voltage.  A meter reading should prove this.

Since this is a ear motor I would suspect that you need a minimum 50% duty cycle to overcome the gearbox losses.

Do you have a 6vdc motor without a gearbox to test your circuit/code?

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Do you have an adjustable power supply that will deliver an amp at maybe 1V or less?

If you do, I suggest that you connect the motor to this supply with NO driver IC. Then, adjust the supply down until it stops turning. What voltage is this? What you now have is a "sanity check". You won't be able to do any better than this with PWM.

By the way, 120Hz is awfully low for a motor drive PWM frequency! I would make it 10X to 100X higher. But, even with this change, you will not do any better than a DC power supply does.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Most of what I read in your post is normal behaviour of DC motors.

They are not ideal devices and you have to work with (or around) their limitations.

Normal brushed DC motors should be adjustable to about 10% of the max speed or lower.

And with a well adjusted PID loop you should be able to controll it to down to 5% of the maximum speed.

You can get better controllability with higher quality motors. Think about Maxon or Faulhaber (But you won't like their prices).

Higher voltage motors (12V or 24V) usually have a bit higher range in which they can be controlled.

Sometimes cheap motors have a bit more friction when new.

It might help a bit to let it run at max speed for half an hour or so to wear in the brushes so the fit the commutator a bit better.

ka7ehk wrote:
You probably want the PWM frequency above 20KHz (to make it harder to hear).

I do not agree with this.

First the old designs of the L293 and L298 are probably not fit for such high PWM frequencies.

Second I've had better experiences with very low Frequencies. (A few hundrerd Hertz).

With a high PWM rate you almost have constant current through the motor.

The PWM voltage is averaged (integrated) by the inductance of the motor.

This averaged current is not enough to overcome static friction at low PWM duty cycles.

With very low PWM rates the motor gets a current ( = Torque) "jolt" each time the PWM turns on which helps to overcome static friction.

An then during the off part of the PWM cycle the motor will coast a bit.

Above a PWM frequency of 10Hz to 50Hz these "jolts" and "coast" phases are usually not noticable because they are averaged (integrated) by the inertia of the motor.

With a H-bridge there is also a "dead time" between switching of the top transistor off and switching the bottom transistor on. With high PWM frequencies this can limit the controllability of the motor significantly. This is a part of the explanation of why your motor performes less well at high PWM frequencies.

And DC motors almost always make some noise, especially the cheap and/or geared ones.

According to your datasheet: "Geräuschangaben 30CM ( Noise）56dB"

A bit of hum from low frequency PWM is usually not a big problem,  as the hum is somewhat similar as the mechanical noises of the motor.

However a high frequency (10kHz) whine can be pretty annoying.

And also:

The L293D is specified for 1.2A peak and 600mA continous. Your motor can draw up to 2A.

But because the L293D has 4 half bridge drivers you can put 2 of them parralel to get the double output current.

If you have a bunch of them you can also solder a 2nd one directly on top of the first to double it's output current.

Also note that the 6V rating from the datasheet is a DC rating.

There is no problem with using a higher input voltage for your PWM (12V or 15V or even higher).

Using a higher input voltage wil increase the controllability of your motor.

It will start at a lower PWM duty cycle.

Unlike electronic stuff, DC motors are quite robust devices. Don't be too carefull with them.

Just make sure you don't continuously overload the motor. Do not let it consume too much (average) current (It will overheat).

Don't let it's RPM get too high. But this should all be handled by your PID loop later on.

I assume you are using module's such as these and not loose chips?

https://www.aliexpress.com/whole...

These drivers are very old designs (30 years or so) and really need the external diode's to work properly.

Apparently you've tried a lot of different combinatons (Which is good I always want to encourage experimentation :) but this also makes it hard to give general advise.

Can you please try this combination:

1). Use a higher input voltage. (Try 15V).

2). Use a low PWM frequency (Try 200 Hz).

3). Use the L298 chip because of the higher peak current at these low PWM frequencies.

Note that you have already noticed that the motor starts at lower PWM duty cycles if you increase the voltage and if you lower the PWM frequency.

The goal is to get your motor started at PWM duty cycles < 10%.

I would like to know the PWM duty cycle where the motor starts and the PWM duty cycle where it stops again.

Also imporant:

Does your motor run smoothly at a pretty low PWM cycle?

This can also be improved upon by a PID loop, but if it runs smoothly without a PID loop al the more the better.

If this works then you can go on and add the PID loop to control you motor down to even lower RPM's.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

No I don't have a motor without a gearbox, the only alternative would be to remove the gearbox of this one, wich I prefer to avoid since I already mounted it and it will be quite hard do undo it.

Thanks for the idea I will try that.

I can't increase the PWM frequency, if I do so I have to increase the duty cycle to make the motor rotate.

EDIT: for example for a frequency of 8kHz the duty cycle has to be 82%

Last Edited: Thu. Jul 20, 2017 - 07:09 PM

M_Luis wrote:
for example for a frequency of 8kHz the duty cycle has to be 82%
That just does not sound right.

Are you sure? Perhaps if you showed some of the PWM setup code...

David (aka frog_jr)

In the beginning I had the voltage too low because of the voltage drop of L293D so I increased the voltage supplied to the H-bridge and the motor didn't start at a lower PWM duty cycle. But the increase was only 3V so it might not be enough to notice a difference.

I'm using the chips not the modules. Like this one:

https://www.aliexpress.com/item/5PCS-IC-L298-L298N-ZIP-15-IC-DRIVER-FULL-DUAL-15MULTIWATT-GOOD-QUANLITY/32649183724.html?spm=2114.search0104.3.25.CYEWbg&ws_ab_test=searchweb0_0,searchweb201602_3_10152_10065_10151_10068_10084_10083_10080_10304_10082_10081_10177_10110_10137_10111_10060_10112_10155_10113_10114_10154_438_10056_10055_10054_10182_10059_100031_10099_10078_10079_10103_10073_10102_10052_10053_10142_10107_10050_10051,searchweb201603_1,ppcSwitch_5&btsid=9f24e01a-42d1-4b12-9d9e-04d6d09f895c&algo_expid=3112851e-0703-433e-b944-f8a280e07c08-6&algo_pvid=3112851e-0703-433e-b944-f8a280e07c08

And yes I did put the schotky diodes.

I've tried multiple frequencies and the motor runs smoothly for frequencies above 50Hz. But just to make sure I use 120Hz.

Here is the code for the PWM:

//PWM_TIMER1_16bits_///////////////////////////

DDRB |= (1 << DDB1);                                           // PB1(OC1A) as output

// set none-inverting mode

TCCR1A |= (1 << COM1A1) | (1 << WGM11);          // set Fast PWM using ICR1 as TOP

TCCR1B |= (1 << WGM13) | (1<<CS10) ;               // no prescaler

ICR1 = 0xFFFF;                                                      // set TOP to 16bit

Once I used a 8 bit timer in fast PWM mode with a prescaler of 8 wich gives a frequency of 7,782 kHz and to make it rotate I had to set the OCR equal to 210 or higher. (210/255)*100% = 82.35%

Last Edited: Thu. Jul 20, 2017 - 09:31 PM

For an Ali express link you can omit everything after the ...3724.html

PWM motor drivers always do need some beefy caps (1000uF or so) on the power supply rails.

Do you have them?

For an explanation see the datasheet of for example the drv8833 Page 14:

M_Luis wrote:
Thanks for the idea I will try that.

When responding to a specific question, prepend it with @ForumName if it might be unclear to who the answer is.

Have you tried my suggestions from Post #12?

That combination of 3 is likely to get you starting pwm dutcy cycle down.

Just wondering, have you verified with a scope / logic analyser that your PWM duty cycle / frequency is running at the values you think it is?

A USD5 Logic analyser transforms a lot of gueswork and assumptions into knowing.
https://www.aliexpress.com/whole...
http://sigrok.org/wiki/Supported...

For a very brief introduction to what you can do with such a LA see my posts here where I sniffed 1.5Mbps low-speed USB:
https://www.avrfreaks.net/forum/c...

There are also a bunch of good video's on Youtube to show the capabilities of Pulseview with USD5 hardware (and also with more capable & expensive hardware).

A led (+ series resistor) parallel to the motor can also give you a reasonable indication of the average motor voltage.

Can you do Jims suggestion from #11 and post the DC voltage at which your motor starts to run / stalls.

Post a small tables of voltages / currents under no load & with a stalled motor.

This gives us more confidence to confirm that your motor itself is running ok.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Paulvdh wrote:
PWM motor drivers always do need some beefy caps (1000uF or so) on the power supply rails.

Do you have them?

No I don't have them but I will try when I get those capacitors. (probably only on monday)

Paulvdh wrote:
Have you tried my suggestions from Post #12?

Haven't had the time to do it. I will probably do it in a couple of hours.

Paulvdh wrote:
Just wondering, have you verified with a scope / logic analyser that your PWM duty cycle / frequency is running at the values you think it is?

I haven't tried with a scope but I used a LED. I set a low frequency to see the LED turning on and off and measured the time and it seemed fine.

ka7ehk wrote:
If you do, I suggest that you connect the motor to this supply with NO driver IC. Then, adjust the supply down until it stops turning. What voltage is this? What you now have is a "sanity check". You won't be able to do any better than this with PWM.

Paulvdh wrote:
Can you do Jims suggestion from #11 and post the DC voltage at which your motor starts to run / stalls.

If increase the voltage from 0, the motor starts run with 0.9V-1V and the power supply shows 0.4A at that point (no load)

When the motor is runnig and I decrease the voltage the motor stops at around 0.5-0.6V

Paulvdh wrote:
Post a small tables of voltages / currents under no load & with a stalled motor.

I can do that but only on monday. But meanwhile I'm gonna try all the other ideas.

EDIT: About the capacitors, I can't find unpolarized 1000uF capacitors is there a problem to use a polarized in place of the unpolarized one shown in the datasheet.

Last Edited: Fri. Jul 21, 2017 - 11:53 AM

M_Luis wrote:
If increase the voltage from 0, the motor starts run with 0.9V-1V and the power supply shows 0.4A at that point (no load) When the motor is runnig and I decrease the voltage the motor stops at around 0.5-0.6V

The strange thing is that if you motor starts running smoothly ! 1V it is probably OK.

But it draws a lot more current then it should.

If there was a significant amount of drag the motor probably won't start @ 1V.

(Can you swap te motor for another just to make sure the motor itself is not the problem?)

I''ve taken one of my Ali express motors (With encoder & angular gearbox) out of a drawer and also done some measurements. It is a 12V motor

https://www.aliexpress.com/item/...

This motor starts at 1.6V and draws 31mA and stalls at 0.94V and draws 130mA.

U = Motor Voltage.

R = Rotating Current [mA]

S = Stalled Current [mA]

U R     S

1  33  140

2  34  288

3  38  420

4  44  430

5  40  522

6  46  640

7  51  720

8  60  814

9  62  920

From this table you can see that the current when rotating idle is almost constant.

You can also see that the current when stalled is almost liniair with the voltage (You can calculate internal resistance from this)

Because you have a (similar) 6V motor your currents should be twice this.

Note that with my motor one of the hall sensors was bent (during shipping?) and it dragged against the magnet and I had to bend it straight.

How are you measuring the motor current? A DMM in series with the motor can have a significant voltage drop. Use the 10A range.

M_Luis wrote:
EDIT: About the capacitors, I can't find unpolarized 1000uF capacitors is there a problem to use a polarized in place of the unpolarized one shown in the datasheet.

Unpolarised 1000uF capacitors are rare, just use a normal Elco (Even 100uF is probably sufficient for these small motors) (But Use ceramic decoupling caps for the rest).

Just to be clear: Put this cap between Ground and the power supply to the motor. ( NOT directly across the motor ! )

What datasheet are you referring to?

How stable is the power supply you are using?

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Paulvdh wrote:
From this table you can see that the current when rotating idle is almost constant.

My motor, while rotating also as almost constant current but around 0.1A - 0.15A.

Paulvdh wrote:
How are you measuring the motor current? A DMM in series with the motor can have a significant voltage drop. Use the 10A range.

The power supply I used shows current.

Paulvdh wrote:
Just to be clear: Put this cap between Ground and the power supply to the motor. ( NOT directly across the motor ! ) What datasheet are you referring to?

The capacitors are placed between the motor driver's input voltage pin (where the 6V connect) and GND, right?

The datasheet you posted of the DRV8833. In page 14, like you said, the schematic shows two capacitors one polarized and one unpolarized.

Paulvdh wrote:
How stable is the power supply you are using? Does it sag under load?

I've measured the voltage with a multimeter but without any load, so under load I can't tell you.

Take a look at the TB6612 FET-based driver...you will likely be much happier.  Get away from those horrible voltage drops!! The LM293 is pretty old school (of course, so is the 0b1000101011 timer).

When in the dark remember-the future looks brighter than ever.

Last Edited: Fri. Jul 21, 2017 - 04:44 PM

Hello again, so I made some more tests. I tested all IC's with various voltages and I measured the currents (rotating and stall) for different voltages:

From the first table I think the best option is the L298N with 6V, since it's the one that can start the motor at the lowest speed, but I think it's not enough the PID will require lower speeds. The tests, for the START section, were made by incrementing the OCR value, every 500ms, until the motor started to rotate, each value was achieved by making the average of 10 samples. For the STOP section I did the same but decreasing the OCR until it stopped to measure the speed in the STOP section I had to set a slightly higher OCR for the motor to run.

In the second table we can conclude, comparing with the values that you posted, that the motor is working properly.

I also measured the voltage in the IC's output pins for different duty cycles and measured the microcontroller's PWM duty cycle:

I used an oscilloscope and the voltage in the IC's output pins is higher than it should be because the output signal never reaches 0V, in other words if I set a PWM with 0% of duty cycle the IC's output signal has an amplitude of 800mV, If I set a duty cycle of 10% the output signal is 6V during 10% of the period and is 800mV during 90% of the period. Is this normal? If not, is there a solution?

But the main problem hasn't been fixed yet that is how can I make the motor start at lower speeds? Because the motor can run at those speeds it just can't overcome the friction of the gearbox at the start.

This is one of the benefits of servo control - the control loop modulates the amount of energy required so you can run the motor at a crawl but yet get high torque.

From your measurements I conclude that your motor is OK, so that is one thing less to worry about.

(Not that the latest measurements show a constant 120mA when running Idle, but your first statement was 400mA (Or did I interpret it wrong))

Whatever, it's solved.

Your motor is running well at 0.6V and 10% duty cycle of your PWM now.

This is about as good as you can expect from cheap motors.

This also looks OK. So there is nothing wrong with your H-bridge.

M_Luis wrote:
it just can't overcome the friction of the gearbox at the start.

It is not the friction of the gearbox which has to be overcome.

The main friction is from the bearing bushes in the motor itself and the carbon brushes.

There is not much you can do about it.

Note that the gearbox reduces RPM and increases torque. So the torque needed to overcome friction in the gearbox is divided by the gear ratio from the motor's point of view.

One way to limit the slip-stic effect is to give the motor a short higher voltage pulse before your start the PID algorithm.

en.wikipedia.org/wiki/Stick-slip_phenomenon

Also don't forget that when under PID control the motor can rotate slower then when it is not in a control loop.

What is the lowest RPM you want your motor to turn? (motor with a different gear ratio?)

What is the ratio between lowest & highes RPM you want? (1:20 is achievable, above that becomes increasingly more difficult)

And as I said before:

Using a higher input voltage (12V) and low PWM frequency sends torque "shocks" to the motor which help a bit in mitigating the effect of the slip-stick.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Tue. Jul 25, 2017 - 01:56 PM

Paulvdh wrote:
but your first statement was 400mA (Or did I interpret it wrong)

To start rotating the motor needs 400mA then, while it's rotating the current is around 120mA. In other words, using the power supply, I start at 0V and slowly increment the voltage when it reaches around 1V the current reaches 400mA and then the motor starts running and the current decreases to around 80mA and stays at that value while it's rotating.

Paulvdh wrote:
Your motor is running well at 0.6V and 10% duty cycle of your PWM now.

It's not running well with the PWM, the motor runs with about 13% duty cycle but I can't start it at that duty cycle (even though it is receiving 1.25V at 10%) it only starts with 30% duty cycle. Is that what you mean? Is that how it's suppose to work?

Paulvdh wrote:
What is the lowest RPM you want your motor to turn? (motor with a different gear ratio?)  What is the ratio between lowest & highes RPM you want? (1:20 is achievable, above that becomes increasingly more difficult)

I don't have specified values I just want to it to run at low speeds so that the PID, as the capability to make small corrections. Because at the moment what I'm doing is whenever the output signal of the PID is lower than minimum duty cycle than the duty cycle to apply is the minimum duty cycle, but that just makes the system oscillates whether the proportional gain is 1 or 200 ( I only tested with proportional gain so far). If I don't make that correction the motor doesn't move because it's not being applied a duty cycle capable of making the motor move.

Why are you wasting your time with these crummy bipolar parts that drop volts?  Use a fet driver chip & drop a few hundred millivolts

At 1 amp, this would drop 0.4V, at 1/2amp would drop 200mV (have to look carefully if the resistance is given as TOTAL or PER LEG)

https://www.infineon.com/dgdl/Infineon-TLE5205_2-DS-v01_01-en.pdf?folderId=db3a30431b3e89eb011bb632994f065b&fileId=db3a30431f848401011fc747c7a0797f&ack=t

also see the allegro A4930, it has low Rds drop

www.allegromicro.com/~/media/Fil...

http://www.st.com/content/ccc/resource/technical/document/datasheet/group1/7f/8a/6c/96/c8/24/49/f6/CD00002345/files/CD00002345.pdf/jcr:content/translations/en.CD00002345.pdf

Do you have a speed sensor?  If so then voltage drop won't matter (much), since the pwm (gas pedal) will be automatically adjusted by software to maintain speed...regardless of any voltage drop.

When in the dark remember-the future looks brighter than ever.

Last Edited: Tue. Jul 25, 2017 - 03:04 PM

M_Luis wrote:
Is that what you mean? Is that how it's suppose to work?

Yes, this is normal.

M_Luis wrote:
I don't have specified values I just want to it to run at low speeds

300rpm is a low speed to me. So I ask again: What do you think is a low speed?

@avrcandies

There are 1000's of better motor drivers with better efficiency and lower bom count (external diode's) but the chip's OP has are capable enough for the job at hand.

avrcandies wrote:
Do you have a speed sensor?

OP's motor has a multi pole magnet with 2 hall sensors in quadrature (See his datasheet).

----------

So your hardware (motor & H-bride) work as best as you can expect in this non perfect world.

The next job is to mitigate the effect of this non perfect world in software untill you are happy.

It's good to start with only a "P" action, It's nice and simple.

School textbook PID examples almost always assume a perfect (liniair) world.

The Real-world slip-stick effect is non liniair.

When you only have the "P"-action it helps to add an ofset between the PID loop and the PWM output control.

Make the offset so big that the output just does not turn yet when the PID control outputs Zero.

And use signed values for the PID variables. In that case they can go negative and substract a bit from the offset you add if it is too big...

But when you add the "I" -action it will integrate over the non-liniair slip-stick untill the motor starts rotating.

I do not see much gain in also adding the "D" -action for simple motor control. PI should be enough.

Your magnet probably only has < 10 poles. It is enough for decent control, but it is near the minimum.

What algorithm do you use to calculate the motor speed from the Hall -sensor input?

(A very accurate way would be to measure the time between each flank of one of the Hall sensors).

I've attached the software for PI(D) control which I've written myself some years ago.

It might be a bit difficult to read even hough I tried hard to make the code readable.

There are lots of extra things in there to compensate for the non perfect world.

Gees, I almost forgot, I put it on the web some time ago:

www.hoevendesign.com/#NetworkRol...

One of the fun part of this project is that it does not use a H- bridge at all.

It uses a double pole relay (Which only switches when there is no current flowing) (unless PID goes haywire...)

and it uses a single TO220 N-MOSfet for the PWM (Good for multiple amps, 10 or more, depends mostly on the MOSfet & gate driver used).

Note: One of the motors I control is from a 6V accu drill but the "H-bridge" input is a 15V 40A power supply. It has been running for about 10 years now (Runs 2x 10 seconds every day).

But I digress.

Study threadmotorcontrol. It has lot's of real life info which is not handled in simplified Textbook PID exmples.

## Attachment(s):

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Tue. Jul 25, 2017 - 03:38 PM

Paulvdh wrote:
300rpm is a low speed to me. So I ask again: What do you think is a low speed?

Maybe the easiest way to explain is by showing what I want. I'm trying to do a hardware demonstration of a PID controller just like this one: https://www.youtube.com/watch?v=fusr9eTceEo

And if you skip to minute 1:34 you can see the integral part in action by making the motor rotating really slow into the desired position, in my case that doesn't happen, mine when the error is small the motor doesn't move and after a while, when integral term as accumulated enough, it moves really fast and overshoot and stops again with a small error and repeats the same thing. And I would like that my system to do that, for the user to see the integral part in action, and also, I can't quite understand how can the system work properly without being able to do small corrections.

Paulvdh wrote:
What algorithm do you use to calculate the motor speed from the Hall -sensor input? (A very accurate way would be to measure the time between each flank of one of the Hall sensors).

I think I haven't explain very well what I want (for my owm fault), and as you can see in the video above I don't want to control velocity, I want to control position so I only determine motor position, the angle (I actually did a algorithm for velocity for the tests that I showed in the tables above, but what I basically did was the derivative of the angle using a timer's interrupt and then convert it to RPMs).

So the input of the PID is the position error and the output is the OCR value (duty cycle). Maybe the problem is just a bad tuning?

Last Edited: Tue. Jul 25, 2017 - 06:44 PM

Just re-watched the video.

It certainly is a nice demonstration of PID.

Unfortunately it has very little info on the motor used, gears, sort of encoder, hardware etc.

Just below his video he links to:

https://github.com/arduinoNube/d...

But you can not do this with your setup.

Note that his control system can measure the error if the tip of the pointer is just a few mm from the middle of the scale.

You will need a higher resolution encoder to be able to control a motor at such low speeds.

(Have you seen those inverted pendulum video's? They're fun)

M_Luis wrote:
see in the video above I don't want to control velocity, I want to control position so I only determine motor position, the angl

Not so true.

It is very common to use multiple control loops nested into each other.

I also only want to controll the positon, but if you want to move to a position you need speed.

Also: To generate speed you need torque.

DC Motor torque is directly proportional to the current through the motor.

A lot of control algorithms use this to get even better control of the motor, but I didn't do this.

Note that the motor current is very easy to measure by putting a shunt resistor between the bottom of the H-bridge and GND. Amplify with an opamp and use your uC's ADC to measure it.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Tue. Jul 25, 2017 - 08:34 PM

Paulvdh wrote:

I have downloaded the files and read the code and I can't see anyting different from mine.

Paulvdh wrote:
You will need a higher resolution encoder to be able to control a motor at such low speeds.

From my math the encoder has a resolution of 0.88º wich is 0.9839mm of the circle's perimeter I think that is good enough. No?

Paulvdh wrote:
(Have you seen those inverted pendulum video's? They're fun)

Now it's too late to change :)

But anyway I'm gonna play around with the PID parameters and see if I get somewhere.

Once again thanks for all the help.

M_Luis wrote:
From my math the encoder ...

From the info I have I gues it's a 6 pole magnet and a 1:10 gearbox

360/6/10 = 6 degree resolution.

M_Luis wrote:
of 0.88º wich is 0.9839mm of the circle's perimeter

Compare that with a sensor like HMC1501

https://aerocontent.honeywell.co...

which states an angular resolution of 0.07 degree

Or with the AS5045 which has a 12 bit resolution and a digital interface:

http://ams.com/eng/Products/Magn...

And it's also affordable from Ali as a nice set with matching magnet:

https://www.aliexpress.com/item/...

But tripple inverted pendulums sure are impressive:

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Paulvdh wrote:
From the info I have I gues it's a 6 pole magnet and a 1:10 gearbox 360/6/10 = 6 degree resolution.

Sorry I forgot some steps, this is how I did:

The encoder's datasheet says it's a 14 pole magnet with 7 pulses per revolution which means, after the gearbox, 70 pulses per revolution, but I measured with an oscilloscope and it outputs 102 pulses per revolution and detecting both rising and falling edges of both channels (X4 encoding) I measure a total of 408 pulses per revolution. If in 360º I have 408 edges, 1 egde is equal to 0.88235º.

Paulvdh wrote:

I'm using something smaller, like 20cm or even smaller.

Perimeter of the circumference = 2*pi*r = 2*pi*0.2 = 0.4*pi meters

(0.88235º / 360º) = 0.00245

0.00245 * 0.4*pi = 0.0031 meters = 3.1 mm

Probably I'm gonna use a 15cm rod to reduce the value.

Last Edited: Wed. Jul 26, 2017 - 09:14 AM

At smaller pwm pulse use higher voltage with linear ratio pulse -voltage.
Use pwm freq about 4k to 10k. Don't worry about noise. It happen when you do pwm speed control. Put ceramic/tantalum capacitor (depends on how big is your motor) at your motor connection to reduce noise.
Even KUKA robotics produce preety loud noise while lift heavy load at very slow speed.
.
MG

I don't know why I'm still doing this hobby

Last Edited: Mon. Jul 31, 2017 - 04:34 AM

Tantalum capacitors at the AC side of a H-bridge are not a good idea.

But why respond at all? OP seems to be happy with a working setup for 6 days now.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Paulvdh wrote:
OP seems to be happy with a working setup for 6 days now.

Actually I'm not very happy still xD. I've been too busy to post anything.

I bought a new h-bridge module, the tb6612 like avrcandies suggested and now the motor works perfectly with a pwm signal, it has almost the same performance as when supplied with dc voltage.

But the Integral part of the PID still has the same problem that I explained in a previous post:

M_Luis wrote:
Maybe the easiest way to explain is by showing what I want. I'm trying to do a hardware demonstration of a PID controller just like this one: https://www.youtube.com/watch?v=... And if you skip to minute 1:34 you can see the integral part in action by making the motor rotating really slow into the desired position, in my case that doesn't happen, mine when the error is small the motor doesn't move and after a while, when integral term as accumulated enough, it moves really fast and overshoot and stops again with a small error and repeats the same thing. And I would like that my system to do that, for the user to see the integral part in action, and also, I can't quite understand how can the system work properly without being able to do small corrections.

So since the new bridge didn't solve the problem I guess you we're right about the L298N being fine for this project. Either way I'm gonna use the new bridge because it's more stable.

At least now I know that neither the motor or the h-bridge is the problem and now I can focus in the software.

With PWM you really only have a certain number of settings (10 bits gives 1024 possible levels, etc)  For starters, do this:

assume you have a desired speed in mind

A) measure your speed, say every 10ms

B) every 10ms compare your speed to the desired

C) If measured speed is way too low (say by 2, 5, or 20 measurement counts) ,increase the PWM by 1 count (up to the max PWM limit)

D) If measured speed is way too low (say by 2, 5, or 20, measurement counts), decrease the PWM by 1 count (zero, is the min)

E) If neither C nor D are true, make no pwm adjustment

F) repeat A-E

When in the dark remember-the future looks brighter than ever.

M_Luis

Your main problem is not understanding that your motor is not a voltage driven device. It is current driven. The on time of each pwm pulse must be longer than the motors L/R time constant in order to reach its rated current . A typical inexpensive dc brush type motor will have multiple mH of inductance and a few ohms of resistance. If the motor does not reach its rated current with short pulses (low speed), it will have little or no torque. The only way to correct that is to use higher voltage and use current sensing to end the pulse when the rated current is reached, or use a much lower frequency.

That is how stepper motors rated at 2.5 to 5 volts & 200 steps/sec can reach several thousand steps/sec in table top cnc routers when operated at 30 to 80 volts.

A clamp on current probe is absolutely the thing to use (such as http://www.ebay.com/itm/TEKTRONIX-TM502A-WITH-AM-503B-A6302-PROBE-TRAY-Nice-/382159800052?epid=1783937380&hash=item58fa7fc6f4:g:Qk4AAOSwSzFZY93n )...then you can see if your pwm current pulses have time to flat top at your low duty cycles (looking like a rounded square wave, with a flat top).

You can see the current using a series resistor & view its voltage drop (I=V/R), but you need to use a low value (such as 0.1 ohm)...so as not to grossly affect the L/R effect you are trying to check!  Really, all you need to do is check the shapeThe easiest thing to square it up is to lower the PWM freq & determine if it is acceptable performance & noise-wise.  You could add series resistance, so it reaches the peak (flat top) quicker timewise, but that peak will be lower, hence not so good (unless you compensate by using a higher supply voltage).

When in the dark remember-the future looks brighter than ever.

Current and voltage are not controlling the speed of your DC motor, they are controlling torque. If you give it too little current (and therefore voltage because of Ohms Law) you're giving in so little torque that the motor can't even spin its rotor, let alone anything connected to it. If you need slow speeds either add a reductor or drive it in a closed loop with encored feedback as suggested in post #38.

Accept that there is going to be a dead band where there simply isn't enough energy to move the motor. Either add code to step over the dead band or increase your proportional gain.

In theory, PID should take care of all situations. It is an art tuning it properly. But in order to do its job, you need to provide the proper hardware.

I see people suggesting lower and lower PWM frequencies. Like everything in life, this has its drawbacks. I believe that you once set a PWM value in the register, that is there until the next timer rollover. Now imagine that your integrated error is increasing the PWM duty cycle to a point that the motor starts spinning. This value corresponds to a speed that is too high. With a low frequency, the timer started, there is no way you can back off immediately. Your error derivative would want to reduce the PWM right away, but it only can do so on the next PWM cycle which is too late. Even if it could, I believe the energy in the motor coil now is wasted in a diode in the H bridge, which takes time to disappear. Here you would need the H bridge to be off completely or to slightly power the motor in reverse. You know better your situation there, I just explain some inner things.

In conclusion, as someone suggested, to have high dynamics, you need higher voltage, higher PWM frequency (I would say about 400 - 1000Hz) and the PID loop running at least two times PWM frequency. In other words you need to be more aggressive with your motor. Also, at low speeds, you should measure the time between two pulses of your encoder, at higher speeds, switch to measuring the frequency as the period measurements would take too much CPU resources. Use a hysteresis to switch in between the two.

You case is somewhat unfortunate as you have a geared motor. The motor (almost) only sees its own rotor moment of inertia which is low, so the fast start. Things gets better for a direct drive case.

Old cassette tape players / recorders had a simple DC motor with an external IC, no encoder. The speed regulation is done by measuring the current and voltage across the motor. Later they introduced centripete switches on the rotor.

George.

If you set your pwm value (0-1023 range ) to 50 do you get any rotation?  , how about 10?, 20?, 100?  etc.  For a fixed PWM value (no pid or automatic adjustment) , how steady is the rotation at low speed ?  Do you see a lot of cogging or chugging?

Your control response stability is probably much more affected by the rate of measurement (5 times a second, 10 times, a second 100 times a second, etc) than the pwm freq , which will occur much faster.

When in the dark remember-the future looks brighter than ever.

First of all thank you everyone for the help.

I read all your ideas and I tested them, and here is what I concluded:

- changing PWM frequency didn't make any difference, at least didn't make a significant change to notice.

- I can make the motor START rotate with a OCR around 55 (1-348 range) wich is a duty cycle of 15.8%. If I supply the motor with a dc power supply the motor STARTS to rotate around 0.9V, since it is a 6V that's the same as a 15% duty cycle.

I can make the motor rotate with lower voltages or PWM duty cycles if the motor is already rotating before lowering the duty cycle/voltage to minimum of 0.6V or 10% duty cycle or OCR of 35 (1-348 range).

I did the PWM tests for frequencies of 23kHz and 122Hz and the results were the same. And from what I can tell the motor runs smoothly with low dut cycles.

So everything right here, and I think we can assume that there's no problem with the current not fully loading during the on time of the PWM signal. Am I correct?

-About the PID, someone suggest adding to the output the minimum value to make the motor rotate, I had already tried that but it just makes the system oscillate alot around the setpoint and changing the PID gains doesn't make any difference, the system response is the same no matter what the gains are.

I also increased the PID frequency up to 800Hz (calling the PID interrupt every 0.00125 seconds) and it also made no difference.

Here are some images of my system response with a PI controller:

The blue line is the angular position of the motor's axis. As you can see the motor stops and stays like that for 2.5 seconds (this time isn't always the same), until the integral part sums up enough to make the motor move, sometimes achieves the setpoint, sometimes overshoots and it waits again for the integral part to sum up enough (changing signal also) to make the motor move again. What it's weird is that sometimes, just like the one you can see in the image (at 3.5 seconds), it overshoots but it was able to correct that small error instantly.

Another problem that is happenig can bee seen in the next image:

The blue line is the angular position of the motor's axis, the orange line is the output of the PID and the red line is the integral term. The behavior is the same as the last case but when it reaches the setpoint it oscillates alot and doesn't stop, sometimes it stops but it's very rare to happen, and some of those rare occasions it starts to oscillates again. And ir seems that the more the system is ON the more likely is for this to happen. This only happens when using a PI or PID controller with a PD or P controller it doesn't happens so the problem is the I term (the red line is also oscillating even though it doesn't look like, but if you compare to the red line in the beginning of the graph you can see that the line is different). I manage to "fix" this setting the duty cycle equal to zero whenever the error is zero, but it doesn't feel like the correct thing to do. Any idea what's the problem?

About the first image from what I read in your comments and my tests I think that there is no solution for that problem, right?

I'm also gonna leave my code just in case.

```ISR(TIMER0_COMPA_vect)		// interrupt PID
{
angulo = (encoder*360)/(4*102.0);   //angulo is the angle variable
erro = setpoint - angulo;

d_term = (erro - erro_ant)/0.00125;

output = kp*erro + ki*i_term + kd*d_term;
//anti-windup
if (fabsf(output) >= OCRmax && (((erro >= 0) && (i_term >= 0)) || ((erro < 0) && (i_term < 0))))
{
i_term = i_term;
}
else
{
i_term = i_term + (0.00125*erro);
}

erro_ant = erro;

if (angulo == 0)
{
setPWM(0);
}
if (angulo > 0)
{
direcao(0);             //change rotation direction
setPWM(fabsf(output));
}
if ( angulo < 0)
{
direcao(1);             //change rotation direction
setPWM(fabsf(output));
}
}

void setPWM (float duty)
{
if (duty > OCRmax)
{
duty = OCRmax;
}
OCR1A = duty;
}```

I assume you are trying to control the position of the motor arm, not the rotational speed (hence you ultimately want zero rpm)-correct?

How often does the ISR run?  That will greatly affect the motor response, especially if called less often.   Maybe try 20 times a second.  If the processor was replaced by you adjusting a knob 20-50 times every second, would you feel satisfied with the result?  Probably.

Why are you using floating point?  There is certainly no need to burden your system so heavily.

Are the calculations actually producing real results (not just on paper).  For instance, integers must stay within certain ranges.

is this actually producing an iterm value in your variable:  i_term + (0.00125*erro)

Just clip your I_term so it cannot exceed some preset limit  (say I_term_max=3, I_term_min=-3), or whatever limit is usable), you don't need to look at OCR_max

Why not spit out your p,i,d values when running, so you can see what they are doing?

You can get very stable and fast motor position response with about 40 lines of assembly--maybe give it a try.

When in the dark remember-the future looks brighter than ever.

but when it reaches the setpoint it oscillates alot and doesn't stop, sometimes it stops but it's very rare to happen, and some of those rare occasions it starts to oscillates again

How you determine that the motor has reached the correct position so the motor does gets off power ? Reading the encoder ? In any case, you need to have few encoder counts plus and few encoder counts minus where you are comfortable as a destination position.

The fact that it takes 2.5s for the integral part to kick in I think it is too slow. You still have to tune more this PID.

avrcandies wrote:
I assume you are trying to control the position of the motor arm, not the rotational speed (hence you ultimately want zero rpm)-correct?

Yes correct. I'm doing something like this one: https://www.youtube.com/watch?v=...

avrcandies wrote:
How often does the ISR run?

I started with every 10ms (100 times every second, 100Hz), but then someone here told to increase the rate, so I experimented 5ms (200 times per second, 200Hz), 2.5ms (400 times per second, 400Hz) and 1.25ms (800 times per second, 800Hz) and neither of them made a difference. I tried like you said 20 times every second but it seems too slow.

avrcandies wrote:
Why are you using floating point?  There is certainly no need to burden your system so heavily.

I'm using floats to have a bigger precision. The encoder has a resolution of around 0.88 degrees.

avrcandies wrote:
Are the calculations actually producing real results (not just on paper).  For instance, integers must stay within certain ranges. is this actually producing an iterm value in your variable:  i_term + (0.00125*erro)

I don't understand what you mean by "real results". If you mean if it is producing values with decimals numbers the the answer is yes, I've tested outputing every math operation to a terminal window. If you mean if it producing any numbers the answer is also yes.

avrcandies wrote:
Just clip your I_term so it cannot exceed some preset limit  (say I_term_max=3, I_term_min=-3), or whatever limit is usable)

This values are something that I have to come up with just like the controller parameters? or is there a mathematical way to find them?

In the previous post I said that the oscillations that sometimes happens (in the end of the second image) was due to the integral term but I manage to zoom in other test I did and proved that it isn't true:

This is without the if(angulo == 0) showed in the last comment

Last Edited: Wed. Aug 9, 2017 - 10:11 PM

angelu wrote:
How you determine that the motor has reached the correct position so the motor does gets off power ? Reading the encoder ?

angelu wrote:
In any case, you need to have few encoder counts plus and few encoder counts minus where you are comfortable as a destination position.

Can you explain it better I don't understand what you mean.

angelu wrote:
The fact that it takes 2.5s for the integral part to kick in I think it is too slow. You still have to tune more this PID.

The problem is that to make the integral part act faster I have to increase the integral gain (ki) but doing so makes the system oscillate and never reaches the setpoint.

Someone suggested me that the problem could be friction or backlash in the motor and they suggested me this article: http://www.wescottdesign.com/art...

I removed the gearbox of my motor and behavior is the same, so I assume that backlash is not the problem. In that article section 2.4 shows something that looks like my problem.

Last Edited: Wed. Aug 9, 2017 - 10:34 PM

I started with every 10ms (100 times every second, 100Hz), but then someone here told to increase the rate, so I experimented 5ms (200 times per second, 200Hz), 2.5ms (400 times per second, 400Hz) and 1.25ms (800 times per second, 800Hz) and neither of them made a difference. I tried like you said 20 times every second but it seems too slow.

20 to 100 speed tweaks a sec should likely be plenty, the motor/mech can only react so fast anyhow.   If you were building a high precision super-fast disk drive, then it might not be enough!

I'm using floats to have a bigger precision. The encoder has a resolution of around 0.88 degrees.

A 16 bit integer has 65500+  choices...way more than your encoder...you only have a limited number of PWM choices as well.

I don't understand what you mean by "real results".

Some people don't pay attention to variables & wonder why they always get zero when they calculate my_cat= 0.01234*my_dog....even if my_dog is "700"

This is without the if(angulo == 0) showed in the last comment

This whole block seems to be a problem  you want to use erro (why not spell it error???), NOT angulo in these conditionals...if the error is positive, go one way, If error is negative, go the other

if the ERROR is zero, set the pwm to zero, NOT if the angle is zero set the pwm to zero.   Since you apparently are aiming for zero angle, the result will be about the same, but you might want a different angle.

The servo's purpose in life is to reduce the error to zero & keep it there.   You want to clip the integral term to keep it from getting too large, regardless of the PWM value.   Too much integral & you'll skid off the road.   Instead your code is trying to limit the PWM value (of course you must always do that too, since only certain timer values, 0 to ....,  are allowed).

even better, recommend if the error is less than some +/-deadband, set the pwm to zero..it is very hard to have an exact match, always allow +/- count at least.

When in the dark remember-the future looks brighter than ever.

Last Edited: Thu. Aug 10, 2017 - 01:01 AM

M_Luis wrote:

angelu wrote:

In any case, you need to have few encoder counts plus and few encoder counts minus where you are comfortable as a destination position.

Can you explain it better I don't understand what you mean.

same as

even better, recommend if the error is less than some +/-deadband, set the pwm to zero..it is very hard to have an exact match, always allow +/- count at least.

Cheers