Ардуино таймер энкодер

Термостат с таймером

Задача

Разработать термостат с таймером для йогуртницы или других применений: термостат держит температуру только на протяжении заданного времени, всё остальное время (режим ожидания) – реле выключено

  • Релейное регулирование с гистерезисом
  • Бесшумное управление – используем нагрузку постоянного тока и МОСФЕТ модуль
  • Рабочий цикл по таймеру (включили-регулируем-выключили)
  • Управление энкодером
  • Вывод на 7-сегментный дисплей
    • Двоеточие мигает, если рабочий цикл запущен
  • Звуковая индикация окончания рабочего цикла

Базовые уроки

Компоненты не из набора

  • В моём проекте контроллера йогуртницы используется блок питания на 12V и нагревательный кабель

Подключение

  • Энкодер: любые цифровые пины
  • Зуммер: любой цифровой пин через ограничительный резистор 100 Ом
  • Дисплей: любые цифровые пины
  • Мосфет модуль: любой цифровой пин
  • Термистор: любой аналоговый пин
  • Внешнее питание 12V: пин Vin

Библиотеки

  • EncButton – энкодер с кнопкой
  • GyverTM1637 – дисплей
  • GyverNTC – термистор

Программа

Инициализация

Компонентов много, так что для удобства задефайним все пины константами, и только потом подключим все библиотеки и создадим объекты:

Нам понадобится несколько глобальных переменных (для простоты программы), обозначим флаги и переменные режимов:

  • Нужен флаг, отвечающий за рабочий цикл: запущен таймер термостата, или нет. Соответственно реле управляется только при поднятом флаге, как и счёт оставшегося времени. Назовём его state : 0 – режим ожидания, 1 – “рабочий цикл”, когда идёт обратный отсчёт
  • Хочу выводить на дисплей оставшееся время, заданную температуру и текущую температуру датчика – имеем три режима отображения, пусть будет переменная mode
  • Понадобится переменная таймера tmr . Таймер мы сбросим при запуске рабочего цикла
  • Нам нужно хранить оставшиеся минуты рабочего цикла (они же – настроенное время работы), целевую температуру и текущее значение с датчика. Назовём всё соответственно:

В блоке setup() сделаем нужные пины выходами, запустим и обновим дисплей:

Обновление дисплея

Здесь updDisp() – функция, которую я создаю для удобства, т.к. она будет вызываться и в других местах программы. Взглянем на неё поближе:

Вывод на дисплей зависит от текущего режима отображения mode :

  • При 0 мы выводим время при помощи displayClock(часы, минуты) . Я не просто так храню время в минутах, так удобнее с ним работать: проверять таймер и менять значение энкодером. Из общих минут можно получить часы, просто разделив на 60. При целочисленном делении дробная часть отсекается, то есть округление идёт вниз и мы всегда получим целые часы. Для получения минут – берём остаток от деления на 60, и всё! Что касается строчки if (!state) disp.point(1); – я хочу чтобы двоеточие на дисплее горело постоянно, если рабочий цикл не запущен. Поэтому принудительно включаем. В ждущем режиме мы просто выводим настроенные минуты mins , а во время работы таймера – сколько времени осталось до конца. Это можно реализовать разными способами, я выбрал самый простой (это всё-таки урок, а не погоня за оптимальным кодом): считаем оставшиеся минуты, вычитая прошедшее с момента запуска таймера время из заданных минут. И заданные минуты мы всё ещё сможем менять, то есть заставить таймер сработать чуть раньше или позже – пусть это будет фишкой
  • При 1 выводим значение установленной температуры temp , а также выводим букву t в левое знакоместо дисплея. Выключаем двоеточие, если находимся в режиме ожидания
  • При 2 выводим значение с датчика sens , а также букву S

Main loop

Главный цикл программы выглядит вот так, в нём несколько функций, мы их рассмотрим ниже:

Управление

Управление энкодером организуем следующим образом:

  • Поворот энкодера: изменение текущего значения на дисплее: градусы на 1, время – на 10 минут. При любом повороте нам нужно обновить дисплей
  • Удержание кнопки: запуск рабочего цикла:
    • Поднимаем флаг рабочего режима state = 1
    • А также сбрасываем таймер обратного отсчёта
  • Клик по кнопке: переключение режимов отображения (фактически закольцованное изменение переменной mode от 0 до 2). Также обновляем дисплей

Регулирование

Здесь всё просто: взводим таймер на 1 секунду, по нему опрашиваем термистор. Мы задаём температуру в целых числах, поэтому для более корректной работы лучше математически округлить значение перед присваиванием к переменной temp .

Если рабочий цикл запущен – идёт релейное регулирование с гистерезисом, оно разбиралось в отдельном уроке. Таким образом сигнал на реле рассчитывается раз в секунду и имеет дополнительную защиту от частых переключений в виде гистерезиса

Таймеры и индикация

Два раза в секунду хотим мигать двоеточием, а также обновлять дисплей (там ведь тикает время и меняются показания датчика). “Мигать” очень просто – заводим себе переменную-флажок, и каждый вызов просто его инвертируем и передаём в функцию управления двоеточием

Далее проверяем таймер рабочего цикла, не вышло ли время. Если вышло – пищим пять раз при помощи функции tone() , а затем переходим в ждущий режим, обнулив state . Всё!

Полный код программы

Возможные доработки

  • Использовать более точный датчик температуры ds18b20
  • Использовать более хитрый алгоритм релейного управления
  • Использовать реле вместо мосфет-модуля для контроля сетевого нагревательного элемента
  • Использовать ПИД регулятор, так как мосфет-модуль и ШИМ сигнал позволяют это сделать

Видео

Источник

Arduino.ru

Простой кухонный таймер 4симв.TM1637, энкодер, аккум.18650

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Простой кухонный таймер, после включения энкодером устанавливается количество минут. Долгое нажатие на энкодер запускает таймер. Через 10 секунд бездействия дисплей на минимальную ярскость переходит, через минуту устройство уходит в спящий режим. В режиме непосредственно обратного отсчета через минуту просто отключается дисплей. Нажать на энкодер или повернуть — экран заново загорается.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Хорошо, но «маловато будет» :)

Мне, частенько, 2 или 3 таймера нужно на кухне. Люблю готовить. Добавив еще одну матрицу и кнопку можно получить 10 таймеров.

Кроме того неплохо-бы сохранять предыдущее значение таймера — крутить не от нуля.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Я все железки делаю под свои простые задачи :) так что развития конкретно данного проекта не будет. Вот с дребезгом контактов не доработал, энкодер пропускает, но надеюсь время найду — доделаю.
Опять же, каждое увеличение функционала — > увеличение кнопок/регуляторов, а в данном случае — просто замена механического таймера газовой плиты Gefest.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Врет mykaida, сдается мне. Тому, кто любит готовить, таймеры не нужны — он время чует. А вот ежели повар вместо готовки форум читает.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

andycat, функции TM1637::Start() и TM1637::Stop() это protected функции класса, которые предваряют/завершают передачу данных в дисплей. Для чего ты их приспособил к энергосбережению? Для энергосбережения надо ноги в INPUT переводить и отключать в регистре энергосбережения пошти всё. :)

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

DetSimen, да когда начинал, понадеялся что это поможет индикаторам поменьше кушать (каюсь — даташит не читал), но не помогло, да так и осталось.
ЗЫ. Из 120 мкА потребления в спящем режиме, 99.99 % это именно индикатор, если переводить схему на более экономный источник питания, не помешает транзисторный ключ. У меня 18650 аккумуляторов много, не стал заморачиваться.

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

Здравствуйте! Можно схемку на этот таймер?

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
  • Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии

andycat, что я делаю не так? помогите решить проблему? я не силен в написании кода. смиренно прошу помощи :)

d:\DiskD\Arduino\timer_2\timer_2.ino: In function ‘void initTM1637()’:
d:\DiskD\Arduino\timer_2\timer_2.ino:77:17: error: ‘void TM1637::Start() const’ is protected within this context
Display.Start();
^
In file included from d:\DiskD\Arduino\timer_2\timer_2.ino:1:0:
d:\DiskD\Arduino\libraries\TM1637/TM1637.h:54:7: note: declared protected here
void Start(void) const; // выдает старт условие на шину
^

d:\DiskD\Arduino\timer_2\timer_2.ino: In function ‘void offTM1637()’:
d:\DiskD\Arduino\timer_2\timer_2.ino:82:16: error: ‘void TM1637::Stop() const’ is protected within this context
Display.Stop();
^
In file included from d:\DiskD\Arduino\timer_2\timer_2.ino:1:0:
d:\DiskD\Arduino\libraries\TM1637/TM1637.h:56:7: note: declared protected here
void Stop(void) const; // выдает стоп условие на шину
^

Compilation error: Error: 2 UNKNOWN: exit status 1

Источник

Подключение энкодера к Ардуино и полнофункциональный код обработки для него

Энкодер — это устройство преобразования механического перемещения или угловых изменений положения в цифровой сигнал. В статье рассматривается самый популярный в DIY сообществе инкрементальный энкодер EC11 с кнопкой. При его вращении на выходах A и B формируются TTL сигналы в виде импульсов сдвинутые между собой по фазе на 90 градусов. Таким образом с его помощью, можно определить направление и скорость вращения, а так же рассчитать угол поворота. В отличие от потенциометров, энкодер KY-040 гораздо надежней и долговечный.

Немного подробностей

Собирая один из проектов с использованием encoder. Я не смог найти код для Ардуино выполняющий все мои условия. Так как для проекта нужно обрабатывать следующие команды: «Вращение без нажатия», «Вращение с нажатием», «Нажатие» и «Длинное нажатие», а так же требуется стабильная работа энкодера. Скетчи использующие один пин с прерыванием INT0 или INT1, работают отвратительно и при вращении вала энкодера вылетает очень много ошибок. Код без использования прерываний работает стабильно, но он не работает в фоновом режиме, его нужно встраивать в тело основной программы, что в свою очередь приводит к не своевременному срабатыванию обработчика и пропускам при вращении энкодера. Еще хуже обстоят дела с обработкой нажатия с вращением вала энкодера и обычным с нажатием. Пришлось написать свой код обработки, который исключает описанные выше проблемы. С дребезгом контактов я не стал бороться программно, так как это приводит к задержкам обработки. Проще и надежней использовать керамические конденсаторы.

Схема подключения энкодера к Ардуино

Для считывания сигналов с выходов EC-11, нужно использовать три цифровых входа Arduino. В схеме подключения я использовал редко используемые мной в своих проектах выводы Arduino(A1, A2 и A3). Внешние подтягивающие резисторы отсутствуют, так как я использовал внутреннюю подтяжку микроконтроллера. Конденсаторы нужны для гашения импульсов дребезга контактов. Если у вас новый и хороший энкодер, то можно обойтись и без них. Но на кнопку в любом случае потребуется конденсатор, так как ее дребезг неизбежен.

Используемые в схеме компоненты:

Скетч для Ардуино

Для того что бы отслеживать изменение положения энкодера в фоновом режиме, я использую прерывание PCINT1. Обработка всех функций происходит в прерывании, обработчик в зависимости от произошедшего действия изменяет переменную enc_state. Если значение переменной enc_state=0 — ничего не произошло, enc_state=1 — экодер вращался без нажатия, enc_state=2 — экодер вращался с нажатием, enc_state=3 — было нажатие на кнопку, enc_state=4 — было длинное нажатие на кнопку, Прерывание будет срабатывать каждый раз по изменению состояния входов, как с высокого уровня на низкий, так и наоборот. То есть при одном щелчке энкодера прерывание сработает 4 раза. Или по 2 раза для каждого из входов. Но обработчик выдаст сигнал поворота только 1 раз на все 4 прерывания.
Код обработчика при каждом срабатывании записывает в переменную lastcomb состояние входов, к которым подключен энкодер. И ждет состояние когда выходы A и B будут замкнуты на GND, это гарантированный сигнал того, что энкодер вращается. После того как этот сигнал получен, обработчик проверяет в какую сторону было вращение. Для этого он сравнивает его предыдущее значение из переменной lastcomb и в зависимости от фазы сдвига определит в какую сторону был поворот ротора. Как я писал ранее, сложнее всего отслеживать нажатие кнопки.
Так как использовать определенные тайминги я не планировал, потому, что они неизбежно приводят длительным задержкам работы обработчика и основной программы, или требуют использование таймера, которых в микроконтроллере всего 3 шт. их, как правило никогда не хватает. Собственно проблема состояла в том, чтобы разделить «нажатие с последующим вращением» от простого нажатия. В итоге как вы уже можете убедиться, я решил эту задачу. Оптимизацией кода я не стал заниматься, потому как все работает и меня все устраивает. Для наглядности в коде все действия с энкодером, отображаются в Serial мониторе программы Adruino IDE.

Заключение

Результат работы кода меня порадовал и теперь я могу продолжить работу над своим новым проектом, который скоро здесь выложу. Надеюсь эта короткая статья вам понравилась и вы сможете воспользоваться моей наработкой в своих самоделках.

Если у Вас остались вопросы и замечания, пишите их в комментариях. Я с удовольствием на них отвечу.

Источник

Adblock
detector