Датчик уровня поплавковый (при помощи делителя напряжения)
- Войдите на сайт для отправки комментариев
Здравствуйте уважаемые форумчане, пришёл к Вам с бедой в виде собственного незнания/неумения и прошу помощи. Пишу код для контроллера авто-подкачки на дачу (качать воду из приточного бака в водонапорный) и естественно решил, что мне необходимо знать уровень жидкости в баках, чтобы как то управлять включениями электро-задвижки и насоса.
Перечень компонентов: плата китайского производства "arduino UNO", резистор на 4.7 кОм - 11шт, экран LCD 2004 I2C символьный, провода соединительные.(в целом ещё будет: контактор ABB for din, реле ардуино или аналог 2 шт, клапан электромагнитный 24v, насос мембранный-погружной 220v, датчик температуры и влажности DHT 22)
Суть проблемы: необходимо отображать на LCD 2004 состояние поплавка корректно(запоминать предыдущее состояние, чтобы показания на дисплее не прыгали от 80 - 0 - 90 - 0 - 100%), ибо между герконами есть просвет в котором делитель показывает минимальное значение которое в моём коде приравнивается к 0% заполнения ёмкости.
Придумал следующие: использовал кучу (11 шт) резисторов номиналом 4.7 кОм, чтобы собрать делитель напряжения, и подключив к этой сборке герконы, магнитом замыкать соответствующие секции делителя. (это датчик уровня).
P.S. Поскольку начал заниматься программированием недавно, прошу не заострять внимание на "технике" письма. "я ещё на волшебник я только учусь". Также если будут советы по оформлению темы, то пишите их личными сообщениями, дабы не захламлять саму тему.

Код прилагаю.
[code]
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // Правила инициализации LCD (править по факту подключённого дисплея).
// Создаём объект, для работы с датчиком iarduino_DHT DHT(12); (недопилено)
const int sensor_inc_MIN_MAX = A0; //датчик уровня воды 1 (приточный бак)
const int sensor_MIN_MAX = A1; //датчик уровня воды 2 (напорный бак)
const int pomp = 6; //насос из промежуточного бака в водонапорный
const int pomp_on = 7; //состояние контактора насоса
const int valve = 8; //клапан притока в промежуточный бак
const int button_on = 10; //кнопка ВКЛ насоса
const int button_off = 11; //кнопка ВЫКЛ насоса
boolean button; //состояние кнопок
boolean relay; //состояние контактора насоса
boolean water_valve; //состояние электро-задвижки
int tact = 0; //количество выполненых циклов ПО
//int persent_barrel_2 = 0;
//void Button();
//void DHT();
//void Pomp();
//void Valve();
void Level();
void(* resetFunc) (void) = 0; //объявляем функцию reset с адресом 0
void setup() {
pinMode(sensor_inc_MIN_MAX, INPUT); //датчик уровня воды 1 (приточный бак)
pinMode(sensor_MIN_MAX, INPUT); //датчик уровня воды 3 (напорный бак)
pinMode(pomp, OUTPUT); //упр.реле насоса
pinMode(pomp_on, INPUT); //состояние контактора насоса
pinMode(valve, OUTPUT); //упр.реле электромагнитного клапана
pinMode(button_on, INPUT); //кнопка ВКЛ насоса
pinMode(button_off, INPUT); //кнопка ВЫКЛ насоса
digitalWrite(pomp, LOW); //упр.реле насоса
digitalWrite(pomp_on, LOW); //состояние контактора насоса
digitalWrite(valve, LOW); //упр.реле электромагнитного клапана
digitalWrite(button_on, LOW); //кнопка ВКЛ насоса
digitalWrite(button_off, LOW); //кнопка ВЫКЛ насоса
Serial.begin(9600);
//------- Инициализация дисплея и статичных надписей -------\\
lcd.init(); // Инициируем работу с LCD дисплеем
lcd.backlight(); // Включаем подсветку LCD дисплея
lcd.setCursor(0, 0); // Устанавливаем курсор в позицию (0 столбец, 0 строка)
lcd.clear();
lcd.print("Temp = c"); // "температура="
lcd.setCursor(11, 0);
lcd.print(" RH = %"); // "влажность="
lcd.setCursor(0, 2);
lcd.print("b1= %"); // "Бак_1-приточный"
lcd.setCursor(0, 3);
lcd.print("b2= %"); // "Бак_2-напорный"
lcd.setCursor(15, 2);
lcd.print("pomp"); // "насос"
}
void loop() {
while (true)
{
// Button();
// DHT();
// Pomp();
// Valve();
Level();
tact++;
delay(1000);
if (tact >= 500000) resetFunc(); //вызываем reset
Serial.println(tact);
//Serial.println(water_valve);
//Serial.println(relay);
//Serial.println(button);
//Serial.println(sensor_1);
//Serial.println(sensor_2);
//Serial.println(sensor_inc_1);
//Serial.println(sensor_inc_2);
}
}
//-------------------------------------работа кнопки-------------------------------------------------------
/*void Button()
{
if (digitalRead(button_on) == HIGH) //если кнопка нажата
{
delay(10);
button = true;
}
else if (digitalRead(button_off) == HIGH)
{
delay(10);
button = false;
}
}
//---------------------------------------работа насоса-------------------------------------------------------- (надо переориентировать на аналоговый датчик)
void Pomp() {
if (digitalRead(sensor_MIN == LOW || button==true))
{
do
{
digitalWrite(pomp, HIGH);
delay(50);
lcd.setCursor (16, 3);
lcd.print ("ON");
}
while (digitalRead(sensor_inc_MIN == LOW || sensor_MAX == HIGH || button == false));
lcd.setCursor (16, 3);
lcd.print ("OFF");
}
}
//---------------------------------------работа электроклапана------------------------------------------------ (надо пилить)
void Valve() {
if (digitalRead(sensor_inc_MAX == LOW))
{
water_valve = true;
delay(10);
}
else if (digitalRead(sensor_inc_MAX == HIGH))
{
water_valve = false;
delay(10);
}
}
//---------------------------------------уровни и вывод LCD---------------------------------------------------
*/
void Level() {
int rawReading = analogRead(A0);
int persent_barrel_1;
float volts = rawReading / 204.6;
Serial.println(volts);
if (volts > 0.34 && volts < 0.47)
{
persent_barrel_1 = 0;
Serial.println(" 0%");
}
else if (volts > 0.46 && volts < 0.52)
{
persent_barrel_1 = 10;
Serial.println(" 10%");
}
else if (volts > 0.53 && volts < 0.58)
{
persent_barrel_1 = 20;
Serial.println(" 20%");
}
else if (volts > 0.59 && volts < 0.64)
{
persent_barrel_1 = 30;
Serial.println(" 30%");
}
else if (volts > 0.65 && volts < 0.73)
{
persent_barrel_1 = 40;
Serial.println(" 40%");
}
else if (volts > 0.78 && volts < 0.85)
{
persent_barrel_1 = 50;
Serial.println(" 50%");
}
else if (volts > 0.95 && volts < 1.10)
{
persent_barrel_1 = 60;
Serial.println(" 60%");
}
else if (volts > 1.20 && volts < 1.27)
{
persent_barrel_1 = 70;
Serial.println(" 70%");
}
else if (volts > 1.60 && volts < 1.70)
{
persent_barrel_1 = 80;
Serial.println(" 80%");
}
else if (volts > 2.40 && volts < 2.60)
{
persent_barrel_1 = 90;
Serial.println(" 90%");
}
else if (volts > 4.40 && volts < 5.30)
{
persent_barrel_1 = 100;
Serial.println(" 100");
}
// if (persent_barrel_1 == 20||30||40||50||60||70||80||90||100 && volts < 0.47)
// {
// }
lcd.setCursor(3,2);
lcd.print(persent_barrel_1);
if (persent_barrel_1 < 100)
{
lcd.setCursor(5,2);
lcd.print(" ");
}
}
//---------------------------------------датчик температуры и влажности--------------------------------------- (недопилено)
//void DHT() {
//}
[/code]
Какой вопрос-то?
А переменный резистор на поплавок закрепить и по аналоговому входу читать не проще?
Какой вопрос-то?
Суть проблемы: необходимо отображать на LCD 2004 состояние поплавка корректно(запоминать предыдущее состояние, чтобы показания на дисплее не прыгали от 80 - 0 - 90 - 0 - 100%), ибо между герконами есть просвет в котором делитель показывает минимальное значение которое в моём коде приравнивается к 0% заполнения ёмкости.
А переменный резистор на поплавок закрепить и по аналоговому входу читать не проще?
А переменный резистор как будет выкручиваться в 0 когда поплавок поднимется вверх на верёвочке?(Видимо нужен подпружиненный резистор, а я такого не видел.)
Я делаю из подручных материалов. Иначе не пахнет diy.
А в этом состоянии "между" как долго поплавок может находится?
не парь мосх никому
https://aliexpress.ru/item/32961227791.html
врежь скока надо по высоте бака.
Какой вопрос-то?
Суть проблемы: необходимо отображать на LCD 2004 состояние поплавка корректно(запоминать предыдущее состояние, чтобы показания на дисплее не прыгали от 80 - 0 - 90 - 0 - 100%), ибо между герконами есть просвет в котором делитель показывает минимальное значение которое в моём коде приравнивается к 0% заполнения ёмкости.
И в чем вопрос-то?
При срабатывании геркона пишем x=5 или сколько надо. На экран выводим значение x.
Правильно ли я понял задачу? Надо при определенном низком уровне в водонапорном баке включить насос и из приемного бака накачать туда воды. При достижении определенного высокого уровня в водонапорном баке насос выключить. То есть, принцип сливного бачка. Так? Тогда зачем измерять промежуточные значения? Самое простое - купить "лягушку" от дренажного насоса (копеечное дело), поместить ее в приемный (водонапорный) бак, и вопрос кардинально решен. Мне кажется, что и ардуина тут вообще не нужна. Или я что-то не так понял?
А если, все-таки, привязываться к резисторной цепочке (по-прежнему, не думаю, что это нужно для выполнения задачи "включить-выключить насос"), то стоило бы не пользоваться переменными с плавающей точкой: зачем уж такая-то точность? Вполне достаточно отслеживать промежутки между целыми значениями напряжения, и переменные назначить как int. Намного меньше памяти сожрёт.
А если труба с герконами так дорога, купи длинный магнит, можно два-три и закрепи вертикально, чтобы мертвой зоны не было. Бак, ведь думаю, не пять метров высотой.
Я делал похожую конструкцию. Нужно 4 геркона. Будут отслеживать 4 уровня воды в баке.
мин - бак пустой, из него забирать воду нельзя. Нужно доливать.
мин+ - забирать воду можно. Нужно доливать.
макс- - забирать воду можно. Нужно доливать.
макс - забирать воду можно. Не нужно доливать.
От мин до мин+ это гистерезис на отбор воды.
От макс- до макс это гистерезис на долив воды.
При включении если поплавок не в точке макс, то включаем долив пока не достигнем точки макс или других точек, если изначально поплавок был между герконами. Запоминаем точку и можем изменить только если сработает другой геркон.
Где система безопасности? Датчиков много, а о защите ни слова.
Поскольку были выходные и на них выпал день рождения сына, то особо времени на ответ не было. Посему отвечаю всем в 1-ом сообщение. (прошу понять и простить)
А в этом состоянии "между" как долго поплавок может находится?
ну бак высотой 935 (бочка пластиковая), поделить на 10 уровней = 9.3 геркон срабатывает где-то на в диапазоне +/- 1 сантиметр при том магните что у меня есть так что нулевые зоны по 7 сантиметров.
не парь мосх никому
https://aliexpress.ru/item/32961227791.html
врежь скока надо по высоте бака.
Экономлю дискреты для других проектов, а за ссылочку спасибо.
Какой вопрос-то?
Суть проблемы: необходимо отображать на LCD 2004 состояние поплавка корректно(запоминать предыдущее состояние, чтобы показания на дисплее не прыгали от 80 - 0 - 90 - 0 - 100%), ибо между герконами есть просвет в котором делитель показывает минимальное значение которое в моём коде приравнивается к 0% заполнения ёмкости.
И в чем вопрос-то?
При срабатывании геркона пишем x=5 или сколько надо. На экран выводим значение x.
читайте код.
Правильно ли я понял задачу? Надо при определенном низком уровне в водонапорном баке включить насос и из приемного бака накачать туда воды. При достижении определенного высокого уровня в водонапорном баке насос выключить. То есть, принцип сливного бачка. Так? Тогда зачем измерять промежуточные значения? Самое простое - купить "лягушку" от дренажного насоса (копеечное дело), поместить ее в приемный (водонапорный) бак, и вопрос кардинально решен. Мне кажется, что и ардуина тут вообще не нужна. Или я что-то не так понял?
А если, все-таки, привязываться к резисторной цепочке (по-прежнему, не думаю, что это нужно для выполнения задачи "включить-выключить насос"), то стоило бы не пользоваться переменными с плавающей точкой: зачем уж такая-то точность? Вполне достаточно отслеживать промежутки между целыми значениями напряжения, и переменные назначить как int. Намного меньше памяти сожрёт.
Если бы я хотел собрать всё просто, я бы купил 2 поплавка от сливного бачка и пару концевиков, а тут другие цели.
А если труба с герконами так дорога, купи длинный магнит, можно два-три и закрепи вертикально, чтобы мертвой зоны не было. Бак, ведь думаю, не пять метров высотой.
Идея такая в голову приходила, но тогда будут моменты когда на делите будет исключаться 1 резистор что будет резко менять показания. ( буду пробовать, Спасибо )
Где система безопасности? Датчиков много, а о защите ни слова.
Честно даже не думал от чего/кого и что охранять, если подскажете буду признателен.
Я делал похожую конструкцию. Нужно 4 геркона. Будут отслеживать 4 уровня воды в баке.
мин - бак пустой, из него забирать воду нельзя. Нужно доливать.
мин+ - забирать воду можно. Нужно доливать.
макс- - забирать воду можно. Нужно доливать.
макс - забирать воду можно. Не нужно доливать.
От мин до мин+ это гистерезис на отбор воды.
От макс- до макс это гистерезис на долив воды.
При включении если поплавок не в точке макс, то включаем долив пока не достигнем точки макс или других точек, если изначально поплавок был между герконами. Запоминаем точку и можем изменить только если сработает другой геркон.
Честно, думал сделать именно так, и сделал на макете, потом захотел допилить экран, потом датчик температуры и влажности и тп... потом всё как в тумане, и вот я уже сижу собираю датчик уровня на магнитах и герконах с резисторами ... бесовщина какая-то =). А на самом деле просто хочется знать более-менее точный уровень в баках.
просто хочется знать более-менее точный уровень в баках.
Поставь тогда ультразвуковой даччик и по времени отражения УЗ волн будешь знать уровень воды в бочке, если постараешься канеш, до сантиметра.
Или ИК отражалку.
просто хочется знать более-менее точный уровень в баках.
Поставь тогда ультразвуковой даччик и по времени отражения УЗ волн будешь знать уровень воды в бочке, если постараешься канеш, до сантиметра.
Или ИК отражалку.
Почитал про использование ультразвукового модуля и могу сказать из прочитанного.
1) он боится конденсата на нём и всякого рода грязи.
2) привередлив к поверхностям от которых отражается звук.
3) делаю всё из имеющихся запчастей.
"ИК отражалку" не знал, не видел, если можно то ссылку в студию.
"ИК отражалку" не знал, не видел, если можно то ссылку в студию.
http://roboparts.ru/products/ik-datchik-urovnya-vodi
Но мне кажецца, ты всё усложняешь.
Вот смотри, у меня на даче, в теплице стоит бочка 200л. В бочку сверху врезан индикатор уровня, на который я давал ссылку. За день вода в бочке прогреваеца и вечером на закате или я или аццкая сотона поливаем лейкой из бочки агурцы. Как только из бочки вытащили первую лейку, сработал индикатор уровня. С этого момента начинается отсчёт 15 минут, это время достаточное, чтобы полить все огурцы, у меня маленькая теплица. Через 15 мин включается клапан и вода наполняет бочку опять пока не сработает индикатор уровня. Алгоритм не поменяется даже когда я сам не буду с лейкой ходить, а врежу насос для поливания.
Упал уровень - подождать 15(30, 45, скокаугодно) минут - наполнить бочку. И мне вовсе не интересно, знать, сколько я леек вытащил, и какой у меня текущий уровень воды, у бочки есть 2 состояния, наполнена и ненаполнена.
Дет, энто фсё очень красиво, агурцы, закат, сотона, 15 минут и тд. Но, дадчик, каторый ты пасаветовал па ссылке - нихрена он не аналоговый, вот в чём беда-то.
Дет, энто фсё очень красиво, агурцы, закат, сотона, 15 минут и тд. Но, дадчик, каторый ты пасаветовал па ссылке - нихрена он не аналоговый, вот в чём беда-то.
Задача у ТС - крайне элементарная. Ума не приложу, в чём он там застрял.
Если бы я хотел собрать всё просто, я бы купил 2 поплавка от сливного бачка и пару концевиков, а тут другие цели.
Дружище, так надо же озвучить эти другие цели! Из стартового поста, прости, я вынес только ту задачу, которую и описал: в нужное время включать или выключать насос. Что надо делать еще-то? Кроме того, если требуется собрать все просто, то есть, еще проще :), то нафига два поплавка-то? В общем, убей меня бог, но пока по скудоумию обычному своему не пойму смысла усложнения системы. Растолкуй.
Где система безопасности? Датчиков много, а о защите ни слова.
Честно даже не думал от чего/кого и что охранять, если подскажете буду признателен.
Если пост не содержит цитирования, значит он относится к предыдущему, что было для Pyotr в данном случае.
А система безопасности в данном разрезе, это не охрана, а дублирование датчиков предельного уровня, как минимум, т.е. тех, что отвечают за перелив и пустой бак. В идеальном случае это совершенно отдельная от основной схема контроля и блокировки.
Совершенно банальный случай, по какой-то причине накрылся датчик верхнего уровня и сх. управления начинает добросовестно из часа в час опустошать колодец или накручивать счетчик расходомера водопровода.
Ну это еще может и ничего, если бак на огороде, а если он на чердаке дома стоит.
Задача у ТС - крайне элементарная. Ума не приложу, в чём он там застрял.
Да в общем то всегда так, что-то простое решить проблема., зато в сложно ищем простое.
Если бы я хотел собрать всё просто, я бы купил 2 поплавка от сливного бачка и пару концевиков, а тут другие цели.
Дружище, так надо же озвучить эти другие цели! Из стартового поста, прости, я вынес только ту задачу, которую и описал: в нужное время включать или выключать насос. Что надо делать еще-то? Кроме того, если требуется собрать все просто, то есть, еще проще :), то нафига два поплавка-то? В общем, убей меня бог, но пока по скудоумию обычному своему не пойму смысла усложнения системы. Растолкуй.
Наверняка проблема не в Вас, а во мне, поскольку объяснил не полностью задачу или не правильно.
В целом цель сделать компактное устройство с LCD на котором будет указан уровень в 2х баках, оно будет управлять подачей воды в первый бак и подкачкой во второй ( водичка с трубы выше чем на 70 см от земли н поднимается - водопровод на дачах), + как приятный бонус будет температура, влажность, время и будут считываться показания электро-счётчика по 232 и отсылаться запросом по смс ( в идеале ).
Водичка нужна в водонапорном бачке чтобы можно было в баньку не носить, а получать по трубе + поставить раковинку чтобы посуду в тазике не мыть.
Также организовать сбор дождевой воды для последующего использования.
Температура, влажность, время - приятные мелочи.
Счётчик ещё под вопросом.
P.S. прилагаю код который чутка доработал и кажется решил первоначальную проблему.
[code] #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 20, 4); // Правила инициализации LCD (править по факту подключённого дисплея). // Создаём объект, для работы с датчиком iarduino_DHT DHT(12); (недопилено) const int sensor_inc_MIN_MAX = A0; //датчик уровня воды 1 (напорный бак) const int sensor_MIN_MAX = A1; //датчик уровня воды 2 (приточный бак) const int pomp = 6; //насос из промежуточного бака в водонапорный const int pomp_on = 7; //состояние контактора насоса const int valve = 8; //клапан притока в промежуточный бак const int button_on = 10; //кнопка ВКЛ насоса const int button_off = 11; //кнопка ВЫКЛ насоса boolean button; //состояние кнопок boolean relay; //состояние контактора насоса boolean water_valve; //состояние электро-задвижки int persent_barrel_1; //уровень в напорном баке int persent_barrel_2; //уровень в приточном баке int tact = 0; //количество выполненых циклов ПО void Button(); //void DHT(); void Pomp(); void Valve(); void Level(); void(* resetFunc) (void) = 0; //объявляем функцию reset с адресом 0 void setup() { pinMode(sensor_inc_MIN_MAX, INPUT); //датчик уровня воды 1 (приточный бак) pinMode(sensor_MIN_MAX, INPUT); //датчик уровня воды 3 (напорный бак) pinMode(pomp, OUTPUT); //упр.реле насоса pinMode(pomp_on, INPUT); //состояние контактора насоса pinMode(valve, OUTPUT); //упр.реле электромагнитного клапана pinMode(button_on, INPUT); //кнопка ВКЛ насоса pinMode(button_off, INPUT); //кнопка ВЫКЛ насоса digitalWrite(pomp, LOW); //упр.реле насоса digitalWrite(pomp_on, LOW); //состояние контактора насоса digitalWrite(valve, LOW); //упр.реле электромагнитного клапана digitalWrite(button_on, LOW); //кнопка ВКЛ насоса digitalWrite(button_off, LOW); //кнопка ВЫКЛ насоса Serial.begin(9600); //------- Инициализация дисплея и статичных надписей -------\\ lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея lcd.setCursor(0, 0); // Устанавливаем курсор в позицию (0 столбец, 0 строка) lcd.clear(); lcd.print("Temp = c"); // "температура=" lcd.setCursor(11, 0); lcd.print(" RH = %"); // "влажность=" lcd.setCursor(0, 2); lcd.print("tank1= %"); // "Бак_1-приточный" lcd.setCursor(0, 3); lcd.print("tank2= %"); // "Бак_2-напорный" lcd.setCursor(11, 3); lcd.print("pomp"); // "насос" lcd.setCursor(11, 2); lcd.print("valve"); // "задвижка" } void loop() { while (true) { Button(); // DHT(); Pomp(); Valve(); Level(); tact++; delay(300); if (tact >= 500000) resetFunc(); //вызываем reset Serial.println(tact); //Serial.println(water_valve); //Serial.println(relay); //Serial.println(button); //Serial.println(volts_1); //Serial.println(volts_2); } } //-------------------------------------работа кнопки------------------------------------------------------- void Button() { if (digitalRead(button_on) == HIGH) //если кнопка нажата { delay(10); button = true; } else if (digitalRead(button_off) == HIGH) { delay(10); button = false; } } //---------------------------------------работа насоса-------------------------------------------------------- void Pomp() { if (button == true || persent_barrel_1 < 60 && persent_barrel_2 > 40) { relay = true; delay(30); digitalWrite(pomp, HIGH); lcd.setCursor(17, 3); lcd.print(" ON"); } else if (button == false || persent_barrel_1 > 90 || persent_barrel_2 < 20 ) { relay = false; digitalWrite(pomp, LOW); lcd.setCursor(17, 3); lcd.print("OFF"); delay(30); } } //---------------------------------------работа электроклапана------------------------------------------------ (надо пилить) void Valve() { if (persent_barrel_2 <= 80) { water_valve = true; delay(10); lcd.setCursor(17, 2); lcd.print(" ON"); digitalWrite(valve, HIGH); } else if (persent_barrel_2 == 90) { water_valve = false; delay(10); lcd.setCursor(17, 2); lcd.print("OFF"); digitalWrite(valve, LOW); } } //---------------------------------------уровни и вывод LCD--------------------------------------------------- void Level() { int rawReading_1 = analogRead(A0); float volts_1 = rawReading_1 / 204.6; if (volts_1 > 0.53 && volts_1 < 0.58) { persent_barrel_1 = 10; } else if (volts_1 > 0.59 && volts_1 < 0.64) { persent_barrel_1 = 20; } else if (volts_1 > 0.65 && volts_1 < 0.73) { persent_barrel_1 = 30; } else if (volts_1 > 0.78 && volts_1 < 0.85) { persent_barrel_1 = 40; } else if (volts_1 > 0.95 && volts_1 < 1.10) { persent_barrel_1 = 50; } else if (volts_1 > 1.20 && volts_1 < 1.27) { persent_barrel_1 = 60; } else if (volts_1 > 1.60 && volts_1 < 1.70) { persent_barrel_1 = 70; } else if (volts_1 > 2.40 && volts_1 < 2.60) { persent_barrel_1 = 80; } else if (volts_1 > 4.40 && volts_1 < 5.30) { persent_barrel_1 = 90; } if (volts_1 < 0.47) { do { lcd.setCursor(6, 3); lcd.print(persent_barrel_2); } while (volts_1 > 0.49); } lcd.setCursor(6, 2); lcd.print(persent_barrel_1); if (persent_barrel_1 < 100) { lcd.setCursor(8, 2); lcd.print(" "); } int rawReading_2 = analogRead(A1); float volts_2 = rawReading_2 / 204.6; if (volts_2 > 0.53 && volts_2 < 0.58) { persent_barrel_2 = 10; } else if (volts_2 > 0.59 && volts_2 < 0.64) { persent_barrel_2 = 20; } else if (volts_2 > 0.65 && volts_2 < 0.73) { persent_barrel_2 = 30; } else if (volts_2 > 0.78 && volts_2 < 0.85) { persent_barrel_2 = 40; } else if (volts_2 > 0.95 && volts_2 < 1.10) { persent_barrel_2 = 50; } else if (volts_2 > 1.20 && volts_2 < 1.27) { persent_barrel_2 = 60; } else if (volts_2 > 1.60 && volts_2 < 1.70) { persent_barrel_2 = 70; } else if (volts_2 > 2.40 && volts_2 < 2.60) { persent_barrel_2 = 80; } else if (volts_2 > 4.40 && volts_2 < 5.30) { persent_barrel_2 = 90; } if (volts_2 < 0.47) { do { lcd.setCursor(6, 3); lcd.print(persent_barrel_2); } while (volts_2 > 0.49); } lcd.setCursor(6, 3); lcd.print(persent_barrel_2); if (persent_barrel_2 < 100) { lcd.setCursor(8, 3); lcd.print(" "); } } //---------------------------------------датчик температуры и влажности--------------------------------------- (недопилено) //void DHT() { //} [/code]Поплавок от унитаза стоит 200р, кстати говоря.
В целом цель сделать компактное устройство с LCD на котором будет указан уровень в 2х баках, оно будет управлять подачей воды в первый бак и подкачкой во второй ( водичка с трубы выше чем на 70 см от земли н поднимается - водопровод на дачах), + как приятный бонус будет температура, влажность, время и будут считываться показания электро-счётчика по 232 и отсылаться запросом по смс ( в идеале ).
Так, стало немного понятнее. Насколько вытекает их этого поста, надо подкачивать воду как в напорный бак, так и в премный. Вывод: нужны два насоса, каждый из которых включается или выключается своей "лягушкой" (извини, я опять стараюсь упростить решение проблемы). Это одна, отдельная, легко решаемая без ардуино задача. Температура, влажность (нафига ???!!!), время, СМС и показания электросчётчика - задача другая, с работой насосов не связанная никак. Здесь ардуина в помощь. Или я опять что-то не понял?
Ну, и уж если хочется запредельного изящества, то датчик относительного давления мрх5010dp может быть применен. Один его патрубок соединен с атмосферой (открыт), другой - с трубкой, опущенной почти до дна бака. Вот тут ардуину и применяем.
Если пост не содержит цитирования, значит он относится к предыдущему, что было для Pyotr в данном случае.
А система безопасности в данном разрезе, это не охрана, а дублирование датчиков предельного уровня, как минимум, т.е. тех, что отвечают за перелив и пустой бак. В идеальном случае это совершенно отдельная от основной схема контроля и блокировки.
Совершенно банальный случай, по какой-то причине накрылся датчик верхнего уровня и сх. управления начинает добросовестно из часа в час опустошать колодец или накручивать счетчик расходомера водопровода.
Ну это еще может и ничего, если бак на огороде, а если он на чердаке дома стоит.
А вот в этом Вы безусловно правы. Необходимо позаботиться об этом. и собрать что то вроде релейной защиты
К примеру: ток на двигатель пускать через концевик перелива бака, чтобы при повышение уровня, цепь разрывалась.
Если есть предложения к конкретно этому проекту, то с удовольствием выслушаю (прочту).
Так, стало немного понятнее. Насколько вытекает их этого поста, надо подкачивать воду как в напорный бак, так и в премный. Вывод: нужны два насоса, каждый из которых включается или выключается своей "лягушкой" (извини, я опять стараюсь упростить решение проблемы). Это одна, отдельная, легко решаемая без ардуино задача. Температура, влажность (нафига ???!!!), время, СМС и показания электросчётчика - задача другая, с работой насосов не связанная никак. Здесь ардуина в помощь. Или я опять что-то не понял?
Температура и влажность - это скажем так удобства, которые можно подоткнуть к ардуино.
Бак приточный наполняется из водопровода ( просто там давление на уровне "как бык поссал" ) или дождевой водой., Бак водонапорный наполняется по-средствам насоса, дабы потом использовать водичку в баньку, поливать, гонять собаку.
Показания счётчика - это тоже удобство + когда тебя нет там, а кто-то нежелательный туда забрёл и включил свет, к примеру, ты видишь что показания пошли в верх ( своеобразная система охраны ).
Просто была плата ардуино уно и немного приблуд к ней. Вот и собираем из того что есть.
А вот в этом Вы безусловно правы. Необходимо позаботиться об этом. и собрать что то вроде релейной защиты
Да, система защиты не помешает. Но, возвращаясь к набившей уже оскомину "лягушке": у меня дренажный насос с ней пашет уже лет 15 или чуть больше без нареканий. 3 раза тьфу!!!! Однако, бак на чердаке, конечно, лучше обезопасить дополнительным контрольным устройством. Желательно, с сигнализацией.
По поводу моего датчика.
1) он самопальный так как запчастей на него ( резисторов и герконов) ну очень в достатке.
2) он позволяет добиться какой-никакой, всё-таки точности измерений.
3) он устойчив ко всяким агрессивным для других датчиков средам ( грязная вода, открытые солнечные лучи, листья и прочий крупный мусор в воде, соседские коты что ссут где попало.)
4) ну ведь очень приятно, согласитесь, когда ты взял и сделал сам, а не купил у пинь хуня со всем известного сайта.
конструкция простая - сборка резисторов и герконов установленная в пластиковую трубу по которой скользит магнит с прилепленным к нему пенопластом.
Прочитал тему , тоже хотел в процентах видеть, но потом подумал, а на кой оно? Ну где реально это потом применить? Разве что приятно что сделал сам, и пристроил герконы и резисторы, которых у меня тоже не мало.
В итоге решил делать как у нас в армии в автоматике было у емкостей с солярой и маслом.
3 Сенсора на которые DetSimen в посте 6 давал ссылку.
Сработал самый верхний сенсор - прекратить налив
Сработал средний сенсор - начать налив, наливать пока не сработает верхний.
Сработал нижний сенсор отправить сообщение о аварии.
Вот и вся логика, на экране тоже отображается три состояния есть вода, идет налив, нет воды авария.
Причем значительно упрощает программирование, запоминать ниче не надо.
Где система безопасности? Датчиков много, а о защите ни слова.
Было у меня такое чувство, что этот камень в мой огород:) Некогда было ответ писать. Думал пронесет, но нет)
Защита у меня "железная". Насос доливает бак со скоростью 1 м3/час. Рядом с баком (он в теплице) приямок. Из него труба 50 в пустой бывший подвал кубов так на 15. В подвале дренажный насос 5м3/час на откачке.
А система безопасности в данном разрезе, это не охрана, а дублирование датчиков предельного уровня, как минимум, т.е. тех, что отвечают за перелив и пустой бак. В идеальном случае это совершенно отдельная от основной схема контроля и блокировки.
Совершенно банальный случай, по какой-то причине накрылся датчик верхнего уровня и сх. управления начинает добросовестно из часа в час опустошать колодец или накручивать счетчик расходомера водопровода.
Ну это еще может и ничего, если бак на огороде, а если он на чердаке дома стоит.
А вот в этом Вы безусловно правы. Необходимо позаботиться об этом. и собрать что то вроде релейной защиты
К примеру: ток на двигатель пускать через концевик перелива бака, чтобы при повышение уровня, цепь разрывалась.
Если есть предложения к конкретно этому проекту, то с удовольствием выслушаю (прочту).
И главное нужно контролировать целостность цепи концевика. А то будете надеяться, что при аварии он замкнется, а провода мыши поели.
Дет, энто фсё очень красиво, агурцы, закат, сотона, 15 минут и тд. Но, дадчик, каторый ты пасаветовал па ссылке - нихрена он не аналоговый, вот в чём беда-то.
NMI, скажи в каком тут месте смияцца нада)
Да ты просто дурдуинщег и нифига ниромантег. ПрикинЪ, закат, агурец, сотона, 15 минут. Вотки тока нихватат, чутка. Атак фсё веривел)))
И главное нужно контролировать целостность цепи концевика. А то будете надеяться, что при аварии он замкнется, а провода мыши поели.
Ну вообще используется реле и концевик (поплавок), который пропускает через свой NС контакт +12v и отдаёт на втягивающую реле., в реле используется NО группа контактов для размыкания цепи питания насоса.
Таким образом когда поплавок поднимается, цепь катушки размыкается и реле рвёт цепь.
я бы датчик уровня топлива от ВАЗ прилепил
я бы датчик уровня топлива от ВАЗ прилепил
А он резистивный?
я бы датчик уровня топлива от ВАЗ прилепил
Да, датчик резистивный, но глубина бочки в среднем 800 мм, и по этому датчик не подходит.
я бы датчик уровня топлива от ВАЗ прилепил
Да, датчик резистивный, но глубина бочки в среднем 800 мм, и по этому датчик не подходит.
Так длину рычага с поплавком можно увеличить в эн раз.
Выставляю на общее обозрение крайнюю версию кода.
После сборки самого устройства воедино представлю принципиальную схему и фото получившихся элементов.(Не скоро)
P.S. Ждём начала дачного сезона.
[code] #include <iarduino_DHT.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 20, 4); // Правила инициализации LCD (править по факту подключённого дисплея). iarduino_DHT dht(12); // Создаём объект, для работы с датчиком iarduino_DHT DHT(12); const int sensor_inc_MIN_MAX = A0; //датчик уровня воды 1 (напорный бак) const int sensor_MIN_MAX = A1; //датчик уровня воды 2 (приточный бак) const int pomp = 6; //насос из промежуточного бака в водонапорный const int pomp_on = 7; //состояние контактора насоса const int valve = 8; //клапан притока в промежуточный бак const int button_on = 10; //кнопка ВКЛ насоса const int button_off = 11; //кнопка ВЫКЛ насоса boolean button; //состояние кнопок boolean relay; //состояние контактора насоса boolean water_valve; //состояние электро-задвижки int persent_barrel_1; //уровень в напорном баке int persent_barrel_2; //уровень в приточном баке int tact = 0; //количество выполненых циклов ПО void Button(); void DHT(); void Pomp(); void Valve(); void Level(); void(* resetFunc) (void) = 0; //объявляем функцию reset с адресом 0 void setup() { pinMode(sensor_inc_MIN_MAX, INPUT); //датчик уровня воды 1 (приточный бак) pinMode(sensor_MIN_MAX, INPUT); //датчик уровня воды 3 (напорный бак) pinMode(pomp, OUTPUT); //упр.реле насоса pinMode(pomp_on, INPUT); //состояние контактора насоса pinMode(valve, OUTPUT); //упр.реле электромагнитного клапана pinMode(button_on, INPUT); //кнопка ВКЛ насоса pinMode(button_off, INPUT); //кнопка ВЫКЛ насоса digitalWrite(pomp, LOW); //упр.реле насоса digitalWrite(pomp_on, LOW); //состояние контактора насоса digitalWrite(valve, LOW); //упр.реле электромагнитного клапана digitalWrite(button_on, LOW); //кнопка ВКЛ насоса digitalWrite(button_off, LOW); //кнопка ВЫКЛ насоса Serial.begin(9600); delay (1000); //------- Инициализация дисплея и статичных надписей -------\\ lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея lcd.setCursor(0, 0); // Устанавливаем курсор в позицию (0 столбец, 0 строка) lcd.clear(); lcd.print("Temp = c"); // "температура=" lcd.setCursor(11, 0); lcd.print(" RH = %"); // "влажность=" lcd.setCursor(0, 2); lcd.print("tank1= %"); // "Бак_1-приточный" lcd.setCursor(0, 3); lcd.print("tank2= %"); // "Бак_2-напорный" lcd.setCursor(11, 3); lcd.print("pomp"); // "насос" lcd.setCursor(11, 2); lcd.print("valve"); // "задвижка" } void loop() { while (true) { Button(); DHT(); Pomp(); Valve(); Level(); tact++; delay(1000); if (tact >= 500000) resetFunc(); //вызываем reset Serial.println(tact); //Serial.println(water_valve); //Serial.println(relay); //Serial.println(button); } } //-------------------------------------работа кнопки------------------------------------------------------- void Button() { if (digitalRead(button_on) == HIGH) //если нажата кнопка ВКЛ меняем переменную { delay(10); button = true; } else if (digitalRead(button_off) == HIGH) //если нажата кнопка ВЫКЛ меняем переменную { delay(10); button = false; } } //---------------------------------------работа насоса-------------------------------------------------------- void Pomp() { if (button == true || persent_barrel_1 < 60 && persent_barrel_2 > 40) // включаем насос по уровню или по кнопке { relay = true; delay(10); digitalWrite(pomp, HIGH); lcd.setCursor(17, 3); lcd.print(" ON"); } else if (button == false || persent_barrel_1 > 90 || persent_barrel_2 < 20 ) // отключаем насос по уровню или по кнопке { relay = false; button == false; digitalWrite(pomp, LOW); lcd.setCursor(17, 3); lcd.print("OFF"); delay(10); } } //---------------------------------------работа электроклапана------------------------------------------------ void Valve() { if (persent_barrel_2 <= 80) // открываем задвижку { water_valve = true; delay(10); lcd.setCursor(17, 2); lcd.print(" ON"); digitalWrite(valve, HIGH); } else if (persent_barrel_2 == 90) // закрываем задвижку { water_valve = false; delay(10); lcd.setCursor(17, 2); lcd.print("OFF"); digitalWrite(valve, LOW); } } //---------------------------------------уровни и вывод LCD--------------------------------------------------- void Level() { //----БАК напорный (1) int rawReading_1 = analogRead(A0); float volts_1 = rawReading_1 / 204.6; Serial.println(volts_1); if (volts_1 > 0.46 && volts_1 < 0.51) { persent_barrel_1 = 10; } else if (volts_1 > 0.53 && volts_1 < 0.57) { persent_barrel_1 = 20; } else if (volts_1 > 0.60 && volts_1 < 0.65) { persent_barrel_1 = 30; } else if (volts_1 > 0.68 && volts_1 < 0.72) { persent_barrel_1 = 40; } else if (volts_1 > 0.80 && volts_1 < 0.85) { persent_barrel_1 = 50; } else if (volts_1 > 0.94 && volts_1 < 1.03) { persent_barrel_1 = 60; } else if (volts_1 > 1.20 && volts_1 < 1.30) { persent_barrel_1 = 70; } else if (volts_1 > 1.60 && volts_1 < 1.70) { persent_barrel_1 = 80; } else if (volts_1 > 2.40 && volts_1 < 2.60) { persent_barrel_1 = 90; } else if (volts_1 > 4.40 && volts_1 < 5.30) { persent_barrel_1 = 100; } if (volts_1 < 0.44) { do { lcd.setCursor(6, 3); lcd.print(persent_barrel_2); } while (volts_1 > 0.49); } lcd.setCursor(6, 2); lcd.print(persent_barrel_1); if (persent_barrel_1 < 100) { lcd.setCursor(8, 2); lcd.print(" "); } //----БАК причтоный (2) int rawReading_2 = analogRead(A1); float volts_2 = rawReading_2 / 204.6; Serial.println(volts_2); if (volts_2 > 0.46 && volts_2 < 0.51) { persent_barrel_2 = 10; } else if (volts_2 > 0.53 && volts_2 < 0.57) { persent_barrel_2 = 20; } else if (volts_2 > 0.60 && volts_2 < 0.65) { persent_barrel_2 = 30; } else if (volts_2 > 0.68 && volts_2 < 0.72) { persent_barrel_2 = 40; } else if (volts_2 > 0.80 && volts_2 < 0.85) { persent_barrel_2 = 50; } else if (volts_2 > 0.94 && volts_2 < 1.03) { persent_barrel_2 = 60; } else if (volts_2 > 1.20 && volts_2 < 1.30) { persent_barrel_2 = 70; } else if (volts_2 > 1.60 && volts_2 < 1.70) { persent_barrel_2 = 80; } else if (volts_2 > 2.40 && volts_2 < 2.60) { persent_barrel_2 = 90; } else if (volts_2 > 4.40 && volts_2 < 5.30) { persent_barrel_2 = 100; } if (volts_2 < 0.44) { do { lcd.setCursor(6, 3); lcd.print(persent_barrel_2); } while (volts_2 > 0.49); } lcd.setCursor(6, 3); lcd.print(persent_barrel_2); if (persent_barrel_2 < 100) { lcd.setCursor(8, 3); lcd.print(" "); } } //---------------------------------------датчик температуры и влажности--------------------------------------- void DHT() { dht.read(); //считываем показания. float H = dht.hum; // показания влажности. float T = dht.tem; // показания температуры. if (tact > 5) { lcd.setCursor(6, 0); lcd.print(H); } else if (tact > 6) { lcd.setCursor(16, 0); lcd.print(T); } } [/code]Хм, ну навскидку: зачем для однобайтных применять инты, зачем в бесконечном цикле еще один, зачем притащили флоаты в уровень?
Хм, ну навскидку: зачем для однобайтных применять инты, зачем в бесконечном цикле еще один, зачем притащили флоаты в уровень?
Ну я же не волшебник, а только лишь начал учиться - иначе тема была бы в "проектах".
int использовал потому что в мозг не пришло ничего иного, по скольку я недавно начал программировать. В цикле циклы - это по точнее если можно?( do...while?), float в цикле Level Вас интересуют?
Пожалуйста уточняйте строки кода или копируйте их в сообщении.
Инты, строки 10-16, у вас количество пинов может превысить 255?
While, который в loop(), loop он и так бесконечный.
Флоаты, да, в уровнях. Чем вас целочисленные с АЦП не устраивают, вы ведь не вольтметр строите, а просто значения сравниваете.
Еще 87 строка, кнопка до секунды может тупить, это много.
И что делает ресет-функция?
Инты, строки 10-16, у вас количество пинов может превысить 255?
While, который в loop(), loop он и так бесконечный.
Флоаты, да, в уровнях. Чем вас целочисленные с АЦП не устраивают, вы ведь не вольтметр строите, а просто значения сравниваете.
Еще 87 строка, кнопка до секунды может тупить, это много.
И что делает ресет-функция?
Исправлюсь, на днях откорректирую код.
Reset - для того чтобы перезагружать контроллер через некоторое количество циклов (думал как защиту от зависания, но видать это не так =) ).
1) Циклы do while здесь тоже бессмысленны (оба). Они у Вас находятся внутри оператора if c полностью противоположным условием. Так что уж если выполнилось условие в if, то условие в while заведомо не выполнится и повторения операторов цикла не будет. А собственно оно зачем? Непонятно, что хотели сделать.
2) В чем магия обильно раскиданных по коду delay(10)?
3) Если Вы намерены периодически перезагружать контроллер, то делать это не глядя на текущее состояние системы как-то не очень хорошо.
Исправлюсь, на днях откорректирую код.
Reset - для того чтобы перезагружать контроллер через некоторое количество циклов (думал как защиту от зависания, но видать это не так =) ).
Вас никто не обвиняет, пишете сами, хорошо. Лучше сразу отрабатывать некий автоматизм, байтовая константа, изменится не может, значит и даем ей - byte. В будущем, когда программы станут сильно развесистыми, это поможет и вы не придете сюда с вопросом, мало памяти, как на 2560 мегу переделать.))))
Для защиты от зависаний в МК есть wdt, здесь на форуме много тем было. Поищите.
по ифам лучше делать спуск от большего к меньшему, тогда там будет типа такого
while(1){
если х> 950 {тогда у= ...;
break;}если х> 900 {тогда у= ...:
break;}остальные сравнения
break;}while(1) -break;можно использовать переход на метку, goto m1;1) Циклы do while здесь тоже бессмысленны (оба). Они у Вас находятся внутри оператора if c полностью противоположным условием. Так что уж если выполнилось условие в if, то условие в while заведомо не выполнится и повторения операторов цикла не будет. А собственно оно зачем? Непонятно, что хотели сделать.
2) В чем магия обильно раскиданных по коду delay(10)?
3) Если Вы намерены периодически перезагружать контроллер, то делать это не глядя на текущее состояние системы как-то не очень хорошо.
1) Необходимо для того чтобы отсекать промежуточные значения (пока поплавок движется по датчику и не замкнут ни один геркон) прочтите в чём суть темы.
2) Ужасная привычка от которой оказалось сложно избавиться.
3) Согласен, необходимо допилить.
1) Необходимо для того чтобы отсекать промежуточные значения (пока поплавок движется по датчику и не замкнут ни один геркон) прочтите в чём суть темы.
А если какой затык и датчик завис между герконами? Здесь, имхо, правильнее будет сделать временную зависимость.
Получили сигнал необходимости доливки, включили исполнение, засекли время, если n-секунд/минут не достигнут следующий уровень, все вырубаем и начинаем орать благим матом, хозяина звать. Еще одна доп.защита получается. Опять таки ИМХО.
1) Необходимо для того чтобы отсекать промежуточные значения (пока поплавок движется по датчику и не замкнут ни один геркон) прочтите в чём суть темы.
А если какой затык и датчик завис между герконами? Здесь, имхо, правильнее будет сделать временную зависимость.
Получили сигнал необходимости доливки, включили исполнение, засекли время, если n-секунд/минут не достигнут следующий уровень, все вырубаем и начинаем орать благим матом, хозяина звать. Еще одна доп.защита получается. Опять таки ИМХО.
В огородном водопроводе может не оказаться воды или напор будет малый или наоборот большой ( всегда не предсказуемо) потому и я выполнил это таким образом + бак наполняется не только водой с водопровода но и дождевой.
По позже предоставлю план-схему как вобще всё устроено.
А если какой затык и датчик завис между герконами? Здесь, имхо, правильнее будет сделать временную зависимость.