Falla de lectura sensor ultrásonico

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