Кухонный таймер на ардуино,

Содержание

Скетч

После того, как все подключено в соответствии с электрической схемой выше, загрузите этот код в ваш Arduino:

После загрузки и компиляции кода, установите потенциометр 10K на минимум.

Реле включит свет, когда фоторезистор будет темным (покрытым). А когда управление установлено на минимальный уровень, реле включит свет, а затем выключит, как только вернется свет (закат на рассвет).

Однако, если вы хотите, чтобы свет появился в темноте, оставьте его включенным на некоторое время, а затем выключите до восхода солнца.

Отрегулируйте потенциометр 10K, чтобы контролировать, как долго свет будет гореть после наступления темноты. Таймер активируется, как только регулятор выше 0V (нуля вольт).

Слегка повернув вверх, регулятор времени включит свет на несколько минут, прежде чем снова выключится. При полном включении таймера свет останется включенным примерно на 4 часа до его выключения.

По истечении времени все автоматически сбрасывается, и свет становится доступным. При полном выключении регулятора (до нуля вольт) свет включается в темноте и остается включенным до тех пор, пока свет не вернется (от захода солнца до восхода солнца).

Если вам необходимо вручную перезагрузить устройство, подумайте о добавлении кнопочного переключателя для заземления кнопки сброса (RST).

Прерывания в языке Arduino

Теперь давайте перейдем к практике и поговорим о том, как использовать прерывания в своих проектах.

Синтаксис attachInterrupt()

Функция attachInterrupt используется для работы с прерываниями. Она служит для соединения внешнего прерывания с обработчиком.

Синтаксис вызова: attachInterrupt(interrupt, function, mode)

Аргументы функции:

interrupt – номер вызываемого прерывания (стандартно 0 – для 2-го пина, для платы Ардуино Уно 1 – для 3-го пина),
function – название вызываемой функции при прерывании(важно – функция не должна ни принимать, ни возвращать какие-либо значения),
mode – условие срабатывания прерывания.

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

  • LOW – выполняется по низкому уровню сигнала, когда на контакте нулевое значение. Прерывание может циклично повторяться – например, при нажатой кнопке.
  • CHANGE – по фронту, прерывание происходит при изменении сигнала с высокого на низкий или наоборот. Выполняется один раз при любой смене сигнала.
  • RISING – выполнение прерывания один раз при изменении сигнала от LOW к HIGH.
  • FALLING – выполнение прерывания один раз при изменении сигнала от HIGH к LOW.4

Важные замечания

При работе с прерываниями нужно обязательно учитывать следующие важные ограничения:

  • Функция – обработчик не должна выполняться слишком долго. Все дело в том, что Ардуино не может обрабатывать несколько прерываний одновременно. Пока выполняется ваша функция-обработчик, все остальные прерывания останутся без внимания и вы можете пропустить важные события. Если надо делать что-то большое – просто передавайте обработку событий в основном цикле loop(). В обработчике вы можете лишь устанавливать флаг события, а в loop – проверять флаг и обрабатывать его.
  • Нужно быть очень аккуратными с переменными. Интеллектуальный компилятор C++ может “пере оптимизировать” вашу программу – убрать не нужные, на его взгляд, переменные. Компилятор просто не увидит, что вы устанавливаете какие-то переменные в одной части, а используете – в другой. Для устранения такой вероятности в случае с базовыми типами данных можно использовать ключевое слово volatile, например так: volatile boolean state = 0. Но этот метод не сработает со сложными структурами данных. Так что надо быть всегда на чеку.
  • Не рекомендуется использовать большое количество прерываний (старайтесь не использовать более 6-8). Большое количество разнообразных событий требует серьезного усложнения кода, а, значит,   ведет к ошибкам. К тому же надо понимать, что ни о какой временной точности исполнения в системах с большим количеством прерываний речи быть не может – вы никогда точно не поймете, каков промежуток между вызовами важных для вас команд.
  • В обработчиках категорически нельзя использовать delay(). Механизм определения интервала задержки использует таймеры, а они тоже работают на прерываниях, которые заблокирует ваш обработчик. В итоге все будут ждать всех и программа зависнет. По этой же причине нельзя использовать протоколы связи, основанные на прерываниях (например, i2c).

Прерывания в Ардуино

Прерывание – это сигнал, который сообщает процессору о наступлении какого-либо события, которое требует незамедлительного внимания. Процессор должен отреагировать на этот сигнал, прервав выполнение текущих инструкций и передав управление обработчику прерывания (ISR, Interrupt Service Routine). Обработчик – это обычная функция, которую мы пишем сами и помещаем туда тот код, который должен отреагировать на событие.

После обслуживания прерывания ISR функция завершает свою работу и процессор с удовольствием возвращается к прерванным занятиям – продолжает  выполнять код с того места, в котором остановился. Все это происходит автоматически, поэтому наша задача заключается только в том, чтобы написать обработчик прерывания, ничего при этом не сломав и не заставляя процессор слишком часто отвлекаться на нас. Понадобится понимание схемы, принципов работы подключаемых устройств и представление о том, как часто может вызываться прерывание, каковы особенности его возникновения. Все это и составляет основную сложность работы с прерываниями.

Аппаратные и программные прерывания

Прерывания в Ардуино можно разделить на несколько видов:

  • Аппаратные прерывания. Прерывание на уровне микропроцессорной архитектуры. Самое событие может произойти в производительный момент от внешнего устройства – например, нажатие кнопки на клавиатуре, движение компьютерной мыши и т.п.
  • Программные прерывания. Запускаются внутри программы с помощью специальной инструкции. Используются для того, чтобы вызвать обработчик прерываний.
  • Внутренние (синхронные) прерывания. Внутреннее прерывание возникает в результате изменения или нарушения в исполнении программы (например, при обращении к недопустимому адресу, недопустимый код операции и другие).

Зачем нужны аппаратные прерывания

Аппаратные прерывания возникают в ответ на внешнее событие и исходят от внешнего аппаратного устройства. В Ардуино представлены 4 типа аппаратных прерываний. Все они различаются сигналом на контакте прерывания:

  • Контакт притянут к земле. Обработчик прерывания исполняется до тех пор, пока на пине прерывания будет сигнал LOW.
  • Изменение сигнала на контакте. В таком случае Ардуино выполняет обработчик прерывания, когда на пине прерывания происходит изменение сигнала.
  • Изменение сигнала от LOW к HIGH на контакте – при изменении с низкого сигнала на высокий будет исполняться обработчик прерывания.
  • Изменение сигнала от HIGH к LOW на контакте – при изменении с высокого сигнала на низкий будет исполняться обработчик прерывания.

Прерывания полезны в программах Ардуино, так как помогают решать проблемы синхронизации. Например, при работе с UART прерывания позволяют не отслеживать поступление каждого символа. Внешнее аппаратное устройство подает сигнал прерывания, процессор сразу же вызывает обработчик прерывания, который вовремя захватывает символ. Это позволяет экономить процессорное время, которое без прерываний тратилось бы на проверку статуса UART, вместо этого все необходимые действия выполняются обработчиком прерывания, не затрагивая главную программу. Особых возможностей от аппаратного устройства не требуется.

Основными причинами, по которым необходимо вызвать прерывание, являются:

  • Определение изменения состояния вывода;
  • Прерывание по таймеру;
  • Прерывания данных по SPI, I2C, USART;
  • Аналогово-цифровое преобразование;
  • Готовность использовать EEPROM, флеш-память.

Как реализуются прерывания в Ардуино

При поступлении сигнала прерывания работа в цикле loop() приостанавливается. Начинается выполнение функции, которая объявляется на выполнение при прерывании. Объявленная функция не может принимать входные значения и возвращать значения при завершении работы. На сам код в основном цикле программы прерывание не влияет. Для работы с прерываниями в Ардуино используется стандартная функция attachInterrupt().

Отличие реализации прерываний в разных платах Ардуино

На других платах число прерываний выше. Например, плата Ардуино Мега 2560 имеет 6 пинов, которые могут обрабатывать внешние прерывания. Для всех плат Ардуино при работе с функцией attachInterrupt (interrupt, function, mode) аргумент Inerrupt 0 связан с цифровым пином 2.

Реле

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

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

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

Внутри реле находится электромагнитная катушка, которая приводит в действие высоковольтный выключатель при протекании тока через цепь.

При отсутствии тока, проходящего через катушку, реле находится в нормально замкнутом состоянии:

Когда выключатель закрыт, ток течет через катушку, и электромагнитное поле, создаваемое катушкой, приводит к тому, что высоковольтная клемма переключается в нормально открытое положение:

При работе с индуктивными нагрузками, такими как реле, соленоиды, двигатели или шаговые двигатели, важно защитить Вашу цепь от обратного ЭДС. Обратный ЭДС возникает, когда электромагнитное поле, окружающее катушку, падает обратно в катушку

Это вызывает большой обратный ток в катушке, который может повредить другие компоненты в цепи

Обратный ЭДС возникает, когда электромагнитное поле, окружающее катушку, падает обратно в катушку. Это вызывает большой обратный ток в катушке, который может повредить другие компоненты в цепи.

Для предотвращения обратного электромагнитного поля, диод должен быть размещен параллельно катушке.

Видео. Освещение дома на Ардуино

— Для питания платы и LED ленты используется блок питания на 12 Вольт с выходным напряжением 1 Ампер. При этом общее потребление электроэнергии, если включить все освещение сразу, не превышает 15 Ватт, что сравнимо с одной энергосберегающей лампочкой. Но при этом освещение на Arduino работает в санузле (туалет совмещен с ванной), в прихожей, в коридоре на 2 этаже, в гостиной (зона отдыха и зона кухни). Для управления освещением на Arduino используется пульт от телевизора. Кроме того, что автоматическое включение подсветки в ванной и коридоре — это очень удобно, можно еще и сэкономить на оплате за электроэнергию. Также в скетче прописан цикл для создания эффекта присутствия, когда вы уезжаете из дома на несколько дней. Освещение включается и выключается в разных комнатах по заданному алгоритму.

Таймеры и реле времени

Выключатель нагрузки с ограничителем времени включенного состояния (К561ТМ2, CD4060) Для питания многих устройств применяются автономные источники питания, энергию которых нужно экономить. Кроме того нужно экономить и потребление электроэнергии от электросети, и не допускать бесполезного горения различных лампочек и ненужной работы других электроприборов. Здесь предлагается схема …

0 68 1

Таймер для отключения питания устройств с низким потреблением тока

Мультиметр, — сейчас самый популярный прибор радиолюбителя, но у него есть и недостатки. Автономное питание, это, безусловно, достоинство, но прибор очень легко забыть выключить, и тогда довольно слабая батарея 6F22 (аналог «Кроны») может быстро израсходоваться Лучшим способом избежать …

0 32 0

Цифровой лабораторный секундомер на 0,01-99 секунд (CD4060, 74C926)

Схема самодельного цифрового секундомера, который позволяет измерять временные интервалы от 0,01 секунды, до 99,99секунд. В основе прибора микросхема ММ74С926 (или другие аналоги «74С926», которая представляет собой десятичный четырехразрядный счетчик, объединенный с системой индикации …

1 629 1

Автомат для циклического обнуления или прерывания питания (CD4060)

Эта схема предназначена для циклического обнуления или прерывания питания какого-либо устройства, нуждающегося в таком действии. Собрана на микросхеме CD4060. Период прерывания (обнуления) зависит от настройки резистора R1 и может быть от одного до 4-5 часов …

0 701 0

Несложный таймер для управления нагрузкой на 220В (CD4060)

Этот таймер предназначен для ограничения продолжительности работы электроприбора. Время можно выставить от 5 минут до 90 минут. Время задается при помощи RC-цепи, переменным резистором, поэтому точность не калиброванная. Особенностью таймера является его полное отключение от электросети …

0 919 0

Электронное реле для временного включения низковольтной нагрузки

Данное устройство представляет собой реле времени, включающее низковольтную нагрузку при нажатии кнопки, и выключающее её через 1-10 минут (время устанавливается при помощи переменного резистора) после отпускания кнопки. Схема показана на рисунке. Продолжительность включенного состояния нагрузки …

1 391 0

Циклический таймер, каждые 60 минут включает нагрузку на 5 минут

Схема несложного самодельного устройства, которое через каждые 60 минут включает нагрузку на время 5 минут. Применение данного устройства может быть самое различное, например, управление скважным насосом или другим устройством, которое нужно каждый час включать на небольшое время, например …

1 755 0

Таймер для каждодневного включения нагрузки (CD4060B, CD4001)

Есть вещи, которые нужно делать каждый день, примерно, в одно и то же время. Например, включать вечером свет во дворе, и выключать его утром, или поливать цветы, кормить рыбок. Этот таймер предназначен для выполнения за человека такой работы, как включение и выключение нагрузки один раз в сутки …

1 879 1

Универсальный двоичный таймер на микросхемах CD4060B и диодах

Этот необычный таймер позволяет включать нагрузку через время,заданное с точностью до секунды, от 1 секунды до более чем 97 суток. Необычность таймера в сложности с ним обращения, и необходимости некоторых математических вычислений для задания времени (желательно как приложение к нему иметь …

0 504 0

Таймер для ограничения времени работы 12-вольтового оборудования

На рисунке показана схема автомата для ограничения времени работы оборудования. питающегося от источника постоянного тока с номинальным напряжением12V. Работа ограничителя. Ограничитель питается параллельно нагрузке. Для включения служит кнопка без фиксации Чтобы включить нагрузку нужно нажать эту …

1 578 0

1 …

Модифицированные библиотеки от Paul Stoffregen

Также доступны отдельно поддерживаемые и обновляемые копии TimerOne и TimerThree, которые отличается поддержкой большего количества оборудования и оптимизацией для получения более эффективного кода.

Плата ШИМ выводы TimerOne ШИМ выводы TimerThree
Teensy 3.1 3, 4 25, 32
Teensy 3.0 3, 4  
Teensy 2.0 4, 14, 15 9
Teensy++ 2.0 25, 26, 27 14, 15, 16
Arduino Uno 9, 10  
Arduino Leonardo 9, 10, 11 5
Arduino Mega 11, 12, 13 2, 3, 5
Wiring-S 4, 5  
Sanguino 12, 13  

Методы модифицированных библиотек аналогичны описанным выше, но добавлен еще один метод управления запуском таймера:

Возобновляет работу остановленного таймера. Новый период не начинается.

Кухонный таймер Ардуино с энкодером

Сейчас рассмотрим, как сделать таймер на Ардуино своими руками с энкодером и LCD. Принцип управления, подобен предыдущему варианту. Поворотом ручки энкодера можно задать необходимый временной интервал, а нажатием на ручку можно запускать и останавливать обратный отсчет времени. Далее размещена схема сборки проекта на Arduino Nano, этот проект можно собрать и на плате Arduino Uno.

Скетч таймера обратного отсчета времени

#include <Wire.h> // библиотека для протокола I2C #include <LiquidCrystal_I2C.h> // библиотека для LCD 1602 LiquidCrystal_I2C LCD(0x27, 20, 2); // присваиваем имя дисплею #include <RotaryEncoder.h> // библиотека для энкодера RotaryEncoder encoder(4, 2); // пины подключение энкодера (DT, CLK) // задаем шаг энкодера, максимальное и минимальное значение #define STEPS 1 #define POSMIN 0 #define POSMAX 30 int lastPos, newPos; boolean buttonWasUp = true; byte w = 0; int SEC = 0; int MIN = 0; unsigned long timer; void setup() { pinMode(6, INPUT_PULLUP); // пин для кнопки энкодера encoder.setPosition(0 / STEPS); pinMode(10, OUTPUT); // подключаем светодиод и зуммер pinMode(12, OUTPUT); digitalWrite(10, HIGH); LCD.init(); // инициализация дисплея LCD.backlight(); // включение подсветки LCD.setCursor(2, 0); LCD.print(«TIMER STOP»); LCD.setCursor(5, 1); LCD.print(MIN); LCD.print(» : «); LCD.print(SEC); } void loop() { // проверяем положение ручки энкодера encoder.tick(); newPos = encoder.getPosition() * STEPS; if (newPos < POSMIN) { encoder.setPosition(POSMIN / STEPS); newPos = POSMIN; } else if (newPos > POSMAX) { encoder.setPosition(POSMAX / STEPS); newPos = POSMAX; } // если положение изменилось — меняем переменную MIN и выводим на дисплей if (lastPos != newPos) { MIN = newPos; lastPos = newPos; LCD.clear(); LCD.setCursor(2, 0); LCD.print(«TIMER STOP»); LCD.setCursor(5, 1); LCD.print(MIN); LCD.print(» : «); LCD.print(SEC); } // если была нажата кнопка энкодера запускаем отсчет времени boolean buttonIsUp = digitalRead(6); if (buttonWasUp && !buttonIsUp && MIN > 0) { delay(10); buttonIsUp = digitalRead(6); if (!buttonIsUp) { if (SEC == 0) { SEC = 60; MIN = MIN — 1; } if (MIN < 0 ) { MIN = 0; } digitalWrite(10, LOW); w = 1; } } buttonWasUp = buttonIsUp; // запоминаем состояние кнопки while (w == 1 ) { // если прошло 995 мс — вычитаем одну секунду от переменной SEC if (millis() — timer > 993) { timer = millis(); SEC = SEC — 1; // если отсчет закончился — обнуляемся, включаем сигнал и выходим из цикла if (SEC == 0 && MIN == 0) { lastPos = 0; newPos = 0; MIN = 0; SEC = 0; LCD.clear(); LCD.setCursor(2, 0); LCD.print(«TIMER STOP»); LCD.setCursor(5, 1); LCD.print(MIN); LCD.print(» : «); LCD.print(SEC); digitalWrite(10, HIGH); tone(12, 100); delay(500); noTone(12); w = 0; } // если секунды дошли до нуля — вычитаем одну минуту if (SEC == 0 && w==1) { SEC = 59; MIN = MIN — 1; if (MIN < 0 ) { MIN = 0; } } // если из цикла while еще не вышли — выводим информацию на дисплей if (w == 1) { LCD.clear(); LCD.setCursor(2, 0); LCD.print(«TIMER START»); LCD.setCursor(5, 1); LCD.print(MIN); LCD.print(» : «); LCD.print(SEC); } } // если была нажата кнопка — обнуляем переменные и выходим из цикла buttonIsUp = digitalRead(6); if (buttonWasUp && !buttonIsUp) { delay(10); buttonIsUp = digitalRead(6); if (!buttonIsUp) { lastPos = 0; newPos = 0; MIN = 0; SEC = 0; LCD.clear(); LCD.setCursor(2, 0); LCD.print(«TIMER STOP»); LCD.setCursor(5, 1); LCD.print(MIN); LCD.print(» : «); LCD.print(SEC); digitalWrite(10, HIGH); w = 0; } } buttonWasUp = buttonIsUp; // запоминаем состояние кнопки } }

Важные страницы

  • Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макро, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту (alex@alexgyver.ru)

ДОКУМЕНТАЦИЯ

Документация

Конструктор

Класс GTimer позволяет работать как с миллисекундным, так и с микросекундным таймером. В общем виде пример выглядит так:

Где type это MS (,мс, миллисекундный таймер) или US (мкс, микросекундный), period – период в мс или мкс соответственно.

Настройки по умолчанию

  • При создании таймера можно ничего не указывать : GTimer myTimer; , тогда таймер будет сконфигурирован как миллисекундный и не запустится
  • Если указать только тип таймера (MS/US) GTimer myTimer(MS); , таймер настроится на выбранный режим (мс/мкс) и не запустится
  • Если указать тип таймера и интервал GTimer myTimer(US, 5000); , таймер настроится на выбранный режим (мс/мкс) и запустится в режиме интервала

Режимы работы

Таймер может работать в режиме интервалов и в режиме таймаута:

  • Интервалы. Запуск – метод setInterval(время) с указанием времени. В режиме интервалов таймер срабатывает (метод isReady() возвращает true) каждый раз при достижении указанного периода и автоматически перезапускается. Удобно для периодических действий
  • Таймаут. Запуск – метод setTimeout(время) с указанием времени. В режиме таймаута таймер срабатывает (метод isReady() возвращает true) только один раз при достижении указанного периода и автоматически отключается. Для повторного запуска нужно вызвать .setTimeout() с указанием периода, или просто .start() – запустит таймер на новый круг с прежним периодом

Управление таймером

Для управления состоянием таймера есть следующие методы:

  • start() – запускает (перезапускает) таймер с последним установленным временем
  • stop() – останавливает таймер
  • resume() – продолжает отсчёт таймера с момента остановки
  • reset() – сбрасывает таймер (отсчёт периода/таймаута начинается заново)
  • isEnabled() – возвращает true, если таймер работает (если он не stop() или не вышел таймаут)

Таймер с обратным отсчетом на Arduino.

https://youtube.com/watch?v=gMJ1K1JJ8TM

Ссылки на компоненты:

Часы реального времени Ds3231 – http://ali.pub/enqbc

Модуль расширителя интерфейса (I2C)- http://ali.pub/dwj5n

ЖК-дисплей LCD1602 (синий экран)- http://ali.pub/alnru

Таймер с обратным отсчетом на Arduino

Деньги можно перечислить на карту Сбербанка России:

4276 5400 2194 5088

Контроллер для сауны

Подпишитесь!

2015, Arduinoprom.ru – блог Чилингаряна Грачика. Все авторские права на тексты принадлежат ему.

При размещении текстов и видеоматериалов на сторонних ресурсах активная гиперссылка ОБЯЗАТЕЛЬНА.

Все логотипы и товарные знаки, размещенные на сайте, принадлежат только их законным владельцам (правообладателям).

Простейший вариант

Пример конструктора для самодельной сборки таймера задержки отключения:

При желании возможно самостоятельно собрать реле времени по следующей схеме:

Времязадающим элементом является конденсатор С1, в стандартной комплектации КИТ-набора он имеет следующие характеристики: 1000 мкФ/16 В, время задержки в этом случае составляет приблизительно 10 минут. Регулировка времени осуществляется переменным резистором R1. Питание платы 12 Вольт. Управление нагрузкой производится через контакты реле. Плату можно не делать, а собрать на макетной плате или навесным монтажом.

Для того, чтобы сделать реле времени, нам понадобятся следующие детали:

Правильно собранное устройство не нуждается в настройке и готово к работе. Данное самодельное реле задержки времени было описано в журнале «Радиодело» 2005.07.

Минимальные частоты и разрядность таймеров

Варианты вызовов timer_init_ISR_2Hz (2Гц, период 500мс) и timer_init_ISR_1Hz (1Гц, период 1с) на PIC32MX 80МГц будут работать только с 32-битными таймерами (_TIMER2_32BIT и _TIMER4_32BIT; TIMER_DEFAULT — по умолчанию = _TIMER4_32BIT), т.к. при 16-битных режимах таймеров PIC32MX 80МГц комбинация «делитель частоты» (prescaler — максимальный вариант 1/256) + «поправка периода» (adjustment — максимальный вариант 2^16=65536-1) дают минимальную частоту 5Гц (период — 200мс):
80000000/256/65536 = 4.8Гц

На PIC32 32-битные таймеры создаются комбинацией 2х 16-битных таймеров:

  • Timer4(32бит) = Timer4(16бит)+Timer5(16бит)
  • Timer2(32бит) = Timer2(16бит)+Timer3(16бит)

поэтому при использовании таймера _TIMER2_32BIT, обычные таймеры _TIMER2 и _TIMER3 будут заняты, при использовании _TIMER4_32BIT — заняты будут _TIMER4 и _TIMER5.

На AVR/Arduino можно получить частоту 1Гц стандартными делителями на 16-битном таймере.

На SAM/Arduino Due все таймеры 32-битные.

Тип данных для параметра adjustment — unsigned int.

  • На PIC32 разрядность int — 32 бит, этого хватит и для 16-тибитного режима таймера (если не закладывать значение более 2^16=65536-1) и для 32-битного (пойдет любое значение до 2^32=4294967296-1).
  • На SAM разрядность int — 32 бит, все таймеры 32-битные.
  • На AVR разрядность int — 16 бит, это опять же, как раз достаточно для 16-битных таймеров.

Таким образом, хотя разрядность параметра adjustment с типом int будет разной на разных платформах, во всех случаях значение будет соответствовать аппаратным свойствам таймеров.

Сборка

При реализации проекта я столкнулся с двумя основными трудностями:

  • Как определить, работает ли помпа, чтобы знать, когда начинать и заканчивать отсчет.
  • Как коммутировать 170В на 20 анодов (по 10 на каждую лампу).

Так как делал я все это ради удовольствия, то решил дать волю инженерной мысли. Мне захотелось выяснить, удастся ли обнаружить магнитное поле помпы, чтобы определять момент готовности шота. Это бы также позволило обойтись без лишних вмешательств в машину – эдакий своеобразный малоинвазивный подход. В довершение ко всему, один близкий друг предоставил свою мастерскую и дал некоторые дельные советы, посодействовав в сборке удачного корпуса. Еще раз спасибо, Нилс!

Кухонный таймер Ардуино с энкодером

Сейчас рассмотрим, как сделать таймер на Ардуино своими руками с энкодером и LCD. Принцип управления, подобен предыдущему варианту. Поворотом ручки энкодера можно задать необходимый временной интервал, а нажатием на ручку можно запускать и останавливать обратный отсчет времени. Далее размещена схема сборки проекта на Arduino Nano, этот проект можно собрать и на плате Arduino Uno.

Скетч таймера обратного отсчета времени

#include <Wire.h>                              // библиотека для протокола I2C
#include <LiquidCrystal_I2C.h>        // библиотека для LCD 1602 
LiquidCrystal_I2C LCD(0x27, 20, 2);  // присваиваем имя дисплею

#include <RotaryEncoder.h>                // библиотека для энкодера
RotaryEncoder encoder(4, 2);       // пины подключение энкодера (DT, CLK)

// задаем шаг энкодера, максимальное и минимальное значение
#define STEPS  1
#define POSMIN 0
#define POSMAX 30

int lastPos, newPos;
boolean buttonWasUp = true;

byte w = 0;

int SEC = 0;
int MIN = 0;
unsigned long timer;

void setup() {
   pinMode(6, INPUT_PULLUP);   // пин для кнопки энкодера
   encoder.setPosition(0 / STEPS);

   pinMode(10, OUTPUT);   // подключаем светодиод и зуммер
   pinMode(12, OUTPUT);
   digitalWrite(10, HIGH);

   LCD.init();                        // инициализация дисплея
   LCD.backlight();              // включение подсветки

   LCD.setCursor(2, 0);
   LCD.print("TIMER  STOP");
   LCD.setCursor(5, 1);
   LCD.print(MIN);
   LCD.print(" : ");
   LCD.print(SEC);
}

void loop() {

   // проверяем положение ручки энкодера
   encoder.tick();
   newPos = encoder.getPosition() * STEPS;
   if (newPos < POSMIN) {
      encoder.setPosition(POSMIN / STEPS);
      newPos = POSMIN;
   }
   else if (newPos > POSMAX) {
      encoder.setPosition(POSMAX / STEPS);
      newPos = POSMAX;
   }

   // если положение изменилось - меняем переменную MIN и выводим на дисплей
   if (lastPos != newPos) {
      MIN = newPos;
      lastPos = newPos;
      LCD.clear();
      LCD.setCursor(2, 0);
      LCD.print("TIMER  STOP");
      LCD.setCursor(5, 1);
      LCD.print(MIN);
      LCD.print(" : ");
      LCD.print(SEC);
   }

   // если была нажата кнопка энкодера запускаем отсчет времени
   boolean buttonIsUp = digitalRead(6);
   if (buttonWasUp && !buttonIsUp && MIN > 0) {
      delay(10);
      buttonIsUp = digitalRead(6);
      if (!buttonIsUp) {
         if (SEC == 0) { SEC = 60; MIN = MIN - 1; }
         if (MIN < 0 ) { MIN = 0; }
         digitalWrite(10, LOW);
         w = 1;
      }
   }
   buttonWasUp = buttonIsUp; // запоминаем состояние кнопки

   while (w == 1 ) {
      // если прошло 995 мс - вычитаем одну секунду от переменной SEC
      if (millis() - timer > 993) {
         timer = millis();
         SEC = SEC - 1;
 
      // если отсчет закончился - обнуляемся, включаем сигнал и выходим из цикла
      if (SEC == 0 && MIN == 0) {
         lastPos = 0; newPos = 0; MIN = 0; SEC = 0;
         LCD.clear();
         LCD.setCursor(2, 0);
         LCD.print("TIMER  STOP");
         LCD.setCursor(5, 1);
         LCD.print(MIN);
         LCD.print(" : ");
         LCD.print(SEC);
         digitalWrite(10, HIGH);
         tone(12, 100);
         delay(500);
         noTone(12);
         w = 0;
      }

      // если секунды дошли до нуля - вычитаем одну минуту
      if (SEC == 0 && w==1) {
         SEC = 59; MIN = MIN - 1;
         if (MIN < 0 ) { MIN = 0; }
      }

      // если из цикла while еще не вышли - выводим информацию на дисплей
      if (w == 1) {
         LCD.clear();
         LCD.setCursor(2, 0);
         LCD.print("TIMER START");
         LCD.setCursor(5, 1);
         LCD.print(MIN);
         LCD.print(" : ");
         LCD.print(SEC);
      }
    }

    // если была нажата кнопка - обнуляем переменные и выходим из цикла
    buttonIsUp = digitalRead(6);
    if (buttonWasUp && !buttonIsUp) {
       delay(10);
       buttonIsUp = digitalRead(6);
       if (!buttonIsUp) {
          lastPos = 0; newPos = 0; MIN = 0; SEC = 0;
          LCD.clear();
          LCD.setCursor(2, 0);
          LCD.print("TIMER  STOP");
          LCD.setCursor(5, 1);
          LCD.print(MIN);
          LCD.print(" : ");
          LCD.print(SEC);
          digitalWrite(10, HIGH);
          w = 0;
       }
    }
    buttonWasUp = buttonIsUp; // запоминаем состояние кнопки
  }
}

Пояснения к коду:

  1. частоту звукового сигнала можно изменить через команду tone();
  2. для скетча потребуется установить библиотеку RotaryEncoder.

Резюме

Платформа Arduino предоставляет нам несколько способов выполнения задержки в своем проекте. С помощью delay вы можете быстро поставить на паузу выполнение скетча, но при этом заблокируете работу микроконтроллера. Использование команды millis позволяет обойтись в ардуино без delay, но для этого потребуется чуть больше программировать. Выбирайте лучший способ в зависимости от сложности вашего проекта. Как правило, в простых скетчах и при задержке меньше 10 секунд используют delay. Если логика работы сложнее и требуется большая задержка, то вместо delay лучше использовать millis.

«>