br3ttb / Arduino-PID-Library

1.93k stars 1.11k forks source link

PID compute() doesn't take into account the elapsed millis() #74

Closed TLS1000 closed 6 years ago

TLS1000 commented 6 years ago

I'm using the PID library for the first time, and my code only computes the PID output every second or so.

When I have a look at the code, the computing doesn't take into account how much time has elapsed since last compute(), it only checks if there were 100ms since last call. So if you compute every 100ms or every two seconds the output of the controller won't take this into account for integration or differentiation.

is this for stability reasons?

TLS1000 commented 6 years ago

ah ok, I see that for the elapsed time, the sample time is taken into account in the 'PID::SetTunings' function. ki and kd are scaled as function of sampletime. that's an indirect way for taking into account the time between compute calls. So for theoretical correct operation, the sample time needs to be set close to actual time between compute calls.

but still, wouldn't it be better to use the real elapsed time between compute calls for scaling ki and kd?

terryjmyers commented 6 years ago

Yes it would be better to use the actual elapsed, however, rerunning SetTunings each Compute would be professor intensive due to the float divide. The timing is implemented such that the average time between calls to Compute will be the required timing. For example if compute is called at some absolte t=90ms, the next call will be at absolute t=110. While the math may not be perfect it's good enough in order to keep the library fast and light for small micro controllers. If you have a fast micro(like an esp32) you could modify the library to take into account the actual time between compute calls. But I wouldn't, as you don't gain anything meaningful. Tldr: not taking into account the actual time between computes is an exercise in compromise

TLS1000 commented 6 years ago

I see, main issue here is that the sample time has to be enlarged if the compute isn't called every 100ms. Otherwise the behavior of the PID controller vs Ki and Kd settings is erratic. As controllers get ever more powerfull, maybe someone with the right skillset could make the real time calculation between computes an option in the construct of the PID controller?

Makes it also future-proof I think? And yes, I'm running it onESP32

br3ttb commented 6 years ago

there are certainly libraries that already do this. for more information on why I decided on things, take a look at my blog series http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/ where I explain my design choices.

the main reason I'm replying though is to ask what you could be doing that would make your loop take 1000ms. usually this will only happen if you're using delay() calls. if that's the case, please take a look at the blink without delay example that ships with the arduino ide.

On Mon, Apr 16, 2018 at 1:48 PM TLS1000 notifications@github.com wrote:

I see, main issue here is that the sample time has to be enlarged if the compute isn't called every 100ms. Otherwise the behavior of the PID controller vs Ki and Kd settings is erratic. As controllers get ever more powerfull, maybe someone with the right skillset could make the real time calculation between computes an option in the construct of the PID controller?

Makes it also future-proof I think?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/74#issuecomment-381690860, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWL8vag8at1Kg7BYhgWHXtfDNMGEr4nks5tpNlxgaJpZM4TVfYB .

terryjmyers commented 6 years ago

@TLS1000 if you're using the esp32, you could create a task which processes compute at a regular interval. The entire esp32 SDK is already running free rtos. But again, the esp32 is fast enough that a couple milliseconds here or there shouldn't really matter using this Library.

TLS1000 commented 6 years ago

Hi, there are a few delays() here and there in my program, main cause for loop time is response times from external communications like modbus@19200kbs, response times from http servers, and SPI communications. In near future I'll also need a fast PID for controlling the RPM of a generator via a servo. I haven't experimented with interrupt based function calls, I guess I might start looking into that direction :-)

I've seen this 'blink' function here and there, but haven't gone to work with it yet.

br3ttb commented 6 years ago

Yeah, those delays can be tough to remove. If they're non-negotiable, maybe another pid library would work.

I can't endorse it as I haven't used it, but the author of the fastPid library posted here a few days ago, and I believe that his library does account for elapsed time. (Sorry no links, on my phone)

On Tue, Apr 17, 2018, 1:59 AM TLS1000 notifications@github.com wrote:

Hi, there are a few delays() here and there in my program, main cause for loop time is response times from external communications like modbus@19200kbs, response times from http servers, and SPI communications. In near future I'll also need a fast PID for controlling the RPM of a generator via a servo. I haven't experimented with interrupt based function calls, I guess I might start looking into that direction :-)

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/74#issuecomment-381855260, or mute the thread https://github.com/notifications/unsubscribe-auth/AAWL8rOX0ZdR_QUa-9HAq_UlPKIi0hqRks5tpYTUgaJpZM4TVfYB .

binduni commented 6 years ago

How can I unsubscribe from this thread? The notifications setting is off " You’re not receiving notifications from this thread. " and yet I clearly am.

On Mon, Apr 16, 2018 at 10:59 PM, TLS1000 notifications@github.com wrote:

Hi, there are a few delays() here and there in my program, main cause for loop time is response times from external communications like modbus@19200kbs, response times from http servers, and SPI communications. In near future I'll also need a fast PID for controlling the RPM of a generator via a servo. I haven't experimented with interrupt based function calls, I guess I might start looking into that direction :-)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/br3ttb/Arduino-PID-Library/issues/74#issuecomment-381855260, or mute the thread https://github.com/notifications/unsubscribe-auth/ALfqGLxhYP2g51GDVJJqTUx6-i3oZ746ks5tpYTYgaJpZM4TVfYB .