Tratando de crear un controlador PID para el control de la temperatura usando un elemento Peltier, decidí ir paso a paso y crear primero los algoritmos Proporcional y luego el Integral y el Derivativo.
Todo el sistema se basa en un raspberry-pi zero que se controla con la ayuda de un Controlador Syren 10A un elemento Peltier.
Como ha comprendido (ya que he hablado de PID) quiero establecer una temperatura objetivo y alcanzarlo lo más cerca posible.
Inicialmente, probé un método bang-bang para hacer eso, pero los resultados no fueron tan esperanzadores. Tuve un error constante alrededor de +/- 5 grados. El código que utilicé era bastante simple y sigue:
import pigpio
import time
import os
from w1thermsensor import W1ThermSensor
pi = pigpio.pi()
FAN_PIN = 5
PLTR_PIN = 18
def FAN_ON( fanPIN ):
print("[on] FAN")
pi.write( fanPIN, 1 )
def FAN_OFF( fanPIN ):
print("[off] FAN")
pi.write( fanPIN, 0 )
def PLTR_OFF( pltrPIN ):
print("[off] PELTIER")
pi.set_servo_pulsewidth( pltrPIN, 1500 )
def PLTR_ON( pltrPIN ):
print("[on] PELTIER")
pi.set_servo_pulsewidth( pltrPIN, 2000 )
#pi.set_servo_pulsewidth( pltrPIN, 1600 )
def PLTR_REV( pltrPIN ):
print("[reverse] PELTIER")
pi.set_servo_pulsewidth( pltrPIN, 1000 )
def GET_TEMP():
sensor = W1ThermSensor()
temp = sensor.get_temperature()
return temp
try:
print("System is starting...")
FAN_ON( FAN_PIN )
PLTR_OFF( PLTR_PIN )
target_temp = 55
PLTR_ON( PLTR_PIN )
time.sleep(3)
PLTR_OFF( PLTR_PIN )
time.sleep(4)
while True:
error = GET_TEMP() - target_temp
print( "Error: ", error, "Temp: ", GET_TEMP() )
if (error > 10):
PLTR_OFF( PLTR_PIN )
time.sleep(15)
elif (error <= 10 and error >= 0):
PLTR_OFF( PLTR_PIN )
time.sleep(7)
PLTR_ON( PLTR_PIN )
time.sleep(1)
elif (error < -10):
PLTR_OFF( PLTR_PIN )
time.sleep(2)
PLTR_ON( PLTR_PIN )
time.sleep(3)
elif (error >= -10 and error <= 0):
PLTR_OFF( PLTR_PIN )
time.sleep(0)
PLTR_ON( PLTR_PIN )
time.sleep(0)
except KeyboardInterrupt:
FAN_OFF( FAN_PIN )
PLTR_OFF( PLTR_PIN )
pi.stop()
Entonces pensé en probar los PID. Así que empiezo a codificar la primera parte. El proporcional y aquí está el código:
from time import sleep
from w1thermsensor import W1ThermSensor
import pigpio
pi = pigpio.pi()
def GET_TEMP():
sensor = W1ThermSensor()
temp = sensor.get_temperature()
return temp
def PLTR_CTRL( PWM_VALUE ):
pi.set_servo_pulsewidth( PLTR_PIN, PWM_VALUE )
def FAN_CTRL( FAN_VALUE ):
pi.write( FAN_PIN, FAN_VALUE )
# PIN CONFIGURATION
PLTR_PIN = 18
FAN_PIN = 5
# PARAMETERS CONFIGURATION
SAMPLE_TIME = 1
PWM_ON = 2000
PWM_OFF = 1500
PWM_REVERSE = 1000
TARGET_TEMP = 40
KP = 0.02
output = 1
# MAIN PROGRAM STARTS HERE
# INITIALLY OPEN THE FAN
FAN_CTRL(1)
# AND THE PELTIER
PLTR_CTRL( PWM_ON )
try:
while True:
error = TARGET_TEMP - GET_TEMP()
output += error * KP
# Turn it in a value between 0 an 1
output = max(min(1, output),0)
if ( output >= 0.5 ):
PLTR_CTRL( PWM_ON )
else:
PLTR_CTRL( PWM_OFF )
print("Temperature: ", GET_TEMP(), "\tError: ", error, "\t\t\tOutput: ", output)
sleep(SAMPLE_TIME)
except KeyboardInterrupt:
PLTR_CTRL( PWM_OFF )
FAN_CTRL(0)
pi.stop()
El problema aquí es que no puedo convertir la variable de salida en un valor significativo para el control de Peltier. Quiero decir, traté de dividir los valores de la salida en la mitad y abrir el Peltier para > 0.5
y cerrarlo de lo contrario. Pero esa idea realmente no funcionó porque los valores de 0.5 output
realmente pueden ocurrir desde error
positivo o positivo.
Aquí hay una salida de muestra:
Temperature: 22.937 Error: 17.375 Output: 1
Temperature: 26.437 Error: 14.875 Output: 1
Temperature: 31.125 Error: 10.375 Output: 1
Temperature: 35.937 Error: 5.438000000000002 Output: 1
Temperature: 39.875 Error: 1.375 Output: 1
Temperature: 43.437 Error: -2.375 Output: 0.9525
Temperature: 46.625 Error: -5.561999999999998 Output: 0.8412600000000001
Temperature: 49.5 Error: -8.625 Output: 0.6687600000000001
Temperature: 51.875 Error: -11.125 Output: 0.4462600000000001
Temperature: 52.0 Error: -12.311999999999998 Output: 0.20002000000000014
Temperature: 50.062 Error: -10.811999999999998 Output: 0
Temperature: 46.875 Error: -7.936999999999998 Output: 0
Temperature: 43.437 Error: -4.5 Output: 0
Temperature: 40.125 Error: -1.125 Output: 0
Temperature: 37.062 Error: 2.0 Output: 0.04
Temperature: 34.5 Error: 4.688000000000002 Output: 0.13376000000000005
Temperature: 32.125 Error: 7.125 Output: 0.27626000000000006
Temperature: 30.187 Error: 9.25 Output: 0.46126000000000006
Temperature: 28.625 Error: 10.875 Output: 0.67876
Temperature: 29.812 Error: 11.062999999999999 Output: 0.90002
Temperature: 33.312 Error: 7.938000000000002 Output: 1
Temperature: 37.375 Error: 3.9380000000000024 Output: 1
Temperature: 41.812 Error: -0.375 Output: 0.9925
Si alguien tiene una idea sobre cómo darle a Peltier un significado a los valores de salida, lo apreciaría.