m-lundberg / simple-pid

A simple and easy to use PID controller in Python
MIT License
801 stars 217 forks source link

ZeroDivisionError: float division by zero #5

Closed groverdivas closed 5 years ago

groverdivas commented 5 years ago

I am trying to use this on a list here is my code:

pr = ['list of some values'] pid = PID(1, 0.5, 0, setpoint=1, output_limits=(0, 1), sample_time=None) pid.set_auto_mode(True, last_output=0.5) vfdp = [] for i in pr: print(i) vfdp.append(pid(i))

and it gives me zero division error as follows:

self._derivative = -self.Kd * d_input / dt

ZeroDivisionError: float division by zero

m-lundberg commented 5 years ago

This is interesting. I tried to reproduce it in Linux but couldn't. I then tried to reproduce it in Windows and there I could get the error to appear pretty easily. So it seems like time.time() has much smaller precision on Windows, which also seems to be confirmed by some googling. This causes the time difference from two calls to be so small that dt is zero, giving the ZeroDivisionError.

I'm not entirely sure what the best way is to fix it. There seem to be other functions for getting time in python which are more accurate in Windows but none of them feel like a good choice for this purpose. I also don't see anything in the documentation about them being monotonic and I don't want to bring back #1 by using a non-monotonic time function. So for now I solved the problem by setting dt to some small value (1e-16, chosen kind of arbitrarily) if it was zero. The fix is implemented in the latest release (0.2.1).

By the way, I recommend you to set sample_time to something else than None since that should give more stable results, especially with this fix in place.