Hola muy buenas estoy intentando hacer un PID para controlar la temperatura del interior de una maqueta de invernadero y lo quiero hacer mediante 2 ventiladores, uno será el que inserte calor en la maqueta mediante una bombilla y el otro lo que hace es enfriar el interior.
Estoy usando la librería PID de arduino.
¿ Dónde esta el problema ? El problema es que no se donde colocar la entrada (Input) si en el void Compute()o en el void loop() os dejo el código:
#include <PID_v1.h>
#include <Sensirion.h>
uint8_t dataPinInt = 8;
uint8_t clockPinInt = 9;
int motor1 = 6;
int motor2 = 5;
float temperatureInt;
float humidityInt;
float dewpointInt;
int pwmc=255;
int pwmf=255;
//Variablesdetrabajo.
unsigned long lastTime;
double Input,Output,Setpoint;
double ITerm,lastInput;
double kp=2,ki=5,kd=1;
int SampleTime;
double outMin=27.9,outMax=28.1;
bool inAuto=false;
#define MANUAL 0
#define AUTOMATIC 1
#define DIRECT 0
#define REVERSE 1
int controllerDirection=DIRECT;
PID myPID(&Input,&Output,&Setpoint,2,5,1,DIRECT);
Sensirion tempSensorInt = Sensirion(dataPinInt, clockPinInt);
void setup() {
Serial.begin(9600);
pinMode(6, OUTPUT);
pinMode(5, OUTPUT);
analogWrite(motor2,pwmf);
analogWrite(motor1,pwmc);
Setpoint=28;
myPID.SetTunings(2,5,1);
myPID.SetSampleTime(600);
myPID.SetOutputLimits(28.5,28.6);
myPID.SetMode(AUTOMATIC);
myPID.SetControllerDirection(DIRECT);
}
void Compute()
{
if(!inAuto)return;
unsigned long now=millis();
int timeChange=(now-lastTime);
if(timeChange>=SampleTime)
{
//Calculamos todos los errores.
double error=Setpoint-Input;
ITerm+=(ki*error);
if(ITerm>outMax)ITerm=outMax;
else if(ITerm<outMin)ITerm=outMin;
double dInput=(Input-lastInput);
//Calculamos la función de salida delPID.
Output=kp*error+ITerm-kd*dInput;
if(Output>outMax)Output=outMax;
else if(Output<outMin)Output=outMin;
//Guardamos el valor de algunas variables para el próximo recálculo.
lastInput=Input;
lastTime=now;
}
}
void SetSampleTime(int NewSampleTime)
{
if(NewSampleTime>0)
{
double ratio =(double)NewSampleTime/(double)SampleTime;
ki*=ratio;
kd/=ratio;
SampleTime=(unsigned long)NewSampleTime;
}
}
void SetOutputLimits(double Min,double Max)
{
if(Min>Max)return;
outMin=Min;
outMax=Max;
if(Output>outMax)Output=outMax;
else if(Output<outMin)Output=outMin;
if(ITerm>outMax)ITerm=outMax;
else if(ITerm<outMin)ITerm=outMin;
}
void SetMode(int Mode)
{
bool newAuto=(Mode==AUTOMATIC);
if(newAuto&&!inAuto)
{
Initialize();
}
inAuto=newAuto;
}
void Initialize()
{
lastInput=Input;
ITerm=Output;
if(ITerm>outMax)ITerm=outMax;
else if(ITerm<outMin)ITerm=outMin;
}
void SetControllerDirection(int Direction)
{
controllerDirection=Direction;
}
void loop()
{
tempSensorInt.measure(&temperatureInt, &humidityInt,&dewpointInt);
Serial.println(temperatureInt);
Input=temperatureInt;
myPID.Compute();
Serial.println(Output);
analogWrite(motor2,(int)(1-Output));
analogWrite(motor1,(int)Output);
}
La entrada será la temperatura que me mide el sensor y la comparo con el setpoint y se pone en marcha la función Compute() que es la que hace el PID, y la salida es la velocidad de los ventiladores.
El problema debe estar a la hora de ejecutarse la función Compute() ya que me devuelve siempre un Ouput de 28.6 y eso es lo que me escribirá en el ventilador caliente y eso se debe a que la entrada no cambia o es cero por eso no se donde poner la entrada (Input) en el void loop () o en el void Compute(), asi que me gustaría saber como enviar el Input desde el void loop() hasta a la función Compute() y que esta me devuelva el Output desde la función Compute() al void loop() para poder escribirlo en los ventiladores.
Un saludo y muchas gracias de antemano.