![]() |
![]() |
||||||||||||
Таймер по будним дням на К1946ВМ014
Автор: ejsanyo Приветствую любителей малой автоматиации. В прошлый раз мы уже собирали простейший автомат для регулярного включения нагрузки на основе микроконтроллера К1946ВМ014. Как насчёт сделать в этот раз кое-что посложнее и фунциональнее? Понадобился мне тут таймер, чтобы вовремя включать и, что важнее, выключать на рабочем месте тепловентилятор. Надёжный, программируемый (чтобы все настройки можно было сделать заранее), но при этом не переусложнённый в настройке. В каком смысле "не переусложнённый"? В наше время, понятное дело, модно для этого прикручивать выход в Интернет с управлением через "облако" или какую-нибудь "Алису", ну или хотя бы bluetooth с приложением на телефоне по подписке. Но нельзя ли, чтобы всё то же самое можно было интуитивно настроить парой кнопок на корпусе, и отображая при этом всё что нужно на простом "восьмёрочном" светодиодном индикаторе, даже без использования графических/текстовых дисплеев? Если вам так же, как и мне, по душе разумный минимализм, то попробуем сделать "по старинке". Сначала формализуем описание функций нашего изделия:
Коль скоро у нас тут появляется индикация, в первую очередь подумаем, как её можно реализовать. В крайнем случае, можно было бы просто повесить светодиодную матрицу на выходы GPIO контроллера (даже у К1946ВМ014 их количества достаточно) и сделать программную развёртку. Но с точки зрения удобства программирования специализированные чипы - драйверы индикации для этой цели подходят лучше. Да и выходные каскады в них рассчитаны, чтобы пропускать довольно большие токи. Ранее мы уже рассматривали подобный чип по имени MAX7219, также вскользь упомянули про TM1637. А какие существуют ещё варианты? Представляем вашему вниманию TM1650 Производится китайской компанией Titan Micro. Той же самой, что делает TM1637. Продаётся во многих магазинах, при этом стоит даже дешевле, чем его предшественник! Выпускается в малогабаритном корпусе SO-16, поддерживает 4 разряда цифр, именно столько, сколько нам требуется для отображения времени. Поддерживает опрос кнопок, параллельно подключенных к сегментным выходам, с фильтрацией дребезга конактов. В части интерфейса китайцы проделали в нём большую работу, сделав его гораздо более удобным и применимым на практике. Что за нюансы с интерфейсом? Чтобы понять это, рассмотрим сначала, как с этим обстоят дела у "старшего брата" TM1637: Видим синхронный интерфейс, отдельно тактовый сигнал, отдельно двунаправленная линия данных. Старт, стоп-биты...всё очень похоже на типовую шину I2C? Не тут-то было! По неведомым причинам в TM1637 разработчики сочинили нечто своё, "по мотивам", но несовместимое с I2C. Опишем основные отличия:
И последний нюанс представляет реальную проблему. Почему так? Вот, допустим, вы, обрадовавшись такому сходству протоколов, вешаете чип на аппаратный выход I2C мастера своего любимого контроллера. Подумаешь, передадим вместо адреса I2C устройства ту самую команду, переставив местами биты, а потом и данные. Так вот, это будет работать только в случае, если на борту вашего контроллера "глупый" I2C модуль, который не проверяет корректность формируемого пакета. Мне такие попадались крайне редко: в контроллере 1986ВЕ92 от Миландра, да ещё "полуаппаратный" модуль USI, встречающийся с чипах серии Attiiny. Ну и, конечно, в программных реализациях I2C ("ногодрыгом"), или прицельно интерфейса TM1637, проблем не будет. Но чаще всего разработчики чипов зачем-то всё усложняют, и, в частности, делают аппаратную проверку младшего бита адреса I2C, соответствует ли он текущей операции. Дело в том, что по правилам I2C этот бит должен быть всегда равен нулю, если мы передаём данные в девайс (будем после адреса передавать ещё байты данных) и единице - если принимаем данные. И если, скажем, выставить этот бит в единицу, но при этом попробовать выполнить операцию записи, практически в любом контроллере, шибко "умный" I2C модуль тут же встанет колом с ошибкой и откажется что-либо передавать. Даже аппаратный блок в нашей, казалось бы, совсем несвежей Atmega8535 К1946ВМ014 ведёт себя так же! А таких команд, с "неправильным" битом, у TM1637 немало. Скажем, "Display ON/OFF". Но самое печальное - команда установки адреса, без которой данные для отображения мы не запишем - в пролёте, поскольку имеет единицу в старшем разряде. Даже команда опроса кнопок имеет ноль в "неправильном месте" и потому не пройдёт! Вот почему подавляющее большинство применений TM1637, которые вы найдёте в интернетах, предполагают именно программную реализацию обмена данных с ним, что порой делать очень неудобно. Но что же относительно TM1650? По-первых, разработчики сделали порядок битов таким же, как в I2C, от старшего к младшему. Лучше поздно, чем никогда. Но самое главное - они подогнали все команды более-менее под соответствие I2C! Т.е. все команды записи данных имеют ноль младшим битом, команда опроса кнопок - единицу. Выглядит как "костыль", и с точки зрения "настоящего" I2C мы по прежнему творим полный беспредел, закидывая по разным адресам невесть что. Но, по крайней мере, теперь наш контроллер не ругается и пропускает всё это через себя. Учитывая вышесказанное, очень странным кажется то, что рынок по прежнему завален готовыми модулями индикации лишь на основе TM1637, чуть в меньшей степени - MAX7219, а, казалось бы, неплохой и копеечный TM1650 для этих целей игнорируется. Модули на его основе крайне редко встречаются, а те, что встречаются, стоят каких-то неадекватных денег. Хотя в бытовой аппаратуре китайского производства чип попадается довольно часто. Что-ж, раз с готовыми платами индикации не очень, попробуем сделать свою? В качестве, собственно, индикатора, возьмём GNQ-4041AS-21 из предыдущей статьи. Он как раз имеет конфигурацию, оптимизированную для отображения времени, три дополнительные точки (они нам пригодятся, см. далее) и разряды с общим катодом, что как раз требуется для TM1650. Добавим также на плату те самые пару кнопок для настройки таймера, раз уж TM1650 предлагает нам такую возможность, да ещё и с антидребезгом. С этим связан интересный момент - TM1650 передаёт не только скан-код нажатой кнопки, но и после сохраняет скан-код только что отжатой кнопки, до следующего нажатия. Вероятно, это где-то может пригодиться. XP1 - типовая линейка PLS-4. C2, C3, возможно, несколько улучшают помехоустойчивость интерфейса. Вроде у TM1650 с этим проблем нет, но сами китайцы их, как правило, ставят. Ещё отметим, что в режиме максимальной яркости чип потребляет ток более 100 мА и, соответственно, начинает ощутимо греться. Учитывайте этот факт в своих разработках. Проект платы в Altium Designer, как обычно, в конце статьи. Плата односторонняя, поэтому некоторое количество переходных перемычек поставить пришлось. Аппаратную часть интерфейса пользователя мы сделали. Перейдём теперь ко всему остальному. Используем по максимуму наработки, полученные в прошлых проектах. И изобразим результат. Как видно, силовая часть практически полностью повторяет схемотехнику дистанционно управляемой розетки. Напомним лишь основные моменты: Трансформатор питания ТПК-2 на 8В, после выпрямления его выхода и сглаживания это напряжение превращается примерно в 11...12В постоянного тока под номинальной нагрузкой. Отметим, что из-за возросшей за счёт индикации нагрузки это напряжение во всех случаях укладывалось в диапазон до 16В, но для надёжности рекомендую устанавливать C5 на 25В. Из-за возросшей нагрузки и стабилизатор на 5В пришлось взять несколько мощнее (старый добрый КР142ЕН5А), прижав его фланцем к заливке в качестве радиатора. Управление симистором осуществляется через импульсный трансформатор МИТ-16В при помощи ШИМ выхода таймера 0. О его особенностях, подстройке длительности импульсов и о мерах безопасности при подстройке подробно рассказано в той же статье. Моменты включения/выключения нагрузки синхронизируются с полупериодами сетевого напряжения при помощи внешнего прерывания Int0. Мощности симистора ТС106-10-8, установленного на радиатор SK29-25S, достаточно, чтобы коммутировать нагрузку примерно до 500 Вт. Если вам требуется больше, придётся озаботиться дополнительным охлаждением. И не забываем учитывать силовые характеристики элементов снабберной цепочки C1 R1, если будете её устанавливать. В качестве источника временных отсчётов используется, как и в первом проекте, таймер 2 с подключенным к нему часовым резонатором 32768 Гц. Но на сей раз в обработчике прерываний размещается минимум действий, всего лишь приращение счётчика времени. Предделитель таймера настроен, как и в прошлый раз, на 1024, но коэффициент пересчёта таймера мы выставим 16. Так что счётчик времени, по сути, подсчитывает количество половин секунд! Зачем это нужно? Изначально из-за того, что хотелось сделать характер мигания двоеточия на индикаторе таким же, как на моих часах на основе КР145ИК1911, там состояние его меняется раз в пол секунды. В алгоритме вывода времени делаем так, что двоеточие выводится при чётном количестве полусекунд, и дело сделано. Позже такое представление времени пригодилось ещё в некоторых моментах, см. далее. Разъём программатора, как всегда, сделан в соответствии с распиновкой, принятой для программаторов ChipProg. Аппаратный I2C интерфейс, имеющийся в К1946ВМ014, тоже выведем на межплатный разъём. Для работы с I2C (или "Two wire interface", как его упорно именуют в документации Atmel) можно было бы использовать готовые функции, входящие в более поздние версии CodevisionAVR, но мы, пожалуй, пойдём другим путём и адаптируем популярную библиотеку avr-twi. Вообще, работа с "умным" I2C модулем через прерывания и его статусы - это отдельная тема, достойная целой статьи, поэтому здесь не будем подробно рассматривать устройство данной библиотеки. Главное в нашем случае - объявить обработчик прерывания и не забывать вызывать twi_wait() перед тем, как запускать новый обмен данными по шине. В качестве I2C адреса, понятное дело, подсовываем ей команды, а вернее, номера регистров TM1650. Для поддержки работы часов при пропадании питания, как и в прошлый раз, возьмём ионисторную батарею СКФ-2.5-5В4, или другую на напряжение не ниже 5В. Но если в простом таймере после отработки прерывания часов мы могли сразу отправлять контроллер в режим экономии энергии, без разницы, что у нас с питанием в текущий момент, то в данном приборе так не пойдёт, в рабочем режиме у контроллера много дел: надо выводить время на дисплейную плату, опрашивать её кнопки, да ещё и генерировать импульсы включения симистора. А значит, появляется необходимость оперативного контроля наличия сетевого напряжения. При его пропадании требуется срочно прекращать всякую излишнюю активность и начинать экономить энергию, чтобы подольше продержаться на заряде ионистора, а при восстановлении - возобновлять полноценную работу. Чем же контролировать сетевое напряжение? Вспомним, что наша "российская Атмега" имеет в своём составе не только цифровые, но и аналоговые блоки. В частности, имеется встроенный компаратор напряжения. Да не просто компаратор, а со встроенным источником опорного напряжения (примерно 1,2В). Вот с ним мы и будем сравнивать то, что приходит от стабилизатора. Но не всё так просто! Смотрим схему силовой части и внезапно понимаем, что вход компаратора мы уже заняли выходом ШИМ таймера 0! Что же теперь делать? Переделывать ШИМ на другой таймер? И всё-таки иной выход есть: в архитектуре чипа заложена необычная возможность задействовать вместо "номинального" входа AIn1 аналоговый мультиплексор, являющийся составной частью АЦП, и подключить к компаратору таким образом любой из его входов! Воспользуемся этим и подключим сигнал сетевого питания, скажем, ко входу ADC4. Делитель R13, R14 подобран так, чтобы порог срабатывания компаратора находился в пределах около 4,2В. А братья-диоды Шоттки VD3 помогают правильно подавать питание на контроллер и его цепи, не замыкая между собой источники. Осталось только доделать алгоритм прошивки. Счётчик половин секунд считает непрерывно, до тех пор, пока может. Однажды он, конечно, перейдёт через ноль, но как уже говорилось ранее, в мире беззнаковых чисел это не важно, результат вычислений будет адекватным. В основном цикле программы поведение определяется текущим значением статуса выполняемой операции (кажется это называют "конечным автоматом"?). В нормальном режиме работы (когда питание в норме, и не включен режим настройки) при помощи волшебства модулярной арифметики отсчёты половин секунд превращаются в значения дня недели, часов и минут. Всё это выводится на индикаторы с минимальной яркостью, чтобы не бросалось в глаза, да и не так сильно расходовало ресурс светодиодов. Производится также опрос кнопок через TM1650. Помните, у нас на плате индикации есть кнопки? Для дальнейшего описания обозначим кнопку SB1 как "+1", а кнопку SB2 - как "Настр.". Итак, в нормальном режиме если нажимать кнопку "+1" можно в ручном режиме управлять нагрузкой, включая и выключая её (мало ли, если от нагревателя стало жарко). Включение нагрузки дублируется зажиганием средней точки индикатора. При длительном нажатии кнопки "Настр." таймер переходит в режим настройки. При этом индикатор загорается ярче, а точка снизу намекает, какой разряд времени мы редактируем. Кнопка "+1", соответственно, увеличивает разряд на единицу, кнопка "Настр." делает переход от редактирования часов к минутам, а следующим нажатием - к дню недели. Во внутренней памяти этот параметр начинается, конечно, с нуля, но не будем нарушать человеческих традиций, и при отображении настройки покажем её более общепринятым способом, начиная с единицы (понедельник) до семи (воскресенье). Следующее нажатие "Настр." применит настроенное время и перекинет нас к настройке уставки 1 - времени включения, на что намекает средняя точка индикатора. Кнопка "+1" увеличивает разряд на единицу, кнопка "Настр." делает переход от редактирования часов к минутам. Ещё одно нажатие кнопки "Настр." сохранит в EEPROM выставленное значение уставки 1 и переведёт нас к настройке уставки 2 - времени выключения. Чтобы это показать, средняя точка индикатора погашена , и точка. Кнопка "+1" увеличивает разряд на единицу, кнопка "Настр." делает переход от редактирования часов к минутам. И если после этого ещё раз нажать "Настр.", настройка уставки 2 будет записана в EEPROM, а мы вернёмся в нормальный режим работы. Предусмотрен таймаут на режим настройки (вдруг кто-то случайно нажал на кнопку?), который мы реализовали на оставшемся свободным таймере 1: если в течение примерно 8 секунд не нажимать кнопки, таймер выйдет из режима настроек, и изменения последнего редактировавшегося параметра не сохранятся. Рассмотрим некоторые нештатные моменты: Что будет, если юзер возьмёт, да и настроит обе уставки на одно и то же время? В алгоритме ввода на этот случай предусмотрена защита - поскольку значение уставок, как и времени, хранится в виде количества половин секунд, при обнаружении совпадения значений уставка 2 автоматически будет увеличена на единицу, т.е. на 0,5 секунды. И далее по сути, автоматика так и отработает - включит нагрузку в заданное время всего лишь на пол секунды. А что будет, если мы только что включили таймер, не успев его настроить? Тогда алгоритм, обнаружим, что считанные уставки совпали, задаст им значения по умолчанию: уставка 1 - 00:00, уставка 2 - на пол секунды больше. В самом начале цикла у нас вставлена проверка состояния компаратора, в норме ли первичное питание? Если оно пропадает, как уже говорилось, алгоритм резко выключает все таймеры, кроме таймера 2, гасит индикацию TM1650 и переводит ядро а глубокий сон, из которого оно будет выводиться по циклическим прерываниям таймера 2. Согласно различным версиям даташита TM1650, китайцы обещают статический ток потребления то ли 0,05, то ли до 0,3 мА. Фактически суммарный замеренный ток потребления таймера в режиме экономии у меня составил около 0,2 мА. На какое время этого хватит? Не так уж сложно посчитать, когда есть хороший калькулятор: Получается, часа на 4,5 мы рассчитывать можем? Если у вас на работе свет выключают на более продолжительное время, всегда можно попробовать просто отсыпать побольше фарад, а потом ещё побольше либо задуматься об установке небольшого аккумулятора. Но вот у нас питание восстановилось, что тогда? Если уставка 2, как ей и положено, выставлена позже по времени, чем уставка 1, то нагрузка будет включена, если текущее время находится в интервале между уставкой 1 и 2, и при этом будний день. Можно рассмотреть и нештатную ситуацию, когда уставка 2 по времени раньше, чем уставка 1...эмм, вы работаете в ночную смену и заканчиваете работу на следующий день? Пока сделал так, что в этом случае нагрузка будет включена, если текущее время находится в интервале между уставкой 2 и 1, хотя это и не полностью согласуется с принудительным выключением в выходные дни. Конечно, мало ли у кого какой бывает рабочий график, и если он у вас не совсем обычный, вероятно, алгоритм придётся исправить под него. Конечно, наиболее универсальным был бы вариант с настройкой включения и выключения индивидуально для каждого дня недели, но как сказано выше, не хотелось усложнять процедуру настройки. По этой же причине не заложена возможность совсем отключить действие уставок: если, скажем, уходите в отпуск, или на новогодние праздники, вероятно более правильно и безопасно будет перед уходом просто выключить все приборы из розетки. Прошивка написана, как обычно, в CodeVision V2.04.4a. Фьюзы выставлены так: lfuse = 0x24, hfuse = 0xD9. Проект основной платы в Altium Designer также в конце статьи. Как видно, она снова спроектирована под корпус BOX-KA05, потому что...почему бы и нет? С платой индикации она соединяется шлейфом небольшой длины. На крышке сверху - классическая советская розетка РД1. Традиционное напоминание о безопасности: Часть схемы таймера находится под опасным сетевым напряжением! Соблюдайте соответствующие меры предосторожности при сборке и наладке устройства. На схеме предохранитель по входу не показан, но как видите, он есть. И вы не пренебрегайте его установкой, когда будете повторять конструкцию!
Файлы: Все вопросы в Форум.
|
|
||||||||||||
![]() |
![]() |


![]() |
||||
|
|
||||










