Задержка включения и выключения вентиляции в санузле
- Войдите на сайт для отправки комментариев
Доброго времени суток, уважаемые форумчане! Как новичок, прошу помощи у гуру в моем первом проекте. Хочу сделать таймер (на базе ардуино) задержки включения и выключения вентилятора в санузле.
Имеем: 1)Ардуино; 2)фоторезистор 3) резистор 10кОм; 4) релейный модуль
Алгоритм следующий: 1) Включаем свет; 2) вентилятор не включается 2мин.; 3)если свет горит более 2 мин., то включается вентилятор и работает пока горит свет и после отключения света продолжает работать еще 5 мин.; 4) если свет горит менее 2 мин., то вентилятор не включается.
Написал скетч (для отладки время принял 10 и 15сек.) :
[code]
}
void loop()
{
digitalWrite(Rele, HIGH);
if (analogRead(ldr) < 800) //если свет включен
{
goto A; //то идем на А
}
else goto B; //иначе идем на В
A: delay(10000); // выдерживаем паузу
if (analogRead(ldr) < 800) //после паузы проверяем включен ли свет
{
while (analogRead(ldr) < 800) //если включен свет, то пока свет горит
digitalWrite(Rele, LOW); //реле включено
}
else goto B; //иначе идем на В
delay(15000); //после выключения света выдерживаем паузу и выключаем реле
B: digitalWrite(Rele, HIGH); //реле выключено
}
[/code]
В итоге имеем: при включении ардуино срабатывает реле и через 10сек выключается, при засвете фоторезистора в течение 15сек - реле включается и выключается по истечении 10сек. При засвете фоторезистора в течение 1сек - реле также включается и выключается по истечении 10сек. Короче все получается наоборот. Не могу понять где косяк. Помогите плиз!
Вы уверены, что у Вас реле включается по LOW, а не по HIGH? Схему покажите.
Вы уверены, что у Вас реле включается по LOW, а не по HIGH? Схему покажите.
+++
void loop() { digitalWrite(Rele, HIGH); if (analogRead(ldr) < 800) //если свет включен { goto A; //то идем на А } else { goto B; //иначе идем на В } A: delay(10000); // выдерживаем паузу if (analogRead(ldr) < 800) //после паузы проверяем включен ли свет { while (analogRead(ldr) < 800) //если включен свет, то пока свет горит { digitalWrite(Rele, LOW); //реле включено } } else { goto B; //иначе идем на В } delay(15000); //после выключения света выдерживаем паузу и выключаем реле B: digitalWrite(Rele, HIGH); //реле выключено }Специально раскидал код - тут гдето есть включение?
Только выключение каждые перу миллисекунд и перепроверка...
int Rele = 13; int ldr = A0; void setup() { pinMode(Rele, OUTPUT); digitalWrite(Rele, HIGH); } void loop() { if (analogRead(ldr) < 800) //если свет включен { digitalWrite(Rele, LOW); //реле включено delay(10000); // выдерживаем паузу } else { digitalWrite(Rele, HIGH); //реле выключено delay(10000); // выдерживаем паузу } }Помоему так лучше и проще....
Строка 20 -включение реле
Сейчас попробую
Строка 20 -включение реле
а смысл постоянно выключать?? в его коде на 6 строке!
Ответа на вопрос нет. Я не знаю, что у Вас там за модуль, а схему Вы не дали.
Просто проверьте как у Вас включается реле. ЧТо нужно на него подать, чтобы оно включилось HIGH или LOW. Понимаете как это проверить?
Ответа на вопрос нет. Я не знаю, что у Вас там за модуль, а схему Вы не дали.
Просто проверьте как у Вас включается реле. ЧТо нужно на него подать, чтобы оно включилось HIGH или LOW. Понимаете как это проверить?
[code] int Rele = 13; void setup() { pinMode(Rele, OUTPUT); digitalWrite(Rele, HIGH); } void loop() { digitalWrite(Rele, LOW); //реле включено } [/code]Так?
p.masyukov, Попробовал Ваш код. Все равно какая-то ерунда получается. Вначале вроде нормально было, а потом то через 3сек включится, то через 6сек выключится
p.masyukov, Попробовал Ваш код. Все равно какая-то ерунда получается. Вначале вроде нормально было, а потом то через 3сек включится, то через 6сек выключится
не. по коду всё там правильно.
он не делает всё то что ждете от него... он для проверки реле!!!!
а если вам надо тот алгоритм что описан --- то Вам его тут никто не напишет (он конечно не сложный, так мелочи) - вам в рездел ищу исполнителя!!!
один из них я..
Исправил код
[code] #define Rele 13 //переменная с номером пина реле #define ldr 0 //и фоторезистора void setup() { pinMode(Rele, OUTPUT); //указываем, что реле - выход pinMode(ldr, INPUT); //указываем, что фоторезистор - вход } void loop() { digitalWrite(Rele, LOW); if (analogRead(ldr) > 800) //если свет включен { goto A; //то идем на А } else goto B; //иначе идем на В A: delay(10000); // выдерживаем паузу if (analogRead(ldr) > 800) //после паузы проверяем включен ли свет { while (analogRead(ldr) > 800) //если включен свет, то пока свет горит digitalWrite(Rele, HIGH); //реле включено } else goto B; //иначе идем на В delay(15000); //после выключения света выдерживаем паузу и выключаем реле B: digitalWrite(Rele, LOW); //реле выключено } [/code]1) Да, действительно релейный модуль включается у меня по HIGH;
2)В строках, где analogRead(ldr)<800 был неправильный знак - исправил на analogRead(ldr)>800
Проверил - вроде работает! Спасибо всем за помощь!
Подскажите еще, если нетрудно, как это можно реализовать без delay. Хочу поставить еще одно реле и фоторезистор, чтобы туалет и ванна включались независимо друг от друга.
https://www.youtube.com/watch?v=bO_jN0Lpz3Q&index=1&list=PLfDmj22jP9S759...
http://arduino.ru/forum/programmirovanie/otkaz-ot-delay
http://robocraft.ru/blog/arduino/614.html
Спасибо, Павел за ссылки! А по поводу...
а если вам надо тот алгоритм что описан --- то Вам его тут никто не напишет (он конечно не сложный, так мелочи) - вам в рездел ищу исполнителя!!!
один из них я..
все таки хочется сделать своими руками - это интересней, чем просто заплатить деньги и получить готовый прибор. С таким же успехом можно было бы купить в магазине реле времени. Я обратился к Вам не с целью написать мне готовый код, а с просьбой помочь разобраться, все таки хочется самому научиться программировать. Еще раз Спасибо.
Павел, от меня тоже спасибо за участие в теме и разъяснения. Поскольку я еще более "начинающий, чем Tayfun, то задам Вам вопрос от себя - если можете, то посоветуйте, как скорректировать код, чтобы ограничить максимальное время работы вентилятора заданным временем, например 20 минут. Просто иногда забывают выключить свет в туалете :).
Спасибо.
...скорректировать код, чтобы ограничить максимальное время работы вентилятора заданным временем, например 20 минут. Просто иногда забывают выключить свет в туалете :).
Это - не решение проблемы. Решение - автоматически выключать свет.
Соглашусь, но при условии, что будет абсолютная уверенность, что свет именно забыли выключить. Допускаю такое решение, но если задержка выключения будет увеличена до, допустим, 1-2х часов, а если понадобится восстановить после отключения свет - то можно и перещелкнуть клавишей включения света. В моем случае такое решение не подходит, т.к. оно трудно реализуемо: надо прокладывать провода к светильнику, что испортит интерьер, да и по технике безопасности не айс. Опять же надо будет встраивать куда-то симистор или реле с проводами управления и т.д. и т.п. Хлопотно это. Ремонт из-за этого точно делать не буду. Можно и задержкой на отключение ограничиться.
Вообще то это все можно реализовать .... через автоматы Пуха.
Эта версия просто по свету вкл /выкл вентилятор
/**/ const byte FotoPin =/*пин*/A0; const byte FunPin =/*пин*/2; enum state_t {FunOFF = 0, FunON} state; void stand(state_t s) { state = s; switch (state) { case FunOFF: digitalWrite(FunPin, HIGH); //вентилятор выключен break; case FunON: digitalWrite(FunPin, LOW); //вентилятор включен break; } } //--------------------------- void setup() { pinMode(FunPin, OUTPUT); stand(FunOFF); } void loop() { int foto = analogRead(FotoPin); switch (state) { case FunOFF: /*если свет включен то включить вентилятор */ if (foto < 800) stand(FunON); break; case FunON: /*если свет выключен то выключить вентилятор */ if (foto > 800) stand(FunOFF); break; } }А вот это включает с задержкой как у ТС
/**/ const byte FotoPin =/*пин*/A0; const byte FunPin =/*пин*/2; enum state_t {FunOFF = 0, FunON} state; unsigned long past; const unsigned long time10s = 10000; const unsigned long time15s = 15000; void stand(state_t s) { state = s; switch (state) { case FunOFF: digitalWrite(FunPin, HIGH); //вентилятор выключен break; case FunON: digitalWrite(FunPin, LOW); //вентилятор включен break; } } //--------------------------- void setup() { pinMode(FunPin, OUTPUT); stand(FunOFF); } void loop() { unsigned long mill = millis(); int foto = analogRead(FotoPin); switch (state) { case FunOFF: if (foto > 800) past = mill; /*если свет включен то включить вентилятор */ else if (mill - past >= time10s) stand(FunON); break; case FunON: if (foto < 800) past = mill; /*если свет выключен долго то выключить вентилятор */ if (mill - past >= time15s) stand(FunOFF); break; } }ПС: Плохая новость в том что код не проверял
ПС: Плохая новость в том что код не проверял
Все равно спасибо. Завтра сам попробую проверить. Будет над чем подумать - я же новичек в программировании.
Пока с кнопками придется пробовать, т.к фотодатчики еще не купил. Кстати! Их 2 типа на Али есть - с фотодиодом и фотрорезистором.
Насколько понял, с фотодиодом дискретный датчик, а с фоторезистором - аналоговый. Кто-нибудь подскажет: это так или нет?
Это не так: возможны все 4 варианта сочетания типа датчика и типа выходного сигнала.
Соглашусь, но при условии, что будет абсолютная уверенность, что свет именно забыли выключить.
квадратные датчики китайские - зачастую имеют ждампер режима. В одном варианте оно отрабатывает выставленную чувствительность и длительность и гаснет, потом опять ждет появление движения. А в другом режиме оно постоянно следит за движением и если во время срабатывания движение замечено - оно продлевает счетчик времени.
Другими словами - поставив джампер в соответствующее положение, нужно просто периодически пошевеливаться и свет внезапно не поганснет, пока ты на горшке.
Касательно включения в случае автоматического выключения - так есть же давно выдуманный "проходной выключатель", если сильно нужно! Не подскажу как его задействовать именно в твоей конфигурации, но мож кому-то и поможет!
Я имел ввиду свойства датчика, а не платы Ардуино.
Поискал инструкции и нашел вот что:
- для датчика на фоторезисторе -
Компаратор чип LM393, он устойчив.
Может распознавать яркость и интенсивность света
Точность регулируемый
Рабочее напряжение 3,3 В-5 В
Выход: делаем цифровой коммутатор выход s (0 и 1) АО аналоговый выход напряжения
- для датчика на фотодиоде -
1. Яркость окружающей среды и интенсивность света могут быть обнаружены (сравните с фоторезистором, направленность относительно хорошая, может воспринимать фиксированное направление источника света)
2. Регулировка чувствительности синего цифрового потенциометра (рисунок)
3. Рабочее напряжение 3,3 В-5 В
4. Цифровые импульсные выходы (0 и 1)
Делаю вывод: фоторезисторный датчик - аналоговый, а фотодиодный - дискретный с регулировкой чувствительности
Исправил код
1) Да, действительно релейный модуль включается у меня по HIGH;
программа будет смотреться яснее, если прописать в начале
// исправлены ошибки 11:21.
ПС: Плохая новость в том что код не проверял
Проверил код. Компилятор выругался. Попробовал разобраться, но пока не получилось. Ругаться начинат уже с 8 строки. (имею ввиду вторую версию программы). Пишет error: 'state_t' was not declared in this scope и далее в таком же духе.
/**/ const byte FotoPin =/*пин*/A0; const byte FunPin =/*пин*/2; enum state_t {FunOFF = 0, FunON} state; unsigned long past; const unsigned long time10s = 10000; const unsigned long time15s = 15000; void stand(state_t s) { state = s; switch (state) { case FunOFF: digitalWrite(FunPin, HIGH); //вентилятор выключен break; case FunON: digitalWrite(FunPin, LOW); //вентилятор включен break; } } //--------------------------- void setup() { pinMode(FunPin, OUTPUT); stand(FunOFF); } void loop() { unsigned long mill = millis(); int foto = analogRead(FotoPin); switch (state) { case FunOFF: if (foto > 800) past = mill; /*если свет включен то включить вентилятор */ else if (mill - past >= time10s) stand(FunON); break; case FunON: if (foto < 800) past = mill; /*если свет выключен долго то выключить вентилятор */ if (mill - past >= time15s) stand(FunOFF); break; } } /*Скетч использует 964 байт (3%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 15 байт (0%) динамической памяти, оставляя 2033 байт для локальных переменных. Максимум: 2048 байт. */То у меня это компилируется. А если у вас не поддерживаются enum, то это же не моя вина.
http://cppstudio.com/post/8106/
Извините, если что не так! К сожалению, я пока на уровне чайника в С++. Прежде чем написать про ошибку, я про enum почитал, пока код разбирал. Кстати, разобрался почти во всем, и не мог понять, в чем дело. Спасибо, это хороший пример решения задачи. У меня были совсем другие варианты в планах. Ваше решение мне показалось элегантней. А что надо сделать, чтобы компилятор enum понимал? Может апгрейд какой-то сделать? - У меня стандартная Ардуиновская программа версии 1.8.7
Посто заменить переменной. Хватит bool или byte . Ну в общем так.
/**/ const byte FotoPin =/*пин*/A0; const byte FunPin =/*пин*/2; /*состояние 0 -вык 1 вкл*/ bool state; unsigned long past; const unsigned long time10s = 10000; const unsigned long time15s = 15000; void stand(bool s) { state = s; switch (state) { case 0: digitalWrite(FunPin, HIGH); //вентилятор выключен break; case 1: digitalWrite(FunPin, LOW); //вентилятор включен break; } } //--------------------------- void setup() { pinMode(FunPin, OUTPUT); stand(0); } void loop() { unsigned long mill = millis(); int foto = analogRead(FotoPin); switch (state) { case 0: if (foto > 800) past = mill; /*если свет включен то включить вентилятор */ else if (mill - past >= time10s) stand(1); break; case 1: if (foto < 800) past = mill; /*если свет выключен долго то выключить вентилятор */ if (mill - past >= time15s) stand(0); break; } } /*Скетч использует 934 байт (3%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 14 байт (0%) динамической памяти, оставляя 2034 байт для локальных переменных. Максимум: 2048 байт. */И зря вы просите помощи, лучше сами. Так вы карму себе портите, пути к развитию отрезаете.
Да, да, конечно. Спасибо за мнение.
То у меня это компилируется. А если у вас не поддерживаются enum, то это же не моя вина.
http://cppstudio.com/post/8106/
Разобрался с компилятором, enum не причем. Все заработало. Спасибо за рабочие примеры.
Доброго времени суток всем! Наконец приехало из Китая UNO ии расставило все по местам! :) До этого насочинял разных версий программ управления вентилятором, втом числе и предпринял попытку модернизации чужих. Не работает... То есть работает, но не совсем так, как хотел бы. Столкнулся с пока необъяснимой для меня реакцией Ардуино - в ряде случаев плата игнорирует некоторые куски программы. Думал сначала, что до этих строчек просто дело не доходит, но потом все же постал, что это не так. Почему, однако, они игнорируются так и не понял. Привожу упрощенный пример пример программы от qwone, которую я слегка переделал в процессе запуска на Ардуино, когда столкнулся с проблемами. Доработать я ее сначала хотел под свои требования, но остановился, поскольку столкнулся необъснимым отсутствием реакции устройства. Вот код:
/**/ const byte FotoPin =/*пин*/A0; const byte FunPin =/*пин*/2; /*состояние 0 -вык 1 вкл*/ byte state; unsigned long past; unsigned long maxtime; const unsigned long time10s = 2000; const unsigned long time15s = 3500; const unsigned maxtime20s = 5000; void stand(byte s) { state = s; switch (state) { case 0: digitalWrite(FunPin, LOW); //вентилятор выключен break; case 1: digitalWrite(FunPin, HIGH); //вентилятор включен break; } } //--------------------------- void setup() { pinMode(FunPin, OUTPUT); stand(0); maxtime = 0; } void loop() { unsigned long mill = millis(); int foto = analogRead(FotoPin); switch (state) { case 0: if (foto > 800) stand(1); break; case 1: if (foto > 800 && maxtime == 0) maxtime = mill; else if (foto > 800 && mill - maxtime >= maxtime20s) {stand (0); maxtime=0;} if (foto < 800) {stand(0); maxtime=0;} break; } }Код компилируется, но не работает 3-я снизу строка:
else if (foto > 800 && mill - maxtime >= maxtime20s) {stand (0); maxtime=0;}Может быть кто-то подскажет, в чем причина?
Добавлю, что убрал из первоначального кода задержки, чтобы решить проблему, а хвосты зачищать не стал, т.к. они потом пригодятся.
800+... значит уровень на выходе весьма высокий... тогда может быть вместо аналога использовать цифру?
Между строками №№ 34 и 35 поставьте вывод переменной foto в монитор порта. Посмотрите чему она равна и тогда будете рассуждать ужес открытыми глазами.
И ещё (это не причина проблемы, но всё-таки) в выражении "mill - maxtime >= maxtime20s" у Вас собрано ТРИ разных типа данных в одном выражении. наверняка компилятор предупреждает Вас об этом (если предупреждения не выключены). Старайтесь такого избегать.Уж по крайней мере, не смешивайте знаковые и беззнаковые значения.
Как оно может компилироваться при
constunsigned maxtime20s = 5000;?sadman41, а что не так с этой строкой? Я что-то ... можустал к вечеру.
Как оно может компилироваться при
constunsigned maxtime20s = 5000;?const unsigned long maxtime20s=5000;
Но для простоты понимания лучше воспользоваться автоматом с четырьмя состояниями
sadman41, а что не так с этой строкой? Я что-то ... можустал к вечеру.
Непонятно к какому типу unsigned пристегивается. Или сообщение с кодом подправили враги...
sadman41, а что не так с этой строкой? Я что-то ... можустал к вечеру.
Непонятно к какому типу unsigned пристегивается. Или сообщение с кодом подправили враги...
Между строками №№ 34 и 35 поставьте вывод переменной foto в монитор порта. Посмотрите чему она равна и тогда будете рассуждать ужес открытыми глазами.
Спасибо, попробую.
800+... значит уровень на выходе весьма высокий... тогда может быть вместо аналога использовать цифру?
На самом деле в данной ситуации это не принципиально - пока я использую простой переключатель. Может это не очень правильно, но когда надоело с фоторезистором возиться, я просто его на микротумблер заменил.
Непонятно к какому типу unsigned пристегивается. Или сообщение с кодом подправили враги...
Да, Господь с Вами,это Вы чего-то подзабыли, освежите. Голый unsigned вполне допустим и означает беззнаковый int, чего уж тут непонятного.
Тут Вы правы - даже и не помню, когда осмысленно использовал unsigned без типа. Да и с типом тоже - все intX_t/uintX_t пользую.
Но для простоты понимания лучше воспользоваться автоматом с четырьмя состояниями
Хотел сделать так, но не получилось... А получилось, но подругому.
Но для простоты понимания лучше воспользоваться автоматом с четырьмя состояниями
Добрый вечер! Путем неимоверных усилий наконец-то удалось достичь того, чего хотелось! :)))
(вечера, к сожалению, зимой короткие, да и на работе поздно задерживаться приходится. Но это лирика.
Напомню, что хотел сделать: 1)включаем свет, 2)с задержкой включается вентилятор, 3)горит свет некое время - вентилятор работает, 4)выключаем свет, 5)вентилятор выключается с заданной задержкой, 6)если забыли выключить свет - вентилятор выключается через некое заданное максимальное время, например 20-30мин. Выключение вентилятора можно совместить с принудительным выключением света.
Все началось с примеров нескольких кодов, которые любезно предложил qwone, за что спасибо. Сначала я хотел их просто доработать, но у меня что-то это не получилось. В результате переработки одного из кодов и получился гибрид - финальный вариант.
/**/ const byte FotoPin =/*пин*/A0; const byte FunPin =/*пин*/2; enum state_t {FunOFF = 0, FunON} state; //статус управления вкл/выкл unsigned long past; //время таймера включения unsigned long past1; //время таймера выключения byte flag; //логический флаг состояния включения света const unsigned long time10s = 1000; //уставка задержки включения const unsigned long time15s = 1500; //уставка задержки выключения const unsigned long time20s = 6000; //уставка максимально допустимого времени работы void stand(state_t s) { state = s; switch (state) { case FunON: digitalWrite(FunPin, HIGH); //вентилятор включен break; case FunOFF: digitalWrite(FunPin, LOW); //вентилятор выключен break; } } //_______________________________ void setup() { pinMode(FunPin, OUTPUT); stand(FunOFF); //начальное условие - вентилятор выключен past=0; } void loop() { unsigned long mill = millis(); //запускаем таймер int foto = analogRead(FotoPin); { if (foto > 800 && past == 0) past = mill; //начало работы таймера включения с "нуля", если включили свет. if (foto <= 800 && past1 == 0) past1 = mill; //вводим второй таймер и определяем условие его запуска, если выключен свет if (foto > 800 && mill - past == time10s) {stand(FunON); past1=0;} //условия задержки включения вент. после включения света if (foto<= 800 && mill - past1 == time15s) {stand(FunOFF); past = 0;} //условия задержки выключения вент. после выключения света if (foto > 800 && mill - past >= time20s) {stand(FunOFF); flag = 1;} //условие отключения вентилятора при включенном свете и флаг состояния включения света if (foto<= 800 && flag == 1) {past=0; flag = 0;} //подготовка к новому циклу работы после отключения света - начальные установки параметров flag и past } }Код работает исправно (по крайней мере на макетке). Нужно промышленное тестирование :))) И спасибо Всем за участие и посильную помощь.
А что касается автомата с четырьмя состояниями - хотел, потратил много времени, но не получилось...- не хватило опыта. Пришлось изменить тактику.