Помощь проектом слишком быстрого переключения реле водяного насоса.

У меня возникли проблемы с моим проектом.

Я использую датчик уровня воды с двумя выходами: вентилятор на 5 В и водяной насос. Вот схема подключения project.

Что я хочу сделать с этим проектом:

  1. Когда уровень воды достигает 2 см, включается водяной насос, а вентилятор выключается.
  2. Когда уровень воды составляет менее 2 см, водяной насос выключается и включается вентилятор.

Проблема в том, что когда уровень воды ниже порогового значения, показания датчика весьма нестабильны, из-за чего реле переключается слишком быстро (посмотреть видео).

Как устранить эту проблему?

#include <Wire.h>
#include <Blynk.h>
#include <LiquidCrystal_I2C.h>
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

//Инициализируем ЖК-дисплей
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "xxx";//Введите токен аутентификации
char ssid[] = "xxx";//Введите имя WIFI
char pass[] = "xxx";//Введите пароль WIFI
BlynkTimer timer;

#define pinSensor A0 
#define PIN_RELAY_1  D3
#define PIN_RELAY_2  D4
const int startThreshold = 2; // откачка должна начаться при startThreshold [см] и выше
const int stopThreshold  = 1; // перекачка должна начаться при стоп-пороге [см] и ниже

int sensorValue = 0; // целое число показаний датчика
float tinggiAir = 0; // высота воды
float sensorVoltage = 0; // датчик напряжения
int nilaiMax = 686; // максимальное значение датчика после его полного погружения в воду
float panjangSensor = 4.0 ; // высота датчика в см

enum StatusType {CHECKLEVEL, LEVELHIGH, PUMPING};
StatusType status = LEVELHIGH;   // Начнем с LEVELHIGH, чтобы проверить уровень и правильно настроить отображение

void setup() {
  Serial.begin(115200);
  lcd.begin(); 
  Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
  lcd.backlight();
  pinMode(PIN_RELAY_1, OUTPUT);
  pinMode(PIN_RELAY_2, OUTPUT);
  digitalWrite(PIN_RELAY_1, LOW);
  digitalWrite(PIN_RELAY_2, LOW);
  lcd.setCursor(0, 0);
  lcd.print("Water level");
  lcd.setCursor(4, 1);
  lcd.print("Monitoring");
  delay(1000);
  lcd.clear();
  timer.setInterval(100L, wLevel);
}
void wLevel() {
   sensorValue = analogRead(pinSensor);
  tinggiAir = sensorValue*panjangSensor/nilaiMax;
  sensorVoltage = sensorValue*5.0/686;
}

void loop() {
      Blynk.run();
     timer.run();
     handleStatus();
}

void handleStatus() {
  switch (status) {
    case CHECKLEVEL:
      // Ждем уровня выше порога
      if (tinggiAir >= startThreshold) { // если wlevel больше, чем startThreshold [см], то
        status = LEVELHIGH;
        Serial.println("LEVELHIGH");
      }
      break;
    case LEVELHIGH:
      levelIsHigh();
      break;
    case PUMPING:
      if (tinggiAir < stopThreshold) { // если wlevel меньше, чем stopThreshold [см] (используйте гистерезис!), то
        levelIsLowAgain();
        status = CHECKLEVEL;
        Serial.println("CHECKLEVEL");
      }
      break;
  }
  displayValues();
}

void displayValues() {
  static int oldSensorValue = -1; // переменная для хранения значения показания датчика в целочисленной форме
  float oldTinggiAir = -1; // переменная для хранения уровня воды
  float oldSensorVoltage = -1; // для хранения значения уровня воды

  if (oldSensorValue != sensorValue ||
      oldTinggiAir   != tinggiAir   ||
      oldSensorVoltage != sensorVoltage) {
    Serial.print("Sensor Value = ");
    Serial.println(sensorValue);
    Serial.print("Sensor Voltage = ");
    Serial.println(sensorVoltage);
    Serial.print("Tinggi Air = ");
    Serial.println(tinggiAir);
    Serial.println();
    // Отображение ЖК-дисплея
    lcd.setCursor(0, 0);
    lcd.print("WLevel:");
    lcd.print(tinggiAir);
    lcd.setCursor(12, 0);
    lcd.print("cm");
    oldSensorValue = sensorValue;
    oldTinggiAir   = tinggiAir;
    oldSensorVoltage = sensorVoltage;
    Blynk.virtualWrite(V0, tinggiAir);
  }
}
void levelIsHigh() {
  digitalWrite(PIN_RELAY_1, HIGH);
  digitalWrite(PIN_RELAY_2, LOW);
  lcd.setCursor(0, 1);
  lcd.print("F:OFF P:ON");
  Blynk.logEvent("wlevel", "wLevel more than 2cm");
  status = PUMPING;
  Serial.println("PUMPING");
}

void levelIsLowAgain() {
  digitalWrite(PIN_RELAY_1, LOW);
  digitalWrite(PIN_RELAY_2, HIGH);
  lcd.setCursor(0, 1);
  lcd.print("F:ON P:OFF");
  status = CHECKLEVEL;
  Serial.println("CHECKLEVEL");
}

, 👍1

Обсуждение

Вы можете считать несколько значений с датчика уровня и усреднить их, чтобы получить более стабильные показания., @StarCat

И добавим немного гистерезиса, @KIIV

Попробуйте устранить дребезг датчика на несколько секунд, если вам не нужен более быстрый ответ., @Gil

Вы предпочитаете *программное решение* или *аппаратное решение*? Если аппаратное обеспечение, вам нужно найти компаратор (или операционный усилитель) — возможно, на вашем ESP8266 или отдельное аппаратное обеспечение. [REF1](https://circuitcellar.com/resources/comparator-hysteresis-2/), [REF2](https://www.electronics-tutorials.ws/opamp/op-amp-comparator.html)., @Seamus


1 ответ


4

Проблема заключается в самой спецификации. По вашим правилам, что должен делать насос, если уровень воды ровно 2 см? Конечно, не существует такого понятия, как точные физические измерения. Но вы должны понимать, что каждая система измерения зашумлена. Шум – это факт жизни, с которым вам приходится иметь дело, играя с оборудованием. Вы можете попробуйте сделать его меньше (путем фильтрации), но он всегда будет там. Сейчас вопрос в том, что делать насосу, если разница между уровень воды и необходимые 2 см меньше амплитуды шума?

Стандартное решение, предложенное КМИВ, – реализовать некоторые гистерезис. Вы определяете два пороговых значения: один для включения насоса. и еще один, нижний порог его отключения. Когда будут показания между этими двумя порогами вы живете один насос, в каком бы то ни было заявите, что это было раньше.

В псевдокоде:

const float low_threshold = 1.9;
const float high_threshold = 2.1;

void loop() {
    float water_level = get_level_reading();
    if (water_level < low_threshold)
        turn_pump_off();
    if (water_level > high_threshold)
        turn_pump_on();
}

Если разница между этими порогами больше, чем шум амплитуда, шум не будет мешать вашей системе.

,