Hi,
I have used OpenHAB for a while for simpler tasks. I would now like to implement a PID regulator as a rule. I have used the ivPID (https://github.com/ivmech/ivPID) as a starting point.
The problem is that I cannot get “global” variables to work. I understood from the documentation and from other forum posts that variables can be defined as global (where the global scope is the rule file) if they are declared outside of the rules. Some variables work from some rules, but not from all and I do not understand why. I know I could use items to store the calculations, but as I do not (at this point) intend to use them for anything I prefer to keep them hidden from event logs etc. by defining them as variables.
Please note the code is not complete, I have only added few functions to start off at some point.
Rule file:
import javax.measure.quantity
// PID regulator
// MF2020 - Based on ivPID Python code
val Kp = 0.07 as Number
val Ki = 0.0007 as Number
val Kd = 0 as Number
var sample_time = 0.0 as Number
var current_time = (now.getMillis() as Number)
var last_time = (now.getMillis() as Number)
var PTerm = (0.0 as Number).doubleValue
var ITerm = (0.0 as Number).doubleValue
var DTerm = (0.0 as Number).doubleValue
var last_error = 0.0 as Number
var error = 0.0 as Number
var windup_guard = 0.0 as Number
var output = (0.0 as Number).doubleValue
var max_output = 20 as Number
var min_output = 0 as Number
// Trigger updates
rule "shuntti_pid_update_trig" when Item pannu_paluuvesi received update then
if (shuntti_pid_active.state == ON) {
shuntti_pid_update.sendCommand((pannu_paluuvesi.state as QuantityType<Number>).doubleValue)
}
end
// Clear PID calculations
rule "shuntti_pid_clear_f" when Item shuntti_pid_active changed then
logInfo("Shuntti_PID", "Cleared calculations")
PTerm = (0.0 as Number).doubleValue
ITerm = (0.0 as Number).doubleValue
DTerm = (0.0 as Number).doubleValue
last_error = 0.0 as Number
error = 0.0 as Number
windup_guard = 0.0 as Number
output = 0.0 as Number
end
// Update PID calculation
rule “shuntti_pid_update_f” when Item shuntti_pid_update received command then
logInfo(“Shuntti_PID”, “Starting”)
error = ((shuntti_pid_setpoint.state as Number) - (shuntti_pid_update.state as Number))
current_time = now().getMillis() as Number
var delta_time = (current_time-last_time) as Number
var delta_error = (error - last_error) as Number
if (delta_time >= sample_time){
PTerm = Kp * error
ITerm = ITerm + (error * delta_time)
if (ITerm < -windup_guard) {
ITerm = -windup_guard
}
else if (ITerm > windup_guard) {
ITerm = windup_guard
}
if (delta_time > 0) {
logInfo("Shuntti_PID", "C1")
var Dtermc = delta_error / delta_time
logInfo("Shuntti_PID", Dtermc.toString())
Dterm = Dtermc
}
last_time = current_time
last_error = error
logInfo("Shuntti_PID", "A")
output = PTerm + (Ki * ITerm) + (Kd * Dterm)
// var x_output = Pterm
logInfo("Shuntti_PID", Pterm.toString())
logInfo("Shuntti_PID", Ki.toString())
logInfo("Shuntti_PID", ITerm.toString())
output = PTerm + (Ki * ITerm)
logInfo("Shuntti_PID", "G")
if (output < min_output) {
output = min_output
logInfo("Shuntti_PID", "H")
} else if (output > max_output) {
output = max_output
logInfo("Shuntti_PID", "I")
}
shuntti_pid_output.sendCommand(output)
logInfo("Shuntti_PID", "D")
}
end
To test the rule, I have activated (sent cmd ON) to shuntti_pid_activate (to run shuntti_pid_clear_f) and waited for the temperature pannu_panuuvesi to update.
Log:
2020-05-05 14:56:47.348 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model ‘shuntti_pid.rules’
2020-05-05 14:56:53.626 [INFO ] [e.smarthome.model.script.Shuntti_PID] - Cleared calculations
2020-05-05 14:57:58.789 [INFO ] [e.smarthome.model.script.Shuntti_PID] - Starting
2020-05-05 14:57:58.817 [INFO ] [e.smarthome.model.script.Shuntti_PID] - C1
2020-05-05 14:57:58.823 [INFO ] [e.smarthome.model.script.Shuntti_PID] - 0.00010255
2020-05-05 14:57:58.825 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘shuntti_pid_update_f’: An error occurred during the script execution: Couldn’t invoke ‘assignValueTo’ for feature JvmVoid: (eProxyURI: shuntti_pid.rules#|::0.2.2.2.0.5.1.0.3.1.0.3::0::/1)
What confuses me is that writing to some of the variables seem to work, but not to all. I have added some logInfo lines to show more clearly where the rule aborts (when setting Dterm = dTermc).
I think my variable declarations are overkill, but I tried to make them more specific to fix it, however without success. If I understand it correctly, based on missing errors, the shuntti_pid_clear_f can write to Dterm, but not shuntti_pid_update_f.
Thankful for any advice!
Items defined as follows, however I don’t know if relevant:
Number shuntti_pid_setpoint
Switch shuntti_pid_active
Number shuntti_pid_output
Number shuntti_pid_update
Switch shuntti_pid_clear
When starting, shuntti_pid_active is OFF, but changed to ON. shuntti_pid_setpoint is set to a numeric value (25).
- Platform information:
- Hardware: Raspberry Pi 3B+
- OS: Raspbian + OpenHAB docker image
- Java Runtime Environment: Standard from OpenHAB Docker image
- openHAB version: 2.5