Hola. estoy realizando una maqueta de control de nivel con Arduino UNO, un sensor HC-SR04 y unas bombas dc 12v para llenado y vaciado (uso modulo relé). mi problema es en un determinado rango de medición, al asignar el nivel entre los rangos 0-2cm y 7-16cm (16 es la máxima altura) el sistema no tiene problemas. Pero al asignar cualquier nivel entre 3-6cm el sistema tiene problemas de funcionamiento. Por ejemplo, si asigno el nivel de liquido a 4 cm de altura, físicamente en mi maqueta hay 5.2 cm de agua y en el monitor serial me aparecen lecturas de 6.4cm apróx. Ya probé modificando los pines de conexión y use otro sensor del mismo tipo, donde se presentó el mismo problema. Espero alguien pueda orientarme para solucionar este dilema.
El error esta en la línea 27 del código , además hay un error de conexión en el pin 4 (después me cuentas si adivine correctamente)
Saludos
Mil disculpas, dejo el código adjunto
const int numReadings = 20;
float readings[numReadings]; // las lecturas del sensor ultrasónico
int readIndex = 0; // el índice de la lectura actual
float total = 0; // el total acumulado
float average = 0; // el promedio
const int Trigger = 13; // Pin digital 12 para el Trigger del sensor
const int Echo = 12; // Pin digital 10 para el Echo del sensor
unsigned long t; // tiempo que demora en llegar el eco
float nivel; // distancia en centímetros
int pwm_llenado = 10; // Pin PWM para bomba de llenado
int pwm_vaciado = 9; // Pin PWM para bomba de vaciado
float setPoint = -1; // Valor inicial del setpoint, indicando que no ha sido establecido
float ek = 0, ek1 = 0;
float deltaT = 0.01;
float derivada = 0;
float integral = 0;
float uk = 0;
float kp = 42;
float ki = 36;
float kd = 12;
float correctionFactor = 0.65; // Factor de corrección
void setup() {
Serial.begin(9600);
pinMode(Trigger, OUTPUT);
pinMode(Echo, INPUT);
digitalWrite(Trigger, LOW);
pinMode(pwm_llenado, OUTPUT);
pinMode(pwm_vaciado, OUTPUT);
analogWrite(pwm_llenado, 0);
analogWrite(pwm_vaciado, 0);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
Serial.println("Ingrese el nuevo setpoint (en cm):");
}
void loop() {
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
setPoint = input.toFloat();
Serial.print("Nuevo setpoint: ");
Serial.println(setPoint);
}
// Verificar si el setpoint ha sido establecido
if (setPoint < 0) {
// Si el setpoint no ha sido establecido, esperar
Serial.println("Esperando que se ingrese el setpoint...");
delay(500);
return;
}
digitalWrite(Trigger, HIGH);
delayMicroseconds(5);
digitalWrite(Trigger, LOW);
t = pulseIn(Echo, HIGH, 20000);
if (t == 0) {
Serial.println("Error: No se detectó el eco");
return;
}
nivel = t / 59.0;
nivel = 23 - nivel;
if (nivel < 0) nivel = 0;
// Aplica el factor de corrección a cada lectura antes del promedio
nivel += correctionFactor;
total = total - readings[readIndex];
readings[readIndex] = nivel;
total = total + readings[readIndex];
readIndex = (readIndex + 1) % numReadings;
average = total / numReadings;
// Ajuste adicional después del promedio
average += correctionFactor;
ek = setPoint - average;
derivada = (ek - ek1) / deltaT;
integral += ((ek + ek1) / 2) * deltaT;
integral = constrain(integral, -50, 50); // Ajuste más fino del límite
ek1 = ek;
uk = kp * ek + ki * integral + kd * derivada;
uk = abs(uk);
uk = constrain(uk, 170, 255);
if (setPoint == 0 && nivel == 0) {
analogWrite(pwm_vaciado, 0); // Detener la bomba de vaciado si el setpoint es 0 y el nivel es 0
} else if (nivel < setPoint) {
analogWrite(pwm_llenado, uk);
analogWrite(pwm_vaciado, 0);
} else {
analogWrite(pwm_llenado, 0);
analogWrite(pwm_vaciado, uk);
}
Serial.print("Distancia: ");
Serial.print(average);
Serial.print("\tSetpoint: ");
Serial.println(setPoint);
delay(500);
}
-
Puedes explicar cómo funciona esta corrección y por qué se hace dos veces?
-
Comparte por favor una impresión de las primeras 30-40 lineas