{"id":3806,"library":"simple-pid","title":"simple-pid","description":"simple-pid is a Python library that provides a simple and easy-to-use PID controller. It is designed to be robust and operate without external dependencies, making it suitable for various control system applications. The library is actively maintained, with the current version being 2.0.1, and new major versions released approximately every 2-3 years, supplemented by minor and patch releases as needed.","status":"active","version":"2.0.1","language":"en","source_language":"en","source_url":"https://github.com/m-lundberg/simple-pid","tags":["control-system","pid","automation","robotics"],"install":[{"cmd":"pip install simple-pid","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Requires Python 3.6 or higher for compatibility.","package":"python","optional":false}],"imports":[{"symbol":"PID","correct":"from simple_pid import PID"}],"quickstart":{"code":"import time\nfrom simple_pid import PID\n\n# A dummy controlled system for demonstration\nclass ControlledSystem:\n    def __init__(self, initial_value=0.0):\n        self.value = initial_value\n        self.time_step = 0.1\n\n    def update(self, control_input):\n        # Simulate system response, e.g., a simple first-order system\n        self.value += (control_input - self.value) * (self.time_step * 0.5)\n        return self.value\n\n# Initialize PID controller: Kp, Ki, Kd, setpoint\n# Here, a setpoint of 10 is desired.\npid = PID(2.0, 0.5, 0.2, setpoint=10.0)\n\n# Configure PID parameters\npid.sample_time = 0.1  # Update every 0.1 seconds\npid.output_limits = (-10, 10) # Limit output to avoid integral windup\n\n# Initialize the controlled system\nsystem = ControlledSystem(initial_value=0.0)\n\nprint(f\"Initial system value: {system.value:.2f}\")\n\n# Run the control loop for a few iterations\nfor i in range(100):\n    # Compute new output from the PID according to the system's current value\n    control_output = pid(system.value)\n\n    # Feed the PID output to the system and get its current value\n    system_value = system.update(control_output)\n\n    # Optional: Print current state\n    if i % 10 == 0:\n        print(f\"Iteration {i}: Setpoint={pid.setpoint:.2f}, System Value={system_value:.2f}, Control Output={control_output:.2f}\")\n\n    time.sleep(pid.sample_time)\n\nprint(f\"Final system value: {system.value:.2f}\")\n# Expected output will show the system value approaching 10.0","lang":"python","description":"This quickstart demonstrates the basic usage of `simple-pid`. It initializes a `PID` controller with proportional, integral, and derivative gains, and a target setpoint. The controller is then used within a loop to regulate a simulated system, updating its control output periodically based on the system's current value. Key parameters like `sample_time` and `output_limits` are configured for robust operation."},"warnings":[{"fix":"Upgrade to Python 3.6 or newer to ensure full compatibility and support.","message":"Official support for Python 2 was dropped in version 2.0.0. While the code might still function, it is no longer tested against Python 2 environments, and no guarantees are provided for its compatibility or future functionality.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Always set meaningful `pid.output_limits = (lower, upper)` to prevent integral windup. The library uses these limits to constrain both the output and the integral term.","message":"Integral windup is a common issue in PID controllers where the integral term accumulates error even when the controller output is saturated. simple-pid mitigates this by automatically clamping the integral term when `output_limits` are set. Failing to set appropriate `output_limits` can lead to this problem and unstable control.","severity":"gotcha","affected_versions":"<2.0.1"},{"fix":"Understand the `differential_on_measurement` parameter (defaulting to `True` since v2.0.0) and adjust it based on your system's requirements to prevent derivative kick.","message":"The derivative term can cause a 'derivative kick' (a sharp output spike) on sudden setpoint changes if calculated on the error. By default, `simple-pid` calculates the derivative on the measurement (`differential_on_measurement=True`) to avoid this. If classic derivative-on-error behavior is desired, explicitly set `differential_on_measurement=False` during initialization.","severity":"gotcha","affected_versions":"All"},{"fix":"If providing a custom `time_fn`, ensure it is monotonic. If `sample_time` is `None` and you're manually managing `dt`, ensure `dt` reflects the actual time elapsed between calls.","message":"The accuracy of time-based calculations (integral and derivative terms) depends on reliable time measurements. `simple-pid` defaults to `time.monotonic()`, but if you override `PID.time_fn` or manually set `dt` (especially if `sample_time` is `None`), ensure your custom time source provides consistent and monotonic time to avoid calculation errors.","severity":"gotcha","affected_versions":"All"},{"fix":"For new PID instances or when enabling auto mode, provide a `starting_output` value to the constructor (v2.0.0+) or pass the system's `last_output` value when calling `pid.auto_mode = True` to provide a 'bumpless' transfer.","message":"When switching a system from manual control to PID auto mode, or starting PID on a system already at its setpoint, the PID might initially output zero (causing a 'bump') as its internal state is zero. Version 2.0.0 introduced `starting_output` for a smoother transition, and `auto_mode=True` can take a `last_output` value.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}