PID controlled motor controller (based on measured RPM instead of PWM)

Hello,

I have bought the following motor driver: 4A Dual Bi-Directional Motor Driver (L298 H-Bridge).

Using two motors and two hall sensors (Hamlin - Hall-sensor 55100-3H-02-A, http://www.hamlin.com/specsheets/55100%20IssueAG.pdf) and a few magnets, Ive build a small test setup that is capable of measuring the RPM and current of each motor.

At the moment I control the motors using PWM and read the RPM but I want to give a desired RPM so a PID algorithm calculates the optimal PWM value based on the current RPM and current (mA).

When the motors are running freely the current usage and RPM are really stable (as expected). When force is applied to the motor(s), the RPM value decreases and the mA value increases.

I think that a PID algorithm might be enough to calculate a new PWM value but for a more accurate value I think it might putting the used current into the equation migth be a good idea. But how......?

Is there anyone with some experience or good ideas before I reinvent the wheel?

I will post the code of the library I am making later :slight_smile:

Cheers.

I've finished the library. I'll hope to be able to test it tomorrow and post a draft version of the library.

BTW it is a continuation of this library:

Cheers.

Are you trying to control RPM or torque?

you got me thinking :wink: I think I need RPM but I don't know If I even need the mA value for that?

So my first awnser is RPM (but it might change based on member input).

Cheers.

What is the expected range of the RPM?

Some Characteristics:

  • PWM input: -255 to +255 (where the negative range is reverse and the positive range if forward).
  • RPM range: 0 - 3000 (the encoder are mounted directly on the motors but a reduction will take place afterwards (using a timer belt) 3:1 to increase torque). After the gear ratio, the effective RPM will become 1 - 1000. But all calculations are done based on 0 - 3000!
  • Current sensing is done from 0 to 2000 mA (probably not necessary but worth to mention :slight_smile:

I know I can use PID with current RPM and desired RPM as input and simply map this to a PWM value. This is no problem if the load on the motors is constant (I am building an UGV so terrain properties change over time).

But when the resistance on the tracks increase more PWM needs to be delivered to reach the desired RPM. I know that taking the old PWM value and adding the PID part to it will work but I don't know if that is the best way to go?

So I thought that I might can use the current draw bu the motors.

Example:

  • The motors both rotate at 1000 rpm with no load going (mA value 200 mA) from 1000 to 2000 rpm takes relatively not that much extra PWM.
  • But what if both rotate at 1000 rpm with a load going (mA value 1000 mA) from 1000 to 2000 rpm takes more PWM (If the max RPM can actually be reached!).

So I thougt: what if I know the actual RPM and current value? Maybe I can optimize the PID algorithm with the extra data?

Maybe I first have to do some testing to see what really happens......

Cheers.

and a few magnets

How many per wheel?

Example:

The motors both rotate at 1000 rpm with no load going (mA value 200 mA) from 1000 to 2000 rpm takes relatively not that much extra PWM.
But what if both rotate at 1000 rpm with a load going (mA value 1000 mA) from 1000 to 2000 rpm takes more PWM (If the max RPM can actually be reached!).

So I thougt: what if I know the actual RPM and current value? Maybe I can optimize the PID algorithm with the extra data?

Maybe I first have to do some testing to see what really happens......

Cheers.

With true P&ID its not important that the mapping of the pwm output tracks linearly with the motor range with or without load, as the P&ID just compares the desired rpm (the setpoint) with the actual real time rpm measurement (the process variable) and the output just says 'send more output' or 'send less output' in response to that error until the error is zero where then the output will just remain where it last was until the P&ID once again detects an error. That auto feedback correcting action means the absolute value of the output pwm signal is not important, just that it does cause the motor to speed up or slow down when the P&ID algorithm makes a correction to the output value. One optimizes a P&ID loop by changing the 'constant tuning values' used for the P,I and D terms, not by other external means.

Lefty

@ Codingbadly: i'll start with two magnets for each wheel. This mainly because i don't know if the interrupst can handle that much pulses (6000/min for each motor)?

@ lefty: thanks for you reply. I did some reading yesterday and noticed no extra parameter are use in a real PID algorithm. Your explanation really convinced me :slight_smile:

If the rotation speed changes, either from an output change or from a load change, the change will not be fully measured for 1/2 of a rotation. At high speeds, this dead-time is relatively very small. At low speeds, this dead-time is relatively large. Which means PID parameters that work well at high speeds will not work well (or possibly not at all) at low speeds.

When faced with a similar problem, I used different PID parameters for different setpoint ranges. In my case, I was controlling a wind turbine and the goal was to obtain a very stable flow rate. Because of the system and the goal, changing PID parameters while the system was running did not cause problems. Something similar may work for you. Think of it as "changing gears".

In regards to using the current: the more separated your control strategy is from the thing you are trying to control the more problems you will have. I suspect the current is too far separated from what you are trying to control to add much value.

I vaguely recall that measuring "back EMF" can be used to more directly determine motor speed. That may work to reduce the low speed dead-time. I think this is where I read about it: http://openservo.com/

Thanks for all the replies!!

I think I'll use the current sense function to detect motor stall or motor overload.

At the moment I have two magenets/wheel. I can increase this to four? It will give a more accurate reading at low RPM, but I don't know if the interrupt can handle (12.000 pulses/minute max.)?

PID is starting to make more sense to me :slight_smile: Maybe I'll try to incorporate specific PID settings is certain ranges (like CodingBadly proposed).

EDIT: Maybe I can better use:

http://arduino.cc/playground/Code/PIDLibrary

and

http://arduino.cc/playground/Code/PIDAutotuneLibrary

I am still working on the library... I can post a preview version (not fully tested) if people are intrested?

Cheers.

OpenSource:
At the moment I have two magenets/wheel. I can increase this to four? It will give a more accurate reading at low RPM, but I don't know if the interrupt can handle (12.000 pulses/minute max.)?

12000 / 60 = 200 interrupts per second. Keep the interrupt service routine lean and you will be fine.