#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 300
#End Region
'Ctrl+Click to open the C code folder: ide://run?File=%WINDIR%\System32\explorer.exe&Args=%PROJECT%\Objects\Src
Sub Process_Globals
Public Serial1 As Serial
Dim t As Timer
Dim kp, ki, kd As Double 'Used to set the kp, ki, kd parameters in the inline C code
Dim integral As Double
Dim cont As CONTROLLINO
Dim setpotpin, feedbackpin, outputpin, additionaloutputpin As Pin
Dim A As Long = 1000 'Resistance in darkness in KΩ
Dim B As Int = 15 'Light resistance (10 Lux) in KΩ
Dim Rc As Int = 10 'Calibration resistance in KΩ
Dim input, setpoint, output As Double
Dim feedbackval As Float
Dim outputMin, outputMax As Double
Dim threshold As Double = 3 'threshold between Setpoint and Feedback to stop doing PID corrections
Dim atSetpoint, isStopped As Boolean 'true when Setpoint and Feedback is within +- the threshold range
End Sub
Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")
integral = 0
outputMin = 0
outputMax = 255
setpotpin.Initialize(cont.CONTROLLINO_A1, setpotpin.MODE_INPUT) 'pin 55
feedbackpin.Initialize(cont.CONTROLLINO_A0, feedbackpin.MODE_INPUT) 'pin 54
outputpin.Initialize(cont.CONTROLLINO_D0, outputpin.MODE_OUTPUT) 'pin 2
additionaloutputpin.Initialize(cont.CONTROLLINO_D1, additionaloutputpin.MODE_OUTPUT) 'pin 3
t.Initialize("t_tick", 20)
kp = 0.4 'the kp constant of the PID controller
ki = 6.0 'the ki constant of the PID controller
kd = 0.0001 'the kd constant of the PID controller
RunNative("setup", Null)
RunNative("setOutputRange", Null)
RunNative("setGains", Array(kp, ki, kd))
t.Enabled = True
End Sub
Sub t_tick
setpoint = setpotpin.AnalogRead/4
feedbackval = readFeedback
RunNative("loop", Null)
RunNative("getIntegral", Null) 'get the sum of the integral
If integral > 60 Then 'limit the winding up of the integral
RunNative("setIntegral", 60) 'set the integral wind up to max 60
else if integral < 0 Then
RunNative("setIntegral", 0) 'set the integral wind down to min 0
End If
Log("Setpoint = ", setpoint)
Log("Feedback = ", feedbackval)
Log("Output = ", output)
Log("integral = ", integral)
RunNative("atSetPoint", threshold)
Log("atSetPoint = ", atSetpoint)
RunNative("isStopped", Null)
Log("isStopped = ", isStopped)
Log(" ")
outputpin.AnalogWrite(output)
additionaloutputpin.AnalogWrite(output)
End Sub
Sub readFeedback As Float 'specific to the LDR I am using as feedback from the "plant"
Dim mean As Float = 0
Dim V As Float
For i = 0 To 99
V = feedbackpin.AnalogRead
mean = mean + (V * A * 10) / (B * Rc * (1024 - V))
Next
mean = (mean / 100)
Return mean
End Sub
#If C
#include <AutoPID.h>
#define FEEDBACK_READ_DELAY 10 //
//pid settings and gains
#define OUTPUT_MIN 0
#define OUTPUT_MAX 0
#define KP 0.0
#define KI 0.0
#define KD 0.0
double feedback, setPoint, outputVal;
//input/output variables passed by reference, so they are updated automatically
AutoPID myPID(&feedback, &setPoint, &outputVal, OUTPUT_MIN, OUTPUT_MAX, KP, KI, KD);
unsigned long lastFeedbackUpdate; //tracks clock time of last feedback update
bool updateFeedback() {
if ((millis() - lastFeedbackUpdate) > FEEDBACK_READ_DELAY) {
feedback = b4r_main::_feedbackval; //get feedback reading
lastFeedbackUpdate = millis();
feedback = b4r_main::_feedbackval; //get feedback reading //request reading for next time
return true;
}
return false;
}
void loop(B4R::Object* o) {
updateFeedback();
setPoint = b4r_main::_setpoint;
myPID.run(); //call every loop, updates automatically at certain time interval
b4r_main::_output = outputVal;
}
void setup(B4R::Object* o) {
myPID.setTimeStep(50); //updates automatically at certain time interval
}
void setGains(B4R::Object* o) {
myPID.setGains(b4r_main::_kp, b4r_main::_ki, b4r_main::_kd);
}
void getIntegral(B4R::Object* o) {
b4r_main::_integral = myPID.getIntegral();
}
void setIntegral(B4R::Object* o) {
myPID.setIntegral(o->toDouble());
}
void setOutputRange(B4R::Object* o) {
myPID.setOutputRange(b4r_main::_outputmin, b4r_main::_outputmax);
}
void atSetPoint(B4R::Object* o) {
boolean asp = myPID.atSetPoint(o->toDouble());
b4r_main::_atsetpoint = asp;
}
void stop(B4R::Object* o) {
myPID.stop();
}
void reset(B4R::Object* o) {
myPID.reset();
}
void isStopped(B4R::Object* o) {
boolean isStopped = myPID.isStopped();
b4r_main::_isstopped = isStopped;
}
#End If