PID Library for Teensy 4.1

adi1893

Member
Hi,

I am working on a project that requires two high speed PID loops for generating PWM waveforms that control current and voltage of downstream equipment. The PWM waveforms are generated via IntervalTimer interrupts and there is no issue there. The duty cycle of the PWM requires a finer control compared to 0-255 default and that is why I am using intervalTimer interrupts

However I am unable to properly use any of the PID libraries I could find online. I was able to get the PID_v2 working as a simple PID controller but am unable to find proper documentation for how to define the output limits and also how to change the gains during normal running of the code as the operator may need to make changes to the gains

The PID_V2 reference page takes me to the github page where there isnt much info on the functions: https://github.com/imax9000/Arduino-PID-Library
There is a link to the old PID function list but if I try using any of the functions they show the following error during compiling eg:

error: 'SetOutputLimits' was not declared in this scope
SetOutputLimits(0, 1000)
^
'SetOutputLimits' was not declared in this scope

If I try using the function as below, nothing happens and the output limit is still the default 0-255
bool SetOutputLimits(0, 1000);

Link to original PID reference page: https://playground.arduino.cc/Code/PIDLibrary/

Please guide me on how to use the PID Library or if there is another library that you use for Teensy with clear documentation it would be a huge help. I have been going crazy searching online and coming up with nothing useful.

Would really appreciate direct references to any code or websites/libraries with working code instead of just someone telling me to google something

The code I was using is just a modified version of the Simple PID example to take a potentiometer input and change the brightness of the onboard LED and basically see the output changing as the pot values are changed manually. This isnt the proper implementation of a PID but its just to simply check that the output limits change with code (does not max out at 255 and maxes out at the value I require, also that gains change with commands from the code and dont stay at what they were initialized at). Again this is not my final code but just a test code to see if the PID library generates any output and if that output can be configured to the limits and changing gains required in my final code.

Test program code:

Code:
#include <PID_v2.h>
double Kp = 2.1, Ki = 20.5, Kd = 0;
PID_v2 myPID(Kp, Ki, Kd, PID::Direct);
int potPin = 0; //A0
int potValue = 0;
int ledPin = 13;

void setup() {
  myPID.Start(analogRead(potPin),  // input
              0,                      // current output
              100);                   // setpoint     
  Serial.begin(9600);
}

void loop() {
  const double input = analogRead(potPin);
  const double op = myPID.Run(input);
  analogWrite(ledPin, op);
  Serial.println(op);
}
 
Worked like a charm! Thank you for the help :)

You're welcome. Glad I could help.

Good luck & have fun !! Feel free to ask any other questions that may come up. There are lots of members on here that would be glad to help.

Mark J Culross
KD5RXT
 
I would like to use you Lib to implement a PID. I have a 500W Single Can Thermal Electric Soda Cooler. I have a PWM on the Teency 4.1 and I read the temperature of the water.

the red is the temperature of the diver, black is the temperature of the soda (purple is the PWM value) input is between -15c to +25c and output is PWM x 10. to begin I would like to set the PWM to set the temperature of the Driver
1761683164722.png
 
Its oscillating, so the I term is likely too large, and possibly the gain term too (P). Are you using the D term?
 
Its oscillating, so the I term is likely too large, and possibly the gain term too (P). Are you using the D term?
yes I had an integrator only, so I am now putting this code in. your timing is perfect.

before setup:
#include <PID_v2.h>//https://forum.pjrc.com/index.php?threads/pid-library-for-teensy-4-1.71153/
double Kp = 2.1, Ki = 20.5, Kd = 0; // not set yet
PID_v2 myPID(Kp, Ki, Kd, PID::Direct);
//int potPin = 0; //A0
//int potValue = 0;
//int ledPin = 13;

void setup(){
// input output setpoint
myPID.Start(PIDTmp, PIDPWMVal, 10); //PIDTmp temperature of the aluminum driver, PIDPWMVal (10% to 95%x10, setpoint =+10c





case 2:{
DispMode=2;



const double input =PIDTmp; // current temperature of system
const double output = myPID.Run(input);

PWMVal=output;
SCTESC.jpg
 
yes I had an integrator only, so I am now putting this code in. your timing is perfect.
Well that's an oscillator by definition, the system integrates the control input, which is the integral of the error (if only an I term), so 180 phase shift added to the negative feedback turning it to positive feedback...

P term does the bulk of the work, I term exists only to drive the error to zero over time, and the D term allows faster response (but too much amplifies sensor noise). Since the I term will eventually force instability its wise to optimize P (and maybe D) first.
 
Well that's an oscillator by definition, the system integrates the control input, which is the integral of the error (if only an I term), so 180 phase shift added to the negative feedback turning it to positive feedback...

P term does the bulk of the work, I term exists only to drive the error to zero over time, and the D term allows faster response (but too much amplifies sensor noise). Since the I term will eventually force instability its wise to optimize P (and maybe D) first.
I have an error in my code, so i will make a standalone with a pot input with the temperature range and output to the Monitor of the PWM driver, I need to have it initialize to the PWM output of 45.5% with the temperature pot set to +5.
 
I have an error in my code, so i will make a standalone with a pot input with the temperature range and output to the Monitor of the PWM driver, I need to have it initialize to the PWM output of 45.5% with the temperature pot set to +5.
i know the LED is ok and A9 is OK. what should I expect with the output?

#include <PID_v2.h>
int led = 13;
#define PIN_INPUT A9
#define PIN_OUTPUT 0

// Specify the links and initial tuning parameters
double Kp = 0, Ki = 0, Kd = 0;
PID_v2 myPID(Kp, Ki, Kd, PID::Direct);

void setup() {
myPID.Start(analogRead(PIN_INPUT), // input
0, // current output
100); // setpoint
pinMode(led, OUTPUT);
}

void loop() {
const double input = analogRead(PIN_INPUT);
const double output = myPID.Run(input);
analogWrite(PIN_OUTPUT, output);
int rr;
rr=analogRead(A9)/10;
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(rr); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(rr);
}
 
Back
Top