Buenos días a todos,
Le cuento mi problema a ver si damos con la clave. Anticipo que mis conocimientos en programación son los justos para no prender fuego el escritorio.
El caso es que tengo un circuito en el que por un lado puedo hacer lecturas de caudal en un tubo y por otro puedo hacer que una turbina se mueva a un valor de pwm dado.
Todo esto lo comando introduciendo una orden y un valor por el puerto serial.
El problema viene ahora cuando quiero controlar mediante un PID para que, dando una valor de flujo dado, la turbina ponga el valor de PWM necesario para ese flujo.
Con el código que tengo, cuando escribo pid y un valor de flujo deseado, la turbina arranca, pero no hace fluctuar el pwm.
He probado con varias librerias (PID_v1, Pid_v2, ArduPid, PIDController de Luis en llamas) y todas sin resultados.
Les paso el código, yo lo tengo dividido en diferentes pestaña, pero se los pongo aquí todo junto.
#include <Wire.h>
#include <Adafruit_ADS1X15.h>
#include <BME280I2C.h>
#include <BTS7960.h>
#include "PIDController.hpp"
//Entorno motores
#define L_EN 8
#define R_EN 8
#define L_PWM 10 //pin 5 supports 980hz pwm frequency
#define R_PWM 9 //pin 6 supports 980hz pwm frequency
int imotor = 0;
int iobjetivo = 0;
BTS7960 motor1(L_EN, R_EN, L_PWM, R_PWM); //This method will create a object of the class BTS7960
//Entorno sensores de presión
//Sensores absoluta
Adafruit_ADS1115 ads;
const float multiplier = 0.1875F;
double Q1, Q2;
//Sensor barométrica
BME280I2C bme;
//Calibración
bool calibrated = false; // Indica si se ha realizado la calibración
float pressatm, corr0, corr1, corr2, corr3;
//Entorno PID
PID::PIDParameters<double> parameters(4.0, 0.2, 1);
PID::PIDController<double> pidController(parameters);
//Entorno lectura serial
int accion = 0;
double value;
void setup(void) {
Serial.begin(9600);
inisensores();
calibracionsensores();
motor1.begin(); //This method will set the motor driver pins as output
motor1.enable();
pidController.Input = caudalimetro(1);
pidController.Setpoint = 100;
pidController.SetOutputLimits (30,100);
pidController.TurnOn();
}
void loop(void) {
if (Serial.available()) {
String command = Serial.readStringUntil('\n'); // Leer el comando enviado por el puerto serial
// Extraer el comando y el valor (si está presente)
String task = command.substring(0, command.indexOf(' '));
String valueString = command.substring(command.indexOf(' ') + 1);
value = valueString.toDouble();
// Ejecutar la tarea correspondiente al comando recibido
if (task == "calibrar") {
Serial.println("calibrando");
} else if (task == "inimotor") {
accion = 1;
} else if (task == "parar") {
accion = 2;
} else if ((task == "pid")) {
accion = 3;
}else{
Serial.println("Comando inválido");
}
}
switch (accion){
case (1):
iobjetivo = value;
arranquerampa(iobjetivo,10);
Serial.println("iniciando motor");
break;
case (2):
paradaMotor();
imotor=0;
Serial.println("motor parado");
break;
case (3):
pidController.Input = caudalimetro(1);
pidController.Setpoint = value;
pidController.Update();
accionMotor(pidController.Output);
Serial.print("value: "); Serial.println(value,6);
Serial.print("PWM: "); Serial.println(pidController.Output);
Serial.print("caudal: "); Serial.println(caudalimetro(1),6);
delay (500);
break;
}
//Serial.println("Externo");
//Serial.print("caudal: "); Serial.println(caudalimetro(1),6);
//Serial.print("value: "); Serial.println(value,6);
//Serial.print("imotor: "); Serial.println(imotor);
// Serial.println(caudalimetro(1),6);
//Serial.println(" ");
delay (500);
}
void arranquerampa(int iobjetivo, int crecimiento){
if (imotor<iobjetivo){
motor1.pwm = imotor; //Set the speed, by default the speed is set to 255 you can change it
motor1.front(); //front functions should turn the motor in clockwise direction
imotor=imotor+crecimiento;
Serial.println(imotor);
delay(500);
}else if(imotor>iobjetivo){
motor1.pwm = imotor; //Set the speed, by default the speed is set to 255 you can change it
motor1.front(); //front functions should turn the motor in clockwise direction
imotor=imotor-crecimiento;
Serial.println(imotor);
delay(500);
}else if(imotor=iobjetivo){
accion=0;
}
}
void accionMotor(int imotor){
motor1.pwm = imotor; //Set the speed, by default the speed is set to 255 you can change it
motor1.front(); //front functions should turn the motor in clockwise direction
delay(500);
}
void paradaMotor(){
if (accion=2){
motor1.stop();
accion=0;
}
}
void inisensores(){
//Descomentar el que interese
ads.setGain(GAIN_TWOTHIRDS); //+/- 6.144V 1 bit = 0.1875mV (default)
//ads.setGain(GAIN_ONE); // +/- 4.096V 1 bit = 0.125mV
// ads.setGain(GAIN_TWO); +/- 2.048V 1 bit = 0.0625mV
// ads.setGain(GAIN_FOUR); +/- 1.024V 1 bit = 0.03125mV
// ads.setGain(GAIN_EIGHT); +/- 0.512V 1 bit = 0.015625mV
// ads.setGain(GAIN_SIXTEEN); +/- 0.256V 1 bit = 0.0078125mV
ads.begin();
}
void calibracionsensores(){
Wire.begin();
bme.begin();
Serial.println("Iniciando calibracion");
// Leer la presión atmosférica
printBME280Data(&Serial);
delay(500);
// Leer la presión de los Venturi
int16_t adc0 = ads.readADC_SingleEnded(0);
int16_t adc1 = ads.readADC_SingleEnded(1);
int16_t adc2 = ads.readADC_SingleEnded(2);
int16_t adc3 = ads.readADC_SingleEnded(3);
float press0 = ((((((adc0) * multiplier/1000)/5.05)+0.00842)/0.002421)*1000)+corr0;
float press1 = ((((((adc1) * multiplier/1000)/5.05)+0.00842)/0.002421)*1000)+corr1;
float press2 = ((((((adc2) * multiplier/1000)/5.05)+0.00842)/0.002421)*1000)+corr2;
float press3 = ((((((adc3) * multiplier/1000)/5.05)+0.00842)/0.002421)*1000)+corr3;
//Calibración de sensores de presión
corr0 = (press0 - pressatm)*-1;
corr1 = (press1 - pressatm)*-1;
corr2 = (press2 - pressatm)*-1;
corr3 = (press3 - pressatm)*-1;
calibrated = true; // Marcar que la calibración se ha realizado
Serial.println("Finalizando calibracion");
}
double caudalimetro(int sensor){
int16_t adcx, adcy;
double corrx, corry;
switch (sensor){
case 1:
adcx = ads.readADC_SingleEnded(0); //ADS1115 da una señal de -32.768 a 32767
adcy = ads.readADC_SingleEnded(1);
corrx = corr0;
corry = corr1;
break;
case 2:
adcx = ads.readADC_SingleEnded(2); //ADS1115 da una señal de -32.768 a 32767
adcy = ads.readADC_SingleEnded(3);
corrx = corr2;
corry = corr3;
break;
}
float pressx = ((((((adcx) * multiplier/1000)/5.05)+0.00842)/0.002421)*1000)+corrx;
float pressy = ((((((adcy) * multiplier/1000)/5.05)+0.00842)/0.002421)*1000)+corry;
double Q = 0.000100655*sqrt(abs(pressx-pressy));
return Q;
}
void printBME280Data (Stream* client){
float temp(NAN), hum(NAN), pres(NAN);
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
pressatm = pres;
//client->print("Temp: ");
// client->print(temp);
// client->print("°"+ String(tempUnit == BME280::TempUnit_Celsius ? 'C' :'F'));
//client->print("\t\tHumidity: ");
//client->print(hum);
//client->print("% RH");
//client->print("\t\tPressure: ");
//client->print(pres);
//client->println("Pa");
//client->print("\t\tATMPressure: ");
//client->print(pressatm);
//client->println("Pa");
delay(1000);
}
Muchas gracias de antemano por la ayuda
