Функция таймер ардуино

Arduino.ru

Использование прерываний в Arduino (продолжение)

Таймеры на Arduino

Я связался с Дэвидом Меллисом (David Mellis) из команды разработчиков Arduino и узнал, что Arduino пользуется всеми тремя таймерами ATMega168.

  • Tаймер 0 (Системное время, ШИМ 5 and 6)
    Используется для хранения счетчика времени работы программы. Функция millis() возвращает число миллисекунд с момента запуска программы, используя ISR глобального приращения таймера 0. Таймер 0 также используется для реализации ШИМ на выводах 5 и 6.
  • Tаймер 1 (ШИМ 9 и 10)
    Используется для реализации ШИМ для цифровых выводах 9 и 10.
  • Tаймер 2 (ШИМ 3 и 11)
    Используется для управления выходами ШИМ для цифровых выводов 3 и 11.

Хотя все таймеры используются, только Tаймер 0 имеет назначенную таймеру ISR. Это означает, что мы можем захватить Таймер 1 и/или Таймер2 под свои нужды. Однако в результате вы не сможете использовать ШИМ на некоторых портах ввода-вывода. Если вы планируете использовать ШИМ, имейте это ввиду. Я выбрал использование Таймера 2, что окажет влияние на выводы 3 и 11.

Моя тестовая программа полностью отключила вывод ШИМ на цифровые выводы, управляемые с таймера 2. Я подозреваю, что библиотека функций ШИМ рассчитана на работу счетчика в заданном диапазоне, который я превысил. Функция захвата сравнивает загруженные значения, и значения моего таймера просто не будут понятны для ШИМ.

Дэвид Меллис дал мне эту ссылку для изучения того, как библиотечные программы используют таймеры. Она хорошо документирована и я уверен, что она сослужит мне хорошую службу в будущем. В будущих экспериментах я планирую управлять ШИМ-модуляцией напрямую, чтобы достичь намного большей частоты, чем нормальная. Высокочастотный ШИМ может здорово пригодиться для функции аудио-ЦАП.
Ссылки, относящиеся к прерываниям в Arduino.

Здесь приведены несколько ссылок (англ.), относящихся к прерываниям на Arduino. Я просмотрел некоторые из них, пока забавлялся с прерываниями. Я должен признать, что мои познания – заслуга этих авторов.

Тексты программ

Программы, приведенные в этой статье, доступны в zip-архиве.

Установка Таймера 2

Приведенная ниже программа показывает созданную мной функцию установки Таймера 2. Эта функция подключает прерывание по переполнению Таймера 2, устанавливает предварительно заданный масштаб для таймера подсчитывает загружаемое значение таймера, дающее желаемую частоту прерываний по времени. Эта программа основана на программе, найденной мной по вышеуказанным ссылкам. Я приобрел опыт, читая спецификации AVR, однако гораздо проще повторно использовать программу, если вы можете её найти. Рекомендую вам искать информацию по таймерам в спецификациях, только если по-другому никак не представить, как это трудно для понимания.

Сначала определяется тактовая частота таймера. Показано, что тактовая частота установлена 2 МГц, так как мы используем деление на 8 (делитель частоты) опорной частоты 16 МГц. Это жестко запрограммировано в функции. Это определение улучшает внешний вид программы и может быть полезно в некоторых приложениях. Наконец, оно напоминает мне, как я настроил таймер.

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

Далее подсчитывается значение, перезагружаемое в таймер. Это очень простой подсчет, но требует операций с плавающей точкой. К счастью, нам нужно сделать это только один раз, поскольку операции с плавающей точкой очень дорого обходятся в пересчете на машинное время. Примем, что таймер будет установлен на 2 МГц при каждом счете. Загружаемое значение – это число отсчетов, которое мы хотим произвести при 2 МГц между прерываниями. Вы можете заметить, что я использовал 257 вместо 256 для числа отсчетов в этом выражении. Я знаю, что верное значение – 256, но я получил лучшие результаты с 257. Далее в этой в этой статье я разъясню, почему.

Следующий участок секретного кода устанавливает таймер в режим 0 и выбирает делитель частоты /8. Режим 0 – это базовый режим таймера, а делитель /8 показывает, как мы получаем счетчик, считающий с частотой 2 МГц или 0,5 мкс на отсчет.

Далее подключается прерывание по переполнению. После выполнения этого кода микроконтроллер будет вызывать ISR каждый раз, когда счетчик прокрутится от 0xFF до 0×00. Это случится, когда счетчик просчитает от нашего загруженного значения через FF и назад до 00.

Наконец, мы загружаем значение счетчика в таймер и возвращаем это загруженное значение, чтобы ISR могла использовать его позже.

Я запускал таймер максимум при 50 кГц. Это очень быстро и любые действия, выполняемые в ISR, значительно тормозят выполнение основной программы. Я не рекомендую использовать частоты свыше 50 кГц, разве что вы почти ничего не делаете в ISR.

Загрузка микроконтроллера прерываниями

Чтобы дать вам представление об эффекте, предположим, что таймер ISR запускался бы каждые 20 мкс. Процессор, работающий на 16 МГц, может выполнить около 1 машинной команды каждые 63 нс или около 320 машинных команд для каждого цикла прерывания (20 мкс). Предположим также, что исполнение каждой строки программы на С может занять много машинных команд. Каждая инструкция, используемая в ISR, отнимает время, доступное для исполнения любой другой программы. Если бы наша ISR использовала около 150 машинных циклов, мы сожрали бы половину доступного процессорного времени. При активных прерываниях главная программа откладывалась бы около ½ времени, занимаемого ей в других случаях. 150 машинных команд – не очень большая программа на С, поэтому вы должны быть внимательны.

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

Измерение загрузки прерываниями

Поскольку мне хотелось иметь очень быстрый таймер ISR, я должен был измерить, насколько я загрузил доступные ресурсы. Я придумал трюк, выполняющий оценку загрузки и позволяющий мне вывести измерение на последовательный порт. Так как я работал с таймером ISR, я мог сохранить следы загрузки прерываниями.
Таймер не был установлен в режим, когда он перезагружается автоматически. Это значит, что ISR должна перезагрузить таймер для следующего интервала счета. Было бы точнее иметь автоматически перезагружаемый таймер, но, используя этот режим, мы можем измерить время, проводимое в ISR, и соответственно исправить время, загружаемое в таймер. Ключ в том, что при помощи этой коррекции мы при разумной точности, мы также получаем и число, показывающее, сколько времени мы проводим в ISR.

Трюк заключается в том, что таймер хранит время, даже если он переполнен и прерван. В конце нашей ISR мы можем захватить текущее значение счетчика таймера. Это значение представляет то время, которое он отнял у нас до следующей точки программы. Это суммарное время, затраченное на переход в процедуру прерывания и выполнение программы в ISR. Небольшая ошибка будет оттого, что не подсчитывается время, затраченное на команду перезагрузки таймера, но мы можем исправить её эмпирически. Фактически именно поэтому я использовал в формуле подсчета загружаемого значения 257 вместо 256. Я обнаружил опытным путем, что это дает лучший результат. Лишний такт компенсирует команду перезагрузки таймера.

Источник

Многозадачная Ардуина: таймеры без боли

Не каждый ардуинщик знает о том, что помимо стартового кода в setup и бесконечного цикла в loop, в прошивку робота можно добавлять такие кусочки кода, которые будут останавливать ход основного цикла в строго определенное заранее запланированное время, выполнять свои дела, затем аккуратно передавать управление в основную программу так, что она вообще ничего не заметит. Такая возможность обеспечена механизмом прерываний по таймеру (обычное дело для любого микроконтроллера), с её помощью в прошивку можно вносить элементы реального времени и многозадачности.

Еще меньше используют такую возможность на практике, т.к. в стандартном не слишком богатом API Arduino она не предусмотрена. И, хотя, доступ ко всем богатствам внутренних возможностей микроконтроллера лежит на расстоянии вытянутой руки через подключение одного-двух системных заголовочных файлов, не каждый пожелает добавить в свой аккуратный маленький скетч пару-тройку экранов довольно специфического настроечного кода (попутно потеряв с ним остатки переносимости между разными платами). Совсем единицы (тем более, среди аудитории Ардуино) решатся и смогут в нем разобраться.

Сегодня я избавлю вас от страданий.

и расскажу, как получить настоящие многозадачность и реальное время в прошивке вашего ардуино-робота, добавив в неё ровно 3 строчки кода (включая #include в шапке). Обещаю, что у вас всё получится, даже если вы только что в первый раз запустили Blink.

Начнем сразу с кода

Подключаем библиотеку timer-api.h (раз)

Запускаем таймер с нужной частотой с timer_init_ISR_XYHz: здесь XYHz=1Hz — 1 Герц — один вызов прерывания в секунду (два)

(ISR — interrupt service routine, процедура-обработчик прерывания)

Добавляем в главный цикл loop любую блокирующую или неблокирующую ерунду: печатаем сообщение, ждём 5 секунд (здесь всё, как обычно, поэтому не считаем)

Процедура, вызываемая прерыванием по событию таймера с заданным периодом, — реализация для функции с именем timer_handle_interrupts: печатаем сообщение, мигаем лампочкой (три)

То же самое, только добавим замер времени между двумя вызовами для наглядности и отладки:

Шьем плату, открываем Инструменты > Монитор порта, наблюдаем результат:

Как видим, обработчик timer_handle_interrupts печатает сообщение каждые 1000000 (1 миллион) микросекунд, т.е. ровно раз в секунду. И (о чудо!) постоянная блокирующая задержка на 5 секунд delay(5000) в главном цикле никаким образом ему в этом действии не мешает.

Вот вам реальное время и многозадачность в одном скетче в 3 строчки, я обещал.

Варианты частот для timer_init_ISR_XYHz

(вызов timer_init_ISR_1MHz тоже есть, но он не даёт рабочий результат ни на одном из тестовых контроллеров)

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

Полагаю, излишне пояснять, что чем выше частота таймера, тем меньше период вызова прерываний, тем быстрее должен выполняться код обработчика. Я бы не рекомендовал помещать в него вызовы блокирующих задержек delay, циклы с неизвестным заранее количеством итераций, любые другие вызовы с плохо предсказуемым временем выполнения (в том числе Serial.print).

Суммирование периодов (деление частоты)

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

Произвольная частота

Есть еще вариант установить практически произвольное (в определенных границах) значение частоты таймера при помощи вызова timer_init_ISR(timer, prescaler, adjustment) с параметрами — системным делителем тактовой частоты процессора prescaler и произвольным значением adjustment для размещения в регистре счетчика таймера.

Не вдаваясь в подробности, чтобы не перегружать пост, приведу ссылку на пример с подробными комментариями:
arduino-timer-api/examples/timer-api-custom-clock/timer-api-custom-clock.ino

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

Запуск и остановка таймера в динамике

Для остановки таймера следует использовать вызов timer_stop_ISR, для повторного запуска — любой вариант timer_init_ISR_XYHz, как и раньше.

Установка библиотеки

Клонировать репозиторий прямо в каталог с библиотеками

и перезапустить среду Arduino.

Или на странице проекта arduino-timer-api скачать снапшот репозитория Clone or download > Download ZIP или один из релизов в виде архива, затем установить архив arduino-timer-api-master.zip через меню установки библиотек в среде Arduino (Скетч > Подключить библиотеку > Добавить .ZIP библиотеку. ).

Примеры должны появиться в меню File > Examples > arduino-timer-api

Поддерживаемые чипы и платформы

— Atmega/AVR 16 бит 16МГц на Arduino
— SAM/ARM 32 бит 84МГц на Arduino Due
— PIC32MX/MIPS 32 бит 80МГц на семействе ChipKIT (PIC32MZ/MIPS 200МГц — частично, в работе)

Ну и, напоследок,

Вращение шаговым мотором через интерфейс step-dir:
— в фоне по таймеру генерируем постоянный прямоугольный сигнал для шага по фронту HIGH->LOW на ножке STEP
— в главном цикле принимаем от пользователя команды для выбора направления вращения (ножка DIR) или остановки мотора (ножка EN) через последовательный порт

Источник

Таймеры и многозадачность на Ардуино

Сегодня мы поговорим о такой актуальной теме, как таймеры и организация многозадачности на Arduino. Поводом для написания этой статьи послужили лекции Олега Артамонова @olartamonov для студентов МИРЭА в рамках IoT Академии Samsung, а точнее, высказывание Олега, цитата (2-я лекция, 1:13:08):

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

Судя по высказываниям Олега, у него весьма превратное представление об Arduino вообще и об «ардуинщиках» в частности. Мигание пятью светодиодами в означенных им режимах это абсолютно тривиальная задача для Arduino, а для Arduino Mega Server это вообще не задача, а сущее недоразумение — его штатными средствами организуется многозадачность, которая легко управляет сотнями различных сущностей (светодиодов, сервоприводов, шаговых моторов и т. д.) в реальном времени.

Давайте вместе разберёмся как организовать многозадачность на Arduino, а заодно поможем студентам МИРЭА избавится от навязанных им стереотипов восприятия по отношению к социо-культурному и технологическому феномену нашего времени под названием Arduino.

Лекции Олега Артамонова

Нужно отдать должное, сами лекции Олега хороши — в них даётся много полезной и хорошо структурированной информации о микроконтроллерах и я бы рекомендовал всем заинтересованным в этом вопросе с ними ознакомиться. Единственным недостатком этих лекций мне показался неприкрытый техно-снобизм в отношении Arduino, которая выступает в них в роли «мальчика для битья».

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

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

Не будем далеко ходить за примерами. Вот проект Зимнего сада («Умной теплицы») в котором в реальном времени в многозадачном режиме работают следующие сущности:

Топология распределённого nRF24 контроллера с огромным числом подключённого и работающего в реальном времени оборудования. Пользователь имеет дело только с «базой», работа nRF24 партнёра полностью прозрачна для него. И, да, это Arduino.

— 7 сервоприводов
— 9 шаговых моторов
— 6 реле
— 3 датчика влажности почвы
— 2 датчика освещённости
— Датчик уровня воды
— Датчик влажности и температуры воздуха

На nRF24 удалённой части:

— 12 датчиков влажности почвы
— 12 реле
— 3 шаговых мотора
— 2 датчика освещённости
— Датчик уровня воды

Кроме этого, в реальном времени функционирует собственно сама nRF24 связь между двумя распределёнными частями системы и Ethernet интерфейс сервера и серверный движок, обеспечивающий веб-интерфейс пользователя системы.

Итого, в реальном времени, в многозадачном режиме на 8-битной Меге функционирует как минимум 60 сущностей (и это не считая множества сервисов самой операционной системы AMS, с ними число сущностей приблизится к сотне). Что очевидным образом никак не согласуется с высказыванием о том, что «на Arduino невозможна настоящая многозадачность и мигать даже пятью светодиодами на ней проблематично».

Пара слов в защиту Arduino

(Хотя очевидно, что Arduino как социо-культурный и технологический феномен с многомиллионной армией поклонников и многими тысячами потрясающих проектов в защите не нуждается.)

Я много раз говорил и ещё раз повторю, что Arduino в своей софтверной составляющей это, по сути, просто один из возможных уровней абстракции (как и любой другой) со своими достоинствами и недостатками. И пользователю нет абсолютно никакой разницы, что «крутится» внутри его маленького кусочка кремния — «чистая» Arduino, RTOS, RIOT OS, AMS или какая-то другая математическая абстракция представления и управления железными ресурсами контроллера.

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

Как это работает?

Сама по себе многозадачность на микроконтроллерах может быть организована разными способами, в данном случае речь пойдёт о самом простом — процессы по очереди получают управление и добровольно отдают его после использования своего кванта времени. Этот способ, конечно, не лишён очевидных недостатков, но, как говорится, практика — критерий истины и он прекрасно зарекомендовал себя в реальных условиях: он используется как в стандартных дистрибутивах Arduino Mega Server, так и во множестве проектов на AMS Pro. И эти системы работают в режиме 24/7 и имеют подтверждённые аптаймы во многие месяцы беспроблемной работы.

Это индикация около сотни сущностей распределённой nRF24 системы, управляемых независимо друг от друга в реальном времени. Обратите внимание на два последних индикатора «CPU» — при этом даже на 8-битной Меге загрузка процессора ровна нулю (то есть система полностью свободна).

Немного о таймерах

Для организации управления сложными системами недостаточно просто передавать по очереди управление между процессами и наряду с автоматической передачей управления в AMS используются различные виды таймеров: циклические, циклические с заданным количеством повторений (пакетные), одиночные, рандомные, смешанные и т. д. Всё это организовано нативными средствами Arduino и не использует прерывания или прямое программирование таймеров микроконтроллера (но прерывания, конечно же, использоваться системой «по их прямому назначению»).

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

Основной кейс

Основной кейс при данном типе организации многозадачности — это создавать так называемый «неблокирующий» код, то есть код, который не использует функцию delay(), которая просто приостанавливает выполнение программы на заданное время.

Реальное время

Описываемый способ реализации многозадачности можно охарактеризовать как «soft-realtime», типовое время задержки в системе составляет 10 мс (но пиковые задержки могут быть значительно больше и не нормируются). Это накладывает известные ограничения на спектр применения данного решения, но для большинства «бытовых» задач (и не только) он прекрасно подходит, см. пример выше.

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

Это общее теоретическое описание работы многозадачности в Arduino вообще и в AMS в частности, теперь перейдём к рассмотрению практических примеров.

Циклические таймеры

Рассмотрим реализацию самых простых циклических таймеров. Это таймеры (в терминологии AMS «cycles»), которые включаются через определённые, заранее заданные промежутки времени и используются для активации циклических процессов.

Вообще, таймеры программно лучше оформлять в виде объектов, но в стандартной поставке Arduino Mega Server эти таймеры реализованы в виде функций, поэтому, для начала, рассмотрим их в этой ипостаси.

Использовать циклические таймеры очень просто: достаточно поместить код, который нужно периодически выполнять, между скобками оператора if. Если нужно использовать другой интервал срабатывания, то просто используем нужную переменную вместо cycle1s. Различных циклов можно сделать сколько угодно — система даже на 8-битной Меге без проблем потянет обслуживание буквально сотен таких таймеров (только, естественно, нужно не забывать чтобы вызываемый код не был блокирующим).

Теперь организация работы таймеров. Определение управляющих переменных в главном файле:

Набор интервалов может быть расширен любыми нужными значениями от десятков миллисекунд до суток и более.

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

Циклические таймеры в виде объектной библиотеки

Теперь рассмотрим организацию тех же таймеров, но в более правильном объектном виде, оформленном в готовую библиотеку. Назовём её myCycle.

Заголовочный файл в котором представлены объявления класса, методов и некоторых предопределённых констант:

И файл реализации в котором находится код библиотеки:

Использование этого варианта тоже просто и имеет некоторые преимущества перед «функциональным» вариантом: тут можно очень легко объявлять таймеры с нужными интервалами и не нужно заранее создавать множество таймеров «на всякий случай».

В главном файле:

Добавляем функции обслуживания работы таймеров:

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

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

Другие виды таймеров на Arduino

Чтобы не загромождать статью, я не буду здесь приводить код и разбирать работу всех возможных типов таймеров — все они строятся по одним и тем же принципам. Если эта тема будет интересна, то можно будет написать отдельную статью об этом. Здесь я только дам общее описание таймеров, которые используются в AMS и прекрасно себя зарекомендовали на практике.

Циклические с заданным количеством повторений (пакетные)

Это таймеры, которые срабатывают заранее определённое количество раз. Например, вам нужно делать 3 попытки отправки сообщения по беспроводному каналу nRF24. Таймер активируется только 3 раза и соответственное количество раз делаются попытки отправки сообщений.

Тут же возможны различные расширения функциональности типа активации/дезактивации таймера в зависимости от определённых условий и т. п.

Одиночные

Это различные вариации на тему «автозагрузки», когда какое-либо действие выполняется через определённый интервал времени после старта контроллера или какого-либо события.

Рандомные

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

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

Это только абстрактный пример для понимания того, что собой представляют рандомные таймеры. И вы можете ознакомиться с их реализацией — стандартный дистрибутив Arduino Mega Server содержит код такого таймера.

Смешанные

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

Нет практически никаких ограничений на количество таймеров и логику работы — их может быть сотни, даже на 8-битном контроллере.

Межпроцессное взаимодействие

Межпроцессное взаимодействие, семафоры, почтовые ящики и прочие атрибуты многозадачных систем организуются на Arduino тоже без каких-либо проблем — их можно организовать любым удобным для вас способом — начиная от передачи параметров через статические переменные и заканчивая упаковкой логики в любые классы и объекты, тут нет абсолютно никаких ограничений и проблем.

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

Заключение

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

И это не должно быть секретом для студентов МИРЭА, как будущих инженеров микропроцессорных систем, ведь эти принципы можно применять на любой платформе.

Источник

Adblock
detector