Controlador PID de presión

Hola, necesito hacer un controlador PID de presión, estoy intentando usar la librería "PID_v1.h", pero no la estoy entendiendo muy bien, la idea es que usando este controlador el Arduino mida la presión a través de un sensor de presión y abra o cierre una válvula (conectada a un relé) manteniendo la presión constante, pero no lo estoy logrando, no entiendo muy bien como usar la librería, la idea del código es poder cambiar el setpoint en cualquier momento a través de un teclado numérico conectado al Arduino y que esto se muestre en una pantalla LCD, esa parte funciona bien, pero el control PID no esta funcionando, ya que, independientemente de el setpoint, el output de la función intercala entre 0 y 1, no comprendo porque

#include <PID_v1.h>
#include <Key.h>
#include <Keypad.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'},
};
byte rowPins[ROWS] = { 11, 10, 9, 8 }; //connect to the row pinouts of the keypad
byte colPins[COLS] = { 7, 6, 5, 4 }; //connect to the column pinouts of the keypad

float SPA = 5.00;
float N_SPA = 0.0;
int N_SPAint = 0;
int N_SPAdec = 0;

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
char key;
int dato;

double setpoint = 5.00; 
double input, output;
double Kp = 1, Ki = 0.1, Kd = 0.01;

PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

int relayPin = 26;  
int sensorPin = A0;

void setup()
{
  Serial.begin(9600);
  pinMode(relayPin, OUTPUT);
  pinMode(sensorPin, INPUT);
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  lcd.init();                      
  lcd.backlight();
  myPID.SetMode(AUTOMATIC);
}



void loop()
{
  N_SPA = 0.0; // Nuevo Setpoint
  N_SPAint = 0; //Parte entera del nuevo Setpoint
  N_SPAdec = 0; //Parte decimal del nuevo Setpoint

  ControladorPID_A(); //Llamamos al controlador PID

  lcd.setCursor(0,0);
  lcd.print("Contorlador A");
  lcd.setCursor(0,1);
  lcd.print("Setpoint: " + String(SPA) + " bares");
  lcd.setCursor(0,2);
  lcd.print("Presion: " + String(2.5) + " bares" );

  key = keypad.getKey();

  if (key)
  {
    if(key == 'A')
    { 
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Introducir nuevo Setpoint:");
      int car = 0; //definimos el entero car que corresponde a la cantidad de caracteres que se han ingresado del nuevo Setpoint

      while(car != 4) // el Setpoint siempre tendra 4 caracteres 2 enteros y 2 decimales
      {
        key = Controladores_PID_r(); //llamamos a la funcion recursiva del controlador PID

        if(isdigit(key))
        {
          key -= 48; //Convertimos el char key en un int
          if(car >= 2) // Esta es la parte decimal del nuevo Setpoint, lo hice así para poder ponerlo digito por digito en la LCD
          {
            N_SPAdec = N_SPAdec*10 + key; //Multiplica el valor anterior de N_SPAdec por 10 y le suma la nueva entrada
            digitalWrite(13,HIGH);
            lcd.setCursor(0,3);
            lcd.print(String(N_SPAint) + "." + String(N_SPAdec));
            car += 1;
          }
          
          else
          {
            N_SPAint = N_SPAint*10 + key; //Multiplica el valor anterior de N_SPAint por 10 y le suma la nueva entrada
            digitalWrite(13,HIGH);
            lcd.setCursor(0,3);
            lcd.print(N_SPAint);
            car += 1;
          }
        }
      }
      
      N_SPA = N_SPAint + N_SPAdec*0.01; //Guardamos el nuevo Setpoint

      if(N_SPA < 13.00) //Comprobamos que no exceda el maximo
      {
        SPA = N_SPA;
        lcd.setCursor(0,3);
        lcd.print(SPA);

        Controladores_PID();

        delay(1000);
        lcd.clear();
      }

      else
      {
        lcd.setCursor(0,3);
        lcd.print("Valor excede el maximo");

        Controladores_PID();

        delay(1000);
        lcd.clear();
      }

    }
  
  }
}

void ControladorPID_A() //Definimos una funcion que Haga el control PID
{
  setpoint = SPA;
  input = random(0, 14); //como aun no tengo el sensor de presión estoy haciendo pruebas con un numero aleatorio entre 0 y 13
  output = myPID.Compute();
  if (output > 0) // Si el output del PID es positivo, abrimos la valvula (aumentando la presión)
  {
    digitalWrite(relayPin, HIGH);
  } 
  else // Si el output del PID es negativo, cerramos la valvula y deisminuimos la presion
  {
    digitalWrite(relayPin, LOW); 
  }

}

char Controladores_PID_r() //Definimos una funcion recursiva para que este midiendo la presion hasta que se presione un tecla en el teclado
{ ControladorPID_A();

  key = keypad.getKey();
    if (key)
    {
      return key;
    }
    
    else
    {
      return Controladores_PID_r();
    }
}

Como aun no tengo el sensor de presión estoy usando un numero aleatorio entre 0 y 13 para hacer las pruebas.
Gracias de antemano :smiley:

A relay is either on or off. You don't need a PID for this. Just a setpoint and some hysteresis. Turn the relay on if the pressure is too low and turn it off if it is too high. PID is for controlling things with a variable output.

Un relé está encendido o apagado. No necesitas un PID para esto. Sólo un punto de ajuste y algo de histéresis. Encienda el relé si la presión es demasiado baja y apáguelo si es demasiado alta. PID sirve para controlar cosas con una salida variable.

He trasladado su tema de una categoría de idioma inglés del foro a la categoría International > Español @vvalenzuelao.

En adelante por favor usar la categoría apropiada a la lengua en que queráis publicar. Esto es importante para el uso responsable del foro, y esta explicado aquí la guía "How to get the best out of this forum".
Este guía contiene mucha información útil. Por favor leer.

De antemano, muchas gracias por cooperar.

.Hi,
Los setting del pid estan en zeros. Estos se hacen de acuerdo al response de la variable.
N_SPA = 0.0; // Nuevo Setpoint . N_SPAint = 0; //Parte entera del nuevo Setpoint N_SPAdec = 0;
.

Moderador:
Por favor, lee las Normas del foro
Si posteas en el foro en inglés usa idioma inglés para expresarte, eso incluye los comentarios de tu código. Si un código tiene comentarios en español también moverán tu hilo a esta sección en Español.
Si escribes en español debes usar el foro Arduino en español

Revisa porque existe una solucion de AutoTunning. Busca en Github esta libreria y verás que uno de sus ejemplos tienen el autotunning. Permite autoajustar las constante Kp, Kd y Ki.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.