/ArduPID

PID library for Arduinos with greater accuracy than the legacy Arduino PID library

Primary LanguageC++MIT LicenseMIT

ArduPID

GitHub version arduino-library-badge

PID library for Arduinos with greater accuracy than the legacy Arduino PID library.

Why Use PID?

PID stands for Proportional, Integral, and Derivative and is a simple type of controller. PID controllers can provide stable control of nearly any system such as the speed of a motor, position of a servo, speed of a car (cruise control), and much more.

How Does it Work?

See the explanation video here

How to Tune a PID:

See here

How to Use the Library:

First import the library, instantiate an ArduPID class, and create 6 doubles:

  • Setpoint
  • Input
  • Output
  • P Gain
  • I Gain
  • D Gain
#include "ArduPID.h"

ArduPID myController;

double setpoint = 512;
double input;
double output;
double p = 1;
double i = 0;
double d = 0;

Next, within the setup() function, initialize the controller with the references to the input, output, and setpoint variables. Also pass the values of the PID gains. After initializing the controller within setup(), you can change the settings/configuration of the controller.

void setup()
{
  Serial.begin(115200);
  myController.begin(&input, &output, &setpoint, p, i, d);
  
  // ADD MORE CONFIGURATION COMMANDS HERE <--------------------
}

Here are the different examples of configuration commands available via the library:

  • reverse()
    • Reverse direction of output
  • setSampleTime(const unsigned int& _minSamplePeriodMs)
    • Will ensure at least _minSamplePeriodMs have past between successful compute() calls - this function is not necessary, but is included for convenience
  • setOutputLimits(const double& min, const double& max)
    • Clip output to values to min and max
  • setBias(const double& _bias)
    • Output will have a constant offset of _bias, usually used in conjunction with setOutputLimits()
  • setWindUpLimits(const double& min, const double& max)
  • start()
    • Enable/turns on the controller
  • reset()
    • Used for resetting the I and D terms - only use this if you know what you're doing
  • stop()
    • Disable/turn off the PID controller (compute() will not do anything until start() is called)

Within the loop(), update the input variable via your sensor and then call compute(). The output variable will then be automatically updated and you can use that updated value to send an updated command to your actuator. You can also use the debug() command to print various status information about your controller to the serial plottor/monitor:

void loop()
{
  input = analogRead(A0); // Replace with sensor feedback

  myController.compute();
  myController.debug(&Serial, "myController", PRINT_INPUT    | // Can include or comment out any of these terms to print
                                              PRINT_OUTPUT   | // in the Serial plotter
                                              PRINT_SETPOINT |
                                              PRINT_BIAS     |
                                              PRINT_P        |
                                              PRINT_I        |
                                              PRINT_D);
  
  analogWrite(3, output); // Replace with plant control signal
}