7-и зонное освещение:вкл\выкл с разных выключателей
- Войдите на сайт для отправки комментариев
MK UNO плюс 7 зон освещения от 7 кнопок с вариативным управлением по количеству нажатий.
Здравствуйте, уважаемые! В процессе осмысления схема управления 7 группами нагрузки, подключеные через оптосимисторы. Вопрос- как описать в скетче логику для управления одной кнопкой разными зонами освещения? Описание: LED1 - лампа над лестницей с выключателем S1, LED2;LED5/S2;S3 - верхний свет, LED3;LED4/S3;S4 настенные светильники, LED6/S6 -туалет, LED7/S7 - мастерская. Связь элементов схемы через витую пару, расстояние не более 8 метров на ветвь. Предполагается, что по кнопке S1 должны управляться LED1;2;5;7 и общее выключение, S2;S3 совместно управляют LED2;LED3, S4;S5 для LED4;LED5, S6 индивидуально для LED6, S7 для LED7;LED1;LED2;LED5.
П.С. Это моя первая схема, идеально совпавшая во времени с осенним обострением и ожидаемым периодом долгих зимних вечеров) - почему бы и нет? в дальнейшем есть идеи по расширению функционала- подключение часов для привязки интенсивности освещения от времени суток, имитация присутствия, датчики движения и охранные функции, обесточивание по срабатыванию датчиков, управление климатом и вентиляцией.
Вот я смотрю на схему и понимаю, что ТС "нулевой". Видно к обострению.
Вопрос- как описать в скетче логику для управления одной кнопкой разными зонами освещения?
Сначала нужно описать её словами так, чтобы, кроме Вас, ещё кто-то понял. Пока Вы этого не сделаете, к скетчу даже не прикасайтесь.
Опишите словами логику работы Ваших кнопок.
Если вместо выключателей использовать кнопку, то все упрощается:
Логика для кнопки S1- по первому нажатию включает LED1, при повторном нажатии до истечения одной секунды дополнительно включает LED2;LED5;LED7. По истечению первой секунды от первого нажатия S1 выключает включенные ею нагрузки, при повторном нажатии отключает все освещение LED1-7. ( клик S1 включает LED1, контроллер ожидает повторное нажатие до 1сек для включения дополнительных трех зон; переход в ожидание следущего нажатия кнопки уже для отключения с выдержкой интервала в 1сек.для возможного второго нажатия; переход в начало цикла.) Похожая логика будет и для остальных кнопок, кроме S6/LED6 но с разными зонами освещения
Спасибо за ответы, я буду рад любой помощи, т.к.действительно, мой уровень в использовании контроллеров нулевой.
Значит так,
1 первое нажатие - включение Led1
2 следующее, если в пределах 1 сек - включение LED2;LED5;LED7
3. если поступит ещё одно в течение той же секунды, то ХЗ
4. после секунды, по нажатию выключаем, всё, что включали
5. по следующему нажатию. выключаем всё вообще
6. если будет ещё нажатие, то ХЗ
Я всё правильно понял?
А теперь приведите в божеский вид, чтобы никаких ХЗ не было.
Кстати, надеюсь, Вы повесите инструкцию для пользователя возле каждой кнопки? Ну или поставите бутылку, т.к. без бутылки в этом точно никто не разберётся :)
Пункты 3 и 6 - игнорирование, как мне кажется т.е. максимум на включение 1 или 2 нажатия, на выключение 1 или 2 нажатия. Таким образом любое второе нажатие заканчивает период вкл/выкл.
Инструкцию не повешу, так как пользоваться будем мы с женой, и все логично - у любой кнопки первое нажатие включает лампочку над этой кнопкой, второе нажатие расширяет освещаемую зону дальше, либо выключает лампочку сверху или включенное вокруг и только одна кнопка на лестнице гасит все освещение на мансардном этаже. Этот этаж выполнен без разделения на комнаты, по типу студии, поэтому разветвленное освещение
Вы это, голову-то включайте. Вам же сказали, подумать надо, а не ляпать что придётся. Если игнорировать п.6, то один раз включив и выключив, Вы больше уже не сможете ничего включить. Как Вы включите, если все нажатия после выключения игнорируются?
По-поводу логичности, позволю себе усомниться. Вот горит у мне одна дампа LED1, я решил, что она мешает спать ребёнку и её надо выключить. Но, прежде, чем я смогу её выключить, я должен включить ещё три лампы в дополнение к уже горящей - очень логично.
Евгений, сейчас подробнее подумаю
Дано: кнопка без фиксации S1, нагрузка в виде ламп LED1 и LED2.
1.1. Период1 "ВКЛ" - ожидание до действия на S1 "нажатие1"(первое)
1.1.2. действие"нажатие1" вызывает включение LED1-->запуск "таймер 1секунда"
1.1.3. Окончание отсчета "таймер 1секунда" приводит к переводу работы программы в период2 "ВЫКЛ".
1.2.1 действие "нажатие2"(второе), выполнимо, если "таймер 1секунда от нажатия1" еще не вызвал переход в период2"ВЫКЛ", вызывает включение LED2-->отмену отсчета "таймер 1секунда"-->переход в период2 "ВЫКЛ".
2.1. Период2 "ВЫКЛ" -ожидание до действия на S1 "нажатие1"
2.1.2. действие"нажатие1" вызывает выключение LED1-->запуск "таймер 1секунда"
2.1.3. Окончание отсчета "таймер 1секунда" приводит к переводу работы программы в период1 "ВКЛ".
2.2.1 действие "нажатие2"(второе), выполнимо, если "таймер 1секунда от нажатия1" еще не вызвал переход в период1"ВКЛ", вызывает выключение LED2-->отмену отсчета "таймер 1секунда"-->переход в период1 "ВКЛ".
Я смотрю у вас методы оказания помощи как в армии - ткнуть носом и по возможности добавить пинок), хорошо, я освоюсь, куда дальше смотреть, если логику я описал, надеюсь?
Ну, осталось ровно два шага – выписать автомат и чисто механически написать программу или даже взять готовую программу, реализующую автоматы. В последнем случае достаточно будет подсунуть её свой автомат. Например, для автомата Мили таких программ полно готовых.
Знаете что такое автомат Мили? И как он строится? А то, если знаете, то чего мне пальцы бить-то. Не знаете расскажу.
Про автомат Мили погуглил, суть понятна только в общих чертах, вроде это алгоритм позволяющий проделать всю работу по шагам. Если будет возможность опишите применение автомата Мили на примере моего будущего скетча, это облегчит мне задачу) Пока курю форум, там есть отличный пост про "титановый велосипед для тактовой кнопки"
там есть отличный пост про "титановый велосипед для тактовой кнопки"
Велосипед Вам не пригодится, он плохо ложится на автоматный поход.
Автомат строится очень просто.
Сначала выписываются все возможные состояния в которых он может находится. В Вашем случае они примерно таковы (проверяйте. может я чего пропустил).
1. Ожидаем нажатия кнопки включения
2. Ожидаем второго нажатия кнопки включения
3. Ожидаем кнопки выключения
4. Ожидаем второго нажатия кнопки выключения
Вроде всё.
Дальше назначаем начальное состояние - у нас это состояние №1
теперь выписываются все возможные сигналы (воздействия). У нас они вроде такие
1. Нажата кнопка
2. Истёк таймаут
Вроде, других нет.
Теперь строится матрица (таблица переходов и выходов). Какжда строка соответсвует состоянию, каждый столбец воздействию. В клетках на пересечении состояния и воздействия пишутся ровно две вещи А) что сделать и Б) в какое состояние перейти. И интепретируется это так: если автомат находится в данном состоянии и поступило данное воздействие, то сделать (А) и перейти в состояние (Б). Примерно так:
(начальное состояние)
Б) №2
Б) №3
Б) №3
Б) №4
Б) №1
Б) №1
Посмотрите на таблицу внимательно, поводите по ней пальцем, представьте как всё срабатывает. Вроде, я старался написать также, как в Вашем текстовом пояснении, но может и ошибся. О может и не ошибся. но Вы сейчас передумаете. В общем, Вам нужна законченная и вылизанная такая таблица.
Это и есть таблица переходов и выходов. Она полностью задаёт автомат. Всё с нею понятно?
Программирование такой таблицы дело чисто техническое. Более того, программы получаются всегда одинаковые, потому есть куча готовых, в них только таблицу подставить. Но если Вы этого никогда не делали. то лучше сделайте "ручками".
Знаете как делать? Я больше не нужен?
Евгений, конечно не знаю как делать- темный лес, я еще почитаю и поизучаю. В таблице все правильно, если только в коде программы не забыть про запуск-останов таймера. Как только смогу- задам следущий вопрос по существу.
Запуск - останов таймера забыть никак нельзя - у автомата есть событие "истёк таймаут", его никак не сделаешь забыв про таймер.
А если Вы подумали, что его надо как-то специально останвливать, таки нет. В том-то и прелесть автомата. Посмотрите в таблицу, прямо пальцем водите.
Если автомат в состоянии 1 то ему плевать срабатывает там таймер или нет, он на это просто не смотрит.
Если автомат в состоянии 2 и сработал таймер, он 9автомат тут же перешёл в состояние 3, в еотором ему опять же плавать на таймер.
Смотрите - автомат - очень простая и мощная вещь.
Если хотите. мы это дожмём до конца.
Да, спасибо большое, Евгений, и, конечно, лучше учиться под руководством) Не смог обнаружить на форуме личные сообщения, хотел предложить вознаграждение)
Да, не надо вознограждений - это больно дорого выйдет.
А по теме, пожалуй Вы правы - для "чистоты" давайте добавим завод таймера в действия. некрасиво делать что-то, чего нет в таблице. Несистемно. Итак таблица с заводом таймера выглядит так
&
(начальное состояние)
завести таймер на 1 сек
Б) №2
Б) №3
Б) №3
завести таймер на 1 сек
Б) №4
Б) №1
Б) №1
А теперь, "следите за руками. То, что я сейчас буду писать - касасается любого автомата. Они все одинаковые и различаются только таблицей. Когда таблица готова, далее всё всегда одинаково и одна программа не отличается от другой.
Итак, у Вас есть два события: "нажата кнопка" и "истёк таймер".
Значит, прежде чем писать программу, Вам надо написать две функции, которые возвращают true, если событие произошло и false - в противном случае. Т.е. их заголовки:
Сами функции мы напишем позже. пока же считаем. что они у нас есть.
Также, у Вас есть пять действий: "включить Led1", "включить Led2", "выключить Led1", "выключить Led2" и "завести таймер на 1 сек". Опять же пишем соответсвенно пять функций:
Функции эти тривиальны и мы их напишем позже, пока же опять считаем, что они у нас есть.
Тогда оснновная программа выглядит совсем просто (я сейачс пиша для пояснения и не проверяю на опечатки и т.п., завтра откомпилируем и сделаем как надо). так вот, основная программа выглядит предельно просто. Ведём пальцеп по таблице и пишем точно то, что написано там:
Сравните с таблицей и убедитесь, что это просто слово в слово переписанная таблица и не более того.
осталось только вызывать функцию runAutomata постоянно в loop (ну и дописать недописанные простые функции).
Заметьте, если Вы сейчас поймёте эту идею, Вы сможете сделать почти любую автоматику - главное построить таблицу, а дальше всё и всегда одинаково.
Красота и все стало понятней, только мне все равно для понимания уже написаного и тем более при написании даже самых тривиальных функций придется метаться по справочнику) Как общую идею я все понял - свести логику кода в таблицу или схему где всегда состояние через воздействие меняется на другое определенное состояние и вызывает(или не вызывает) определенное действие
Ну, давайте продолжать.
Вы сказали, что с таблицей всё в порядке. Странно. Значит, с логикой что-то не то. Давайте посмотрим на примерах:
Пример №1.
Рассмотрим последовательность действий
1.Нажали кнопку (led1 горит, мы в состоянии №2)
2. Выждали больше секунды (led1 горит, мы в состоянии №3)
3. Нажали кнопку (ничего не горит, мы в состоянии №4)
4. Не дожидаясь таймаута ещё раз нажали кнопку (выключили led2, который итак был выключен и перешли в состояние №1)
Получается, что при нажатии кнопки в п.4 внешне вообще ничего не происходит. Это явно будет сбивать с панталыку пользователя.
Пример №2
Рассмотрим последовательность действий
1.Нажали кнопку (led1 горит, мы в состоянии №2)
2.Не выжидая нажали ещё раз (led1 и led2 горят, мы в состоянии №3)
3. Нажали кнопку (led1 горит, мы в состоянии №4)
4. Выждали больше секунды (led1 горит, мы ушли в состояние №1)
Приплыли. Теперь, для того, чтобы погасить led1 нам надо сначал зажечь led2 (другого выхода из состояния №1 нет). Это к примеру со спящим ребёнком – чтобы погасить свет, нам надо сначала зажечь его на полную.
Понравились примеры?
Это я к тому, что Вы должны твёрдо усвоить – любая, даже самая простая задача нуждается в тщательно проектировании. Иначе она будет работать через пень-колоду, как в моих примерах.
Проектирование это серьёзная работа, а вовсе не «изложить хотелку». Теперь Вы сами убедились, что нормальный проект всего-то для одной кнопки и двух лампочек у Вас уже со второго раза не получается :(
Никогда нельзя опускать стадию проектирования и программировать непосредственно хотелку. Получится, скорее всего, криво и потребует огромных усилий и очень высокой квалификации программиста. Хотелка – она ведь не проект, а «чувственная идея», а как говаривал граф Калиостро: «Материализация чувственных идей суть сложнейшая задача научной магии».
В общем с логикой Вам ещё разбираться и таблицу переделывать, но это без меня. Я пока покажу Вам как реализуется автомат на примере той таблицы, что есть. Научитесь принципам, легко и исправленную таблицу реализуете.
Итак, вчера мы остановились на том, что осталось написать функции для управляющих сигналов и действий, а именно
Последние 4 функции тривиальны, один digitalWrite Вы, думаю, сумеете написать. Потому. остановимся на первых трёх.
Сначала о кнопке.
Делать её в нашем случае проще всего так:
1. Заводим переменную, в которой будем всегда хранить текущее состояние кнопки (нажат или отпущена)
2. Заводим функцию, которую будем вызывать постоянно из loop. Эта функция один раз в 10 миллисекунд (например) узнаёт новое состояние кнопки. Если новое состояние, отличающееся от текущего (которое в переменной) повторилось два раза подряд, то считаем, что состояние кнопки изменилось. Тогда делаем следующее:
a. Изменяем переменную «текущее состояние» на новое.
b. Если новое значение «текущего состояния» - «нажата», то взводим флажок «кнопка нажата».
3. Наконец наша функция isButtonPressed просто возвращает этот флажок, попутно сбрасывая его (чтобы при следующем обращении не отработать одно нажатие дважды)
В принципе это тоже можно реализовать автоматом, я этого не делаю, но если для Вас сложно писать программы «с ходу», никогда не стесняйтесь делать автомат – рисуйте таблицу и вперёд.
Ну, а у нас получается как-то так:
Разбирайтесь.
Кстати, функцию isButtonPressed можно писать так нагло только потому, что мы не работаем с прерываниями. Если бы работали, то нам бы надо было иметь в виду, что переменная pressedFlag может имениться между строками 55 и 56 и это нам всё сломает.
Ну, смотрите, если там непонятно чего. ...
Ну, вот, собственно и всё. Основную функцию, мы вчера писали. Дополнительные написали сейчас. Осталось правильно сконфигурировать пины в setup и всё время вызывать в loop три функции: runTimer, runButton и runAutomata. Больше ничего не нужно.
Могу собрать весь код в кучу:
теперь, если Вы поставите свои пины для кнопки и светодиодов в строках 3-6 и внимательно отнесётесь к строкам 71-72 (возможно, Вам надо поменять там наоборот), то всё по идее должно нормально заработать по логике той таблицы, что у нас была вчера.
Разбирайтесь, меняйте таблицу (я утром писал про ошибки) и делайте по уму сами.
Пример1 пункт 4 с толку вряд ли собьет, так как вторичное нажатие до истечения 1сек есть действие нелогичное- свет не горит, зачем тыкать кнопку? Я вобще считаю второе нажатие необязательным действием), это просто расширение функционала, никто же на клацает выключателем по многу раз просто так, следовательно, тот кто так будет делать знает чего ожидать.
Пример2 пункт 3 не был мною озвучен именно так, я считал что второе нажатие из второго состояния отключает все включенное этой кнопкой и для моего частного случая на кнопку S1 я бы навесил отключение всего освещения на этаже по второму нажатию.
Так что логика верна))) просто немного осталось за пределами таблицы
Пример2 пункт 3 не был мною озвучен именно так, я считал что второе нажатие из второго состояния отключает все включенное этой кнопкой
Возможно, Вы так подумали, а написали в посте №9 буквально следующее
2.2.1 действие "нажатие2"(второе), выполнимо, если "таймер 1секунда от нажатия1" еще не вызвал переход в период1"ВКЛ", вызывает выключение LED2-->отмену отсчета "таймер 1секунда"-->переход в период1 "ВКЛ".
Как видите про led2 есть, а про "всё" - нету :(
Но это не важно. Мы же занимаемся не поиском виновных, а разработкой. Думайте. если надо меняйте таблицу, работайте.
Комментарии сами по себе достойны уважения, а код тем более) Я и не ожидал такого участия в своем вопросе, посему- огромное человеческое спасибо, про конфигурацию пинов все понятно(из примера blink).
а inline зачем?
Да, тут скорее всего не надо, осталось от чего-то прежнего. inline имеет смысл, когда функция из единственного места вызывается, а здесь это не так. Так что, можно смело убирать.
73