Уровень воды в емкости
- Войдите на сайт для отправки комментариев
Встретил как-то в сети проект по определению уровня воды в емкости, простой, на четырех транзисторах. Решил добавить туда ардуину.
Вот что исходная схема, только на выходах слева у меня реле и дисплей.
Печатка получилась такая, под arduino pro mini.
На всякий случай выведены отдельно пины для перепрошивки дуины. Схема функциональная, с запасом, нарисовать ее для лута можно даже маркером.
вверху две большие колодки под провода - слева выходы щупов, справа питание. 6-7 вольт вполне достаточно.

Фото готового девайса

В архиве скетч, плата в lay6, фотки.
Техподдержки нет, скетч нормально комментирован. Мне пришел ультразвуковой дальномер так что сделал в результате проект на нём, этот до блеска не допиливал, только убедился в работоспособности.
на фото выше желтый провод (плюсовой вход реле) идет в клеммную колодку, это исходная версия платы. сейчас там просто плюс питания, суйте его в выход цифрового пина 2.
подключение дисплея - с 4 по 8 цифровые пины, распиновка в скетче. остальное вроде очевидно.
архив здесь https://yadi.sk/d/ECyGiq39kUdQR
скетч. присутствует быдлокод, писал быстро, особо не проверял. для работы вочдога нужен оптибут.
// УПРАВЛЕНИЕ НАСОСОМ, 3 УРОВНЯ ВОДЫ В БАКЕ #include <avr/wdt.h> //#include "Arduino.h" #include "U8glib.h" U8GLIB_PCD8544 u8g(8, 7, 6, 5, 4); // подключение дисплея NOKIA 5110, по порядку- SCK=CLK, MOSI=DN, CS=CE, A0=DC, Reset #define LedPin 13 // пин сигнального светодиода #define RelePin 2 // пин реле #define SoundPin 3 // пин звуковой сигнализации #define LowPin 10 // нижний уровень воды #define MiddlePin 11 // средний уровень воды #define UpperPin 12 // верхний уровень воды int WaterLevel = -1; // 0 - нулевой уровень воды, 1- нижний уровень, 2 - средний уровень, 3 - высокий уровень, -1 - ошибка unsigned long PumpingTime = 0; // текущее время работы насоса (с момента последнего включения) unsigned long IdleTime = 0; // текущее вермя простоя насоса (с момента последнего выключения) unsigned long StartPumpingTime = 0; // момент последнего включения unsigned long StopPumpingTime = 0; // момент последнего выключения unsigned long Pause = 3000; // время на техническую паузу между циклами boolean Pumping = 0; // флаг состояния насоса вкл/выкл String Error = ""; String WLevel = ""; void setup() { u8g.setColorIndex(1); // pixel on Serial.begin(9600); pinMode(LedPin,OUTPUT); pinMode(RelePin,OUTPUT); digitalWrite(RelePin, LOW); delay(100); pinMode(SoundPin, OUTPUT); pinMode(LowPin,INPUT); pinMode(MiddlePin,INPUT); pinMode(UpperPin,INPUT); delay(1000); // wdt_enable (WDTO_8S); } void loop() { u8g.firstPage(); wDelay(Pause); // пауза цикла + wd_reset WaterLevel = CheckLevel(); // checking level if (Pumping) PumpingTime = millis() - StartPumpingTime; else IdleTime = millis() - StopPumpingTime; CheckErrors(); if (WaterLevel == 0 || WaterLevel ==1 && IdleTime > 60000) // если уровень низкий и время простоя > 1 min { if(!Pumping) PowerOnPump(); } if (WaterLevel < 2 && IdleTime > 120000) // если уровень средний и время простоя > 2 min { if (!Pumping) PowerOnPump(); } if (WaterLevel == 3) { PowerOffPump(); } } int CheckLevel() { boolean all_OK = 0; // флаг успешности проверки на ошибки byte counter = 0; while (!all_OK) { delay(1000); WaterLevel == -1; if (digitalRead(UpperPin) == LOW ) // проверить на верхний уровень { if (digitalRead(MiddlePin) == LOW && digitalRead(LowPin) == LOW) WaterLevel = 3; // верхний уровень ДА else WaterLevel = -1; // ошибка } else if (digitalRead(MiddlePin) == LOW ) { if (digitalRead(LowPin) == LOW) WaterLevel = 2; // средний уровень ДА else WaterLevel = -1; // ошибка } else if (digitalRead(LowPin) == LOW ) WaterLevel = 1; // нижний уровень ДА else WaterLevel = 0; // нулевой уровень ДА delay(100); if (WaterLevel == -1) { delay (1000); counter++; if (counter > 100) return WaterLevel; // появилась ошибка - здесь можно поставить перезагрузку } else all_OK = 1; } return WaterLevel; } void PowerOnPump() { if (IdleTime < 120000) delay (120000); // перед включением насоса задержка на две минуты (debounce) PumpingTime = 0; IdleTime = 0; if (!Pumping) { digitalWrite(RelePin, HIGH); delay (1000); Pumping = 1; StartPumpingTime = millis(); } else Error = "Already pumping"; } void PowerOffPump() { PumpingTime = 0; IdleTime = 0; delay(100); if (Pumping) { digitalWrite(RelePin, LOW); Pumping = 0; StopPumpingTime = millis(); } else { //Error = "Already Stopped"; Pumping = 0; digitalWrite(RelePin, LOW); } } int CheckErrors() // проверка ошибочных ситуаций { do {draw();} while(u8g.nextPage()); Serial.println("_______________________________"); if(Pumping) { Serial.print("Pumping time= "); Serial.print(PumpingTime/1000); Serial.println(" sec"); } else { Serial.print("Idle time= "); Serial.print(IdleTime/1000); Serial.println(" sec"); } Serial.print("Water level ="); Serial.println(WaterLevel); if (Pumping && PumpingTime > 1200000 && WaterLevel < 1) // ошибка - насос работает больше 20 мин но уровень низкий Error = "Slow rate"; if (Pumping && PumpingTime > 1800000) // ошибка - насос работает больше получаса Error = "Long pumping"; if (WaterLevel == -1) Error = "Wrong level"; // ошибка - одновременно активны верхний и нижний датчкик, но не средний if (Error) // обработчик ошибочной ситуации { Serial.print("E: "); Serial.println(Error); PowerOffPump(); delay(2000); while(1){ tone (SoundPin, 500); delay(100); tone(SoundPin, 1000); delay(100);} } else { Serial.println("OK");} Serial.print("Uptime = "); Serial.print(millis()/60000); Serial.println(" min"); } void wDelay(unsigned long Pau) // для пауз при активном вочдоге { while (Pau >= 5000) // { delay(5000); wdt_reset(); Pau = Pau - 5000;} delay(Pau); wdt_reset(); } void draw() { if (WaterLevel == 0) WLevel = " empty"; else if (WaterLevel == 1) WLevel = " low"; else if (WaterLevel == 2) WLevel = "middle"; else if (WaterLevel == 3) WLevel = " high"; else WLevel = "-- n/a --"; u8g.setFont(u8g_font_5x8r); u8g.setPrintPos(2, 10); u8g.print ("On ="); u8g.setPrintPos(30, 10); u8g.print(PumpingTime/1000,DEC); u8g.setPrintPos(70, 10); u8g.print("sec"); u8g.setPrintPos(2, 20); u8g.print ("Off = "); u8g.setPrintPos(30, 20); u8g.print(IdleTime/1000,DEC); u8g.setPrintPos(70, 20); u8g.print("sec"); u8g.setPrintPos(2, 30); u8g.print ("Level ="); u8g.setPrintPos(55, 30); u8g.print(WLevel); u8g.setPrintPos(2, 40); u8g.print ("Uptime ="); u8g.setPrintPos(50, 40); if (Error = "") { u8g.print(millis()/60000); u8g.setPrintPos(70, 40); u8g.print("min"); } else u8g.print(Error); }