Прерывания arduino с помощью attachinterrupt

Library Reference

You should know:

  • — Get the first available Timer.

  • — Attach a interrupt (callback function) for the timer of the object.

  • — Detach current callback of timer.

  • — Start the timer with an optional period parameter.

  • — Stop the timer

  • — Set the timer frequency

  • — Get the timer frequency

  • — Set the timer period (in microseconds)

  • — Get the timer period (in microseconds)

You don’t need to know:

<<<<<<< HEAD

  • — Stores the object timer id (to access Timers struct array).

  • — Instantiate a new DueTimer object for Timer _timer (NOTE: All objects are already instantiated!).

  • — Stores all timers information

  • — Stores all callbacks for all timers

Hardware Information

More information on the Timer Counter module of the µC on the Arduino Due
can be found in the documentation file TimerCounter.

Ардуино задержка включения / выключения

Для этого занятия нам потребуется:

плата Arduino Uno / Arduino Nano / Arduino Mega.

В этой записи мы рассмотрим только основные характеристики функций задержки, а примеры использования представим в виде небольших скетчей. Для работы вам потребуется только сама плата Ардуино. Начнем обзор с delayMicroseconds Arduino, т.к. данную функцию не часто можно встретить в программах, а также рассмотрим, как заменить задержку delay на millis в программировании Arduino IDE.

Ардуино delayMicroseconds()

Команда delayMicroseconds останавливает выполнение программы на заданное количество микросекунд (в 1 секунде 1 000 000 микросекунд). При необходимости задержки в программе более чем на несколько тысяч микросекунд рекомендуется использовать delay(). Продемонстрируем на простом примере использование функции в скетче для мигания встроенным светодиодом на плате Arduino.

// пример использования delayMicroseconds() для мигания светодиодом
void setup() {
   pinMode(13, OUTPUT);
}
 
void loop() {
   digitalWrite(13, HIGH);      // подаем сигнал HIGH на выход
   delayMicroseconds(100);  // задержка 100 микросекунд
   digitalWrite(13, LOW);       // подаем сигнал LOW на выход
   delayMicroseconds(100);  // задержка 100 микросекунд
}

Ардуино delay()

Команда delay останавливает выполнение программы на заданное количество миллисекунд (в 1 секунде 1 000 миллисекунд). Во время задержки программы с помощью функции delay(), не могут быть считаны подключенные к плате датчики или произведены другие операции, например, запись в еепром Ардуино данных. В качестве альтернативы следует использовать функцию millis(). Смотри пример далее.

// пример использования delay() для мигания светодиодом
void setup() {
   pinMode(13, OUTPUT);
}
 
void loop() {
   digitalWrite(13, HIGH);   // подаем сигнал HIGH на выход
   delay(100);                        // задержка 100 миллисекунд
   digitalWrite(13, LOW);    // подаем сигнал LOW на выход
   delay(100);                        // задержка 100 миллисекунд
}

Ардуино millis()

Команда millis возвращает количество прошедших миллисекунд с момента начала выполнения программы. Счетчик времени сбрасывается на ноль при переполнении значения unsigned long (приблизительно через 50 дней). Функция miilis позволяет сделать многозадачность Ардуино, так как выполнение программы не останавливается и можно выполнять параллельно другие операции в скетче.

// пример использования millis() при мигании светодиодом
unsigned long timer;

void setup() {
   pinMode(13, OUTPUT);
   Serial.begin(9600);         // запускаем монитор порта
}
 
void loop() {
   timer = millis();                 // запускаем отсчет времени

   digitalWrite(13, HIGH);   // подаем сигнал HIGH на выход
   delay(1000);                      // задержка 1 секунда
   digitalWrite(13, LOW);    // подаем сигнал LOW на выход
   delay(1000);                      // задержка 1 секунда

   // выводим количество миллисекунд прошедших с момента начала программы
   Serial.print("Time: ");
   Serial.println(timer);
}

Arduino команды millis, delay, delaymicroseconds

Модифицированные библиотеки от 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  

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

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

Автоматическое освещение на базе Arduino


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


Материалы и инструменты для самоделки: — контроллер Arduino Nano; — текстолитовые макетки; — датчики движения; — источник питания 5В; — реле; — паяльник с припоем; — провода; — материалы для изготовления корпуса электроники (оргстекло); — напильник.


Процесс изготовления:

Шаг первый. Доработка и установка реле

Сперва вся схема собирается и тестируется на бредборде. Все отлично заработало, для регулировки чувствительности к свету был добавлен потенциометр. Но при установке всех элементов на плату возникла небольшая проблема. Реле оказалось слишком большим и не влезало на макетку. В связи с этим нужно было немного доработать его напильником. Так как ни контактов ни дорожек там не было, то с этим проблем не возникло. Еще возникла проблема с пайкой контактов реле, их пришлось перенести на другую сторону. Что же в итоге получилось можно увидеть на фото. Самым сложным, по словам автора, было сделать дорожки на плате. Для этих целей используется тоненькая проволока, флюс и олово. Получилось все довольно грубо, но в качестве эксперимента все сделано отлично. В итоге все прекрасно поместилось на плате размером 5х7 см. Плюсом платы стало то, что на ней есть отверстия, которые можно использовать при креплении корпуса из оргстекла.

Шаг второй. Пару слов о датчике движения Автор не делал датчик движения фиксированным, поскольку была идея сделать его на «рожках», это позволит менять его направление при необходимости. Также пока однозначно не решено, где именно будет крепиться прибор. Особенность датчика в том, что при первом запуске ему надо дать время порядка 10-30 секунд. За это время он сам настроиться, произведет калибровку и будет работать как надо. В принципе, этот момент не так важен.Шаг третий. Прошивка электроники Прошивка собрана из кусков различных «туториалов» для датчиков. Работает электроника очень просто, когда датчик обнаруживает движение, идет сравнивание показателей фоторезистора с пороговым значением, которое необходимо для срабатывания реле. Это значение регулируется с помощью потенциометра. Если все требования соблюдены, реле включается на три минуты, можно задать и другой временной промежуток. Далее, если движения нет, то система отключает свет.

Чтобы проверить пороговые значения фоторезистора он был закрыт пальцем и затем автор направил на него фонарик мощностью в 2000 люмен.


В общей сложности с учетом праздников и помощи надежного коллеги — кота, на всю сборку было затрачено порядка 12-15 часов. Для работы системы достаточно источника питания в 4 Ватта, автору он обошелся в 200 рублей.

Подключается система тоже очень просто. Достаточно подключить освещение через реле и подать на электронику через источник питание в 5В.

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

Естественно важно продумать, где установить датчик движения

avtomaticheskoe-osveschenie.rar (скачиваний: 644)

Источник (Source)

Становитесь автором сайта, публикуйте собственные статьи, описания самоделок с оплатой за текст. Подробнее здесь.

Откуда берётся время?

Начнём с того, откуда вообще микроконтроллер знает, сколько проходит времени. Ведь у него нет часов! Для работы микроконтроллера жизненно важен так называемый тактовый генератор, или кварцевый генератор, или он же кварц. Он же oscillator, он же clock. Clock по-английски это часы. Да, но не всё так просто =) Кварц расположен рядом с МК на плате (также во многих МК есть встроенный тактовый генератор), на Ардуинах обычно стоит кварц на 16 МГц, также встречаются модели на 8 МГц. Кварц выполняет очень простую вещь: он пинает микроконтроллер со своей тактовой частотой, то есть 16 МГц кварц пинает МК 16 миллионов раз в секунду. Микроконтроллер, в свою очередь зная частоту кварца, может прикинуть время между пинками (16 МГц = 0.0625 микросекунды), и таким образом ориентироваться во времени. Но на деле не всё так просто, потому что принимают пинки таймера так называемые таймеры-счётчики (Timer-counter). Это физически расположенные внутри МК устройства, которые занимаются подсчётом пинков тактового генератора. И вот микроконтроллер уже может обратиться к счётчику и спросить, а сколько там натикало? И счётчик ему расскажет. И вот этим мы уже можем пользоваться, для этого у Ардуино есть готовые функции времени. В Ардуино на МК 328 имеются три счётчика, и подсчётом времени занимается таймер под номером 0. Этим может заниматься любой другой счётчик, но работая в Arduino IDE вы сразу получаете такую настройку, т.к. создавая скетч в Arduino IDE вы автоматически работаете с библиотекой Arduino.h, где и реализованы все удобные функции.

Работа проекта

Принцип работы проекта достаточно прост. После запуска программы на экране ЖК дисплея высветится надпись “Arduino Timer” и она будет гореть до тех пор пока вы не нажмете кнопку. После нажатия кнопки программа попросит вас ввести время, с которого начнется обратный отсчет, при помощи вызова функции “setFeedingTime”. Время вводится с помощью клавиатуры. После ввода времени необходимо нажать клавишу ‘D’ на клавиатуре чтобы сохранить введенное время и начать обратный отсчет.

Далее в функции loop() мы будем выполнять ряд вычислений чтобы осуществить уменьшение счета (секунда за секундой) и показывать на ЖК дисплее оставшееся до истечения таймера время в формате HH:MM:SS. Более подробно все эти процессы показаны на видео, приведенном в конце статьи.

Когда таймер обратного отсчета достигнет нуля зуммер начнет издавать звуки (100 раз если его не прервать). Чтобы остановить сигнал зуммера необходимо нажать и удерживать кнопку. Также нажать кнопку можно в любое время если вы хотите остановить таймер.

Схема таймера на двух транзисторах

Нетрудно собрать реле времени своими руками на двух транзисторах. Оно начинает работать, если подать питание на конденсатор С1, после чего начнется его зарядка. При этом ток базы открывает транзистор VT1. Вслед за ним откроется VT2, и электромагнит замыкает контакт, подавая питание на светодиод. По его свечению будет видно, что сработало реле времени. Схема обеспечивает переключение нагрузки R4.

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

Повторный запуск устройства происходит, если нажать кнопку SB1, а затем ее отпустить. При этом конденсатор разрядится и процесс повторится.

Работа начинается, когда на реле времени 12 В подается питание. Для этого могут применяться автономные источники. При питании от сети к таймеру подключается блок питания, состоящий из трансформатора, выпрямителя и стабилизатора.

Таймер

Диапазон таймера можно регулировать вверх или вниз от 14400 с помощью переменной задержки.

Максимальное время ожидания составляет примерно 4 часа. Также можно настроить уровень освещенности, при котором срабатывает реле. Изначально значение переменной (яркость) было установлено на 5, но при повышении этого значения свет будет активироваться при более высоком уровне освещенности.

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

Тайминг основан на функции задержки, которая работает в миллисекундах. Потенциометр времени представляет аналоговый вход, считанный в переменную .

Затем он преобразуется с помощью функции » map » в диапазон от 0 до 100. Вы можете попробовать варьировать диапазон до (0-50) с помощью этого кода:

или (0-250) с помощью этого:

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

Прерывания в языке 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).

Реле времени на КМОП коммутаторе

Помимо транзисторов и тиристоров для управления нагрузкой довольно широко используют КМОП-коммутаторы. Такого рода коммутаторы выполнены в микросхемном исполнении на полевых транзисторах.

Их положительное качество — высокое быстродействие, малые габариты, высокая надежность. К недостаткам следует отнести низкую нагрузочную способность (ток нагрузки канала коммутации обычно не должен превышать 10 мА), а также высокую чувствительность к помехам.

Ключевой элемент КМОП-коммутатора включается при подаче на управляющий электрод напряжения «высокого» уровня и отключается при подаче «низкого». Сопротивление ключа во включенном состоянии состовляет несколько десятков Ом; в разомкнутом — превышает сотни МОм.

КМОП-коммутаторы могут быть использованы в качестве промежуточных элементов управления других коммутирующих устройств (транзисторов, реле, оптоэлектронных приборов и т.п.).

Рис. 5. Схема реле времени на КМОП-коммутаторе К561КТ3.

На рис. 5 показана схема КМОП-коммутатора на одном из четырех равнозначных элементов микросхемы К561КТЗ .

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

Коммутирующий элемент (выводы 1, 2) разомкнут, ток через сопротивление нагрузки не протекает. Конденсатор С1 через нормально замкнутый контакт кнопки SB1 заряжен до напряжения питания устройства.

Если кратковременно нажать на кнопку SB1, конденсатор С1 оказывается подключенным к управляющему электроду (вывод 13) микросхемы. Канал коммутатора включается.

Через резистор R3 напряжение высокого уровня поступает на управляющий электрод, фиксируя и поддерживая включенное состояние коммутатора.

Если кнопку SB1 оставить нажатой более продолжительное время, то конденсатор С1 разрядится через резистор R1. Напряжение на управляющем электроде микросхемы снизится до «низкого» уровня, произойдет самовыключение коммутатора.

Динамику процесса включения — выключения КМОП-коммутатора иллюстрируют диаграммы, приведенные на рис. 6. Устройство (рис. 5) можно использовать и для формирования импульсов заданной длительности.

Рис. 6. Динамику процесса включения — выключения КМОП-коммутатора.

Примечание. Для подачи питания на микросхему ее вывод 14 (см. Приложение) соединяют с плюсовой шиной питания, вывод 7 — с общей шиной. Незадействованные выводы входов управления рекомендуется соединить с шиной питания или общей шиной напрямую либо через резистор сопротивлением 1 МОм.

Рис. 7. Схема замены переключателя КМОП-коммутаторами.

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

Этот переключатель является аналогом тумблера, позволяющего, например, изменять полярность питающего напряжения. В то же время число коммутируемых цепей может быть увеличено включением дополнительных КМОП-коммутаторов.

В устройстве (рис. 7) управление коммутацией сигналов можно производить переключателем SA1, либо КМОП- или транзисторным коммутатором (рис. 8, 9).

Рис. 8. Схема для получения управляющего сигнала, выполненная на транзисторе.

Рис. 9. Схема для получения управляющего сигнала, выполненная на К561КТ3.

Управляющие сигналы «0/1» и »1/0» подаются со схем (рис. 8, 9) на соответствующие цепи управления, обозначенные на схеме рис. 7 крестиками.

Простой вариант скетча управления реле

Схема подключения

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

Скетч для работы с реле

/*
 * Скетч для управления реле с помощью ардуино
 * Используем реле SONGLE SRD-05VDC
 * Реле ОТКРЫВАЕТСЯ при подаче низкого уровня сигнала (LOW) на управляющий пин.
 * Реле ЗАКРЫВАЕТСЯ при подаче высокого уровня сигнала (HIGH) на управляющий пин.
 * 
 * В данном примере мы просто открываем и закрываем реле раз в 5 секунд.
 * 
 * PIN_RELAY содержит номер пина, к которому подключено реле, которым мы будем управлять 
 * 
 * В функции setup устанавливаем начальное положение реле (закрытое)
 * Если к реле будет подключена нагрузка(например, лампочка), то после запуска скетча она будет включаться и выключаться каждые 5 секунд
 * 
 * Для изменения периода мигания нужно изменить параметр функции delay(): поставив 1000 миллисекунд, выполучите 1 секунду задержки
 * 
 * В реальных проектах реле включается в ответ на обнаружение каких-либо внешних событий через подключение датчиков 
 * 
 */

#define PIN_RELAY 5 // Определяем пин, используемый для подключения реле

// В этой функции определяем первоначальные установки
void setup()
{
  pinMode(PIN_RELAY, OUTPUT); // Объявляем пин реле как выход
  digitalWrite(PIN_RELAY, HIGH); // Выключаем реле - посылаем высокий сигнал
}
void loop()
{
  digitalWrite(PIN_RELAY, LOW); // Включаем реле - посылаем низкий уровень сигнала
  delay(5000);
  digitalWrite(PIN_RELAY, HIGH); // Отключаем реле - посылаем высокий уровень сигнала
  delay(5000);
}

Базовые вызовы

/**
 * Init ISR (Interrupt service routine) for the timer and start timer.
 * 
 * General algorithm
 * http://www.robotshop.com/letsmakerobots/arduino-101-timers-and-interrupts
 * 1. CPU frequency 16Mhz for Arduino
 * 2. maximum timer counter value (256 for 8bit, 65536 for 16bit timer)
 * 3. Divide CPU frequency through the choosen prescaler (16000000 / 256 = 62500)
 * 4. Divide result through the desired frequency (62500 / 2Hz = 31250)
 * 5. Verify the result against the maximum timer counter value (31250 < 65536 success).
 *    If fail, choose bigger prescaler.
 * 
 * Example: to set timer clock period to 20ms (50 operations per second == 50Hz)
 * 
 * 1) on 16MHz CPU (AVR Arduino)
 *   use prescaler 1:8 (TIMER_PRESCALER_1_8) and adjustment=40000-1:
 *   16000000/8/50=40000, minus 1 cause count from zero.
 * 
 * 2) on 80MHz CPU (PIC32MX ChipKIT)
 *   use prescaler 1:64 (TIMER_PRESCALER_1_64) and adjustment=25000-1:
 *   80000000/64/50=25000, minus 1 cause count from zero.
 *
 * 3) on 84MHz CPU (SAM Arduino Due)
 *   use prescaler 1:128 (TIMER_PRESCALER_1_128) and adjustment=13125-1:
 *   80000000/128/50=13125, minus 1 cause count from zero.
 * 
 * Timer interrupt handler timer_handle_interrupts would be called every 20ms
 * (50 times per second == 50Hz freq) in this case.
 * 
 * @param timer
 *   system timer id: use TIMER_DEFAULT for default timer
 *   or _TIMER1...TIMER9, _TIMER1_32BIT..._TIMER9_32BIT for specific timer.
 *   note: availability of specific timer depends on the platform.
 * @param prescaler
 *   timer prescaler (1, 2, 4, 8, 16, 32, 64, 128, 256, 1024),
 *   use constants: PRESCALER_1_1, PRESCALER_1_2, PRESCALER_1_8,
 *   PRESCALER_1_16, PRESCALER_1_32, PRESCALER_1_64, PRESCALER_1_128
 *   PRESCALER_1_256, PRESCALER_1_1024
 *   note: availability of specific prescaler depends on the platform.
 * @param adjustment
 *   adjustment divider after timer prescaled - timer compare match value.
 */
void timer_init_ISR(int timer, int prescaler, int adjustment);

/**
 * Stop ISR (Interrupt service routine) for the timer.
 * 
 * @param timer
 *     system timer id for started ISR
 */
void timer_stop_ISR(int timer);

/**
 * Timer ISR (Interrupt service routine) handler.
 * Implementation must be provided in module with user code.
 * 
 * @param timer
 *     system timer id for started ISR 
 */
void timer_handle_interrupts(int timer);

Встроенные варианты частот

/**
 * freq: 500KHz = 500000 ops/sec
 * period: 1sec/500000 = 2us
 */
void timer_init_ISR_500KHz(int timer);

/**
 * freq: 200KHz = 200000 ops/sec
 * period: 1sec/200000 = 5us
 */
void timer_init_ISR_200KHz(int timer);s

/**
 * freq: 100KHz = 100000 ops/sec
 * period: 1sec/100000 = 10us
 */
void timer_init_ISR_100KHz(int timer);

/**
 * freq: 50KHz = 50000 ops/sec
 * period: 1sec/50000 = 20us
 */
void timer_init_ISR_50KHz(int timer);

/**
 * freq: 20KHz = 20000 ops/sec
 * period: 1sec/20000 = 50us
 */
void timer_init_ISR_20KHz(int timer);

/**
 * freq: 10KHz = 10000 ops/sec
 * period: 1sec/10000 = 100us
 */
void timer_init_ISR_10KHz(int timer);

/**
 * freq: 5KHz = 5000 ops/sec
 * period: 1sec/5000 = 200us
 */
void timer_init_ISR_5KHz(int timer);

/**
 * freq: 2KHz = 2000 ops/sec
 * period: 1sec/2000 = 500us
 */
void timer_init_ISR_2KHz(int timer);

/**
 * freq: 1KHz = 1000 ops/sec
 * period: 1sec/1000 = 1ms
 */
void timer_init_ISR_1KHz(int timer);

/**
 * freq: 500Hz = 500 ops/sec
 * period: 1sec/500 = 2ms
 */
void timer_init_ISR_500Hz(int timer);

/**
 * freq: 200Hz = 200 ops/sec
 * period: 1sec/200 = 5ms
 */
void timer_init_ISR_200Hz(int timer);

/**
 * freq: 100Hz = 100 ops/sec
 * period: 1sec/100 = 10ms
 */
void timer_init_ISR_100Hz(int timer);

/**
 * freq: 50Hz = 50 ops/sec
 * period: 1sec/50 = 20ms
 */
void timer_init_ISR_50Hz(int timer);

/**
 * freq: 20Hz = 20 ops/sec
 * period: 1sec/20 = 50ms
 */
void timer_init_ISR_20Hz(int timer);

/**
 * freq: 10Hz = 10 ops/sec
 * period: 1sec/10 = 100ms
 */
void timer_init_ISR_10Hz(int timer);

/**
 * freq: 5Hz = 5 ops/sec
 * period: 1sec/5 = 200ms
 */
void timer_init_ISR_5Hz(int timer);

/**
 * freq: 2Hz = 2 ops/sec
 * period: 1sec/2 = 500ms
 */
void timer_init_ISR_2Hz(int timer);

/**
 * freq: 1Hz = 1 ops/sec
 * period: 1sec
 */
void timer_init_ISR_1Hz(int timer);

Выбор таймера

На всех платформах доступно значение TIMER_DEFAULT, которое указывает на рабочий таймер по умолчанию.

Если есть необходимость использовать другой таймер, можно указать его имя напрямую: _TIMER1…TIMER9, _TIMER1_32BIT…_TIMER9_32BIT

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

Доступные таймеры:

  • AVR ATmega1280, ATmega2560: _TIMER1, _TIMER3,_TIMER4, _TIMER5; TIMER_DEFAULT = _TIMER5

  • AVR AT90USB646, AT90USB1286, ATmega128, ATmega1281, ATmega1284, ATmega1284P, AVR_ATmega2561: _TIMER1, _TIMER3; TIMER_DEFAULT = _TIMER3

  • AVR ATmega32U4: _TIMER1; TIMER_DEFAULT = _TIMER1

  • AVR другие чипы: _TIMER1; TIMER_DEFAULT = _TIMER1

  • PIC32 (ChipKIT): _TIMER1, _TIMER2, _TIMER3, _TIMER4, _TIMER5, _TIMER2_32BIT, _TIMER4_32BIT; TIMER_DEFAULT = _TIMER4_32BIT

  • SAM (Arduino Due): _TIMER1/_TIMER1_32BIT, _TIMER2/_TIMER2_32BIT, _TIMER3/_TIMER3_32BIT, _TIMER4/_TIMER4_32BIT, _TIMER5/_TIMER5_32BIT, _TIMER6/_TIMER6_32BIT, _TIMER7/_TIMER7_32BIT, _TIMER8/_TIMER8_32BIT, _TIMER9/_TIMER9_32BIT (все таймеры 32-битные, _TIMERX_32BIT == _TIMERX); TIMER_DEFAULT = _TIMER3/_TIMER3_32BIT;

Library Reference

  • — Constructor

  • — Destructor

  • — Starts the timer

  • — Stops and resets the timer

  • — Pauses the timer. It can continue where it paused after calling start method

  • — Resets the timer elapsed time. If the timer is running, it will continue to do so

  • — Returns the elapsed time in milliseconds

  • — Sets the interval time. The callback function will be called every «interval» ms. The repeat count will prevent the callback from being called after a number of repetetions (if it’s > 0). WARNING: The timer will stop after that (if repeat count > 0)

  • — Sets the timeout time. The callback function will be called just once. WARNING: The timer will stop after that

  • — Removes the interval, so the timer can be used as a normal timer

  • — Sets the callback function

  • — Updates the timer. It must be called in a loop in order to make it work

  • — Check if the timer is paused

  • — Check if the timer is stopped

  • — Check if the timer is running

  • protected — Calls the callback function

  • private — Stores the start time

  • private — Stores the current time

  • private — Stores if the timer is running

  • private — Stores if the timer is paused

  • private — Stores the interval, if setted

  • private — Stores the last time the callback was called

  • private — Stores the number of times remaining to call the callback function

  • private — Stores the number of times to call the callback function

  • private — Stores if the interval was setted

  • private — Stores the callback function

  • — Constructor

  • — Calls the callback method

  • private — Stores the object to be used

  • private — Stores the method to be called

  • — Get the TimerManager instance
  • — Updates all timers
  • — Starts all timers
  • — Stops and resets all timers
  • — Pauses all timers
  • — Resets elapsed time of all timers. If any timer was running, it will continue to do so
  • private — Adds a timer to the TimerManager
  • private — Removes a timer from the TimerManager. Return true if the timer was removed, false otherwise
  • private — Constructor
  • private — Constructor
  • private — Copy operator
  • private — A node of Timers used to implement a simple linked list
  • private — A pointer to the first TimerNode
  • private — A pointer to the last TimerNode

Проблемы с контекстом прерываний

Для обмена данными между кодом обработчика прерывания и остальной частью вашей программы необходимо принять дополнительные меры.

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

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

Задержки

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

  • delay(time) – “Приостанавливает” выполнение кода на time миллисекунд. Дальше функции delay выполнение кода не идёт, за исключением прерываний. Использовать рекомендуется только в самых крайних или тех случаях, когда delay не влияет на скорость работы устройства. time принимает тип данных unsigned long и может приостановить выполнение на срок от 1 мс до

50 суток (4 294 967 295 миллисекунд) с разрешением в 1 миллисекунду. Работает на системном таймере Timer 0delayMicroseconds(time) – Аналог delay(), приостанавливает выполнение кода на time микросекунд. time принимает тип данных unsigned long и может приостановить выполнение на срок от 4 мкс до

70 минут (4 294 967 295 микросекунд) с разрешением 4 микросекунды. Работает на системном таймере Timer 0

Задержки использовать очень просто:

И вот мы можем делать какое-то действие два раза в секунду. А что делать, если нам нужно выполнять одно действие два раза в секунду, а другое – три? А третье – 10 раз в секунду например. Сразу привыкаем к той мысли, что задержки лучше вообще не использовать в реальном коде. Разве что delayMicroseconds, он бывает нужен для генерации каких-то протоколов связи. Нормальным инструментом для тайм-менеджмента своего кода являются функции, которые считают время со старта МК.