Arduino введение и дополнительные ресурсы нуну пес
INTRODUCTION AND ADVANCED RESOURCES
AUTHOR
Nuno Pessanha Santos
ВВЕДЕНИЕ И ДОПОЛНИТЕЛЬНЫЕ РЕСУРСЫ
автор
Нуну Песанья Сантос
nuno.pessanha.santos@gmail.com
Персональный веб-сайт
Google Scholar
Открытый идентификатор исследователя и соавтора (ORCID)
ResearchGate
Научные круги
Scopus
Биографические данные
Web of Science
6 МАРТА 2023 г.
Вы не можете ничему научить человека,
вы можете только помочь ему найти это в
самом себе.
Галилео Галилей
КОНТЕНТЫ( Содержание)
ГЛАВА 1, ВВЕДЕНИЕ СТР. 1
ГЛАВА 2 АППАРАТНОЕ ОБЕСПЕЧЕНИЕ ПРОТИВ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ СТР. 3
2.1Аппаратное обеспечение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1 Микропроцессор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.2 Микроконтроллер. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.3 Доступные типы и объемы памяти . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.4 Доступная распиновка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2Программное обеспечение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2.1 Установка и использование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2.2 Цикл разработки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2.3 Взаимодействие с другим программным обеспечением . . . . . . . . . . . . . . . . . . . . 16
Глава 3 УКАЗАТЕЛЬ ИНСТРУКЦИЙ СТР. 18
3.1 Базовые функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.1.1 Настройка Setup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.2 Цикл Loop. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2 Циклы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.1 Если/Иначе if/else. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.2 Для for. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.2.3 Выключатель/вариант switch/case. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2.4 В то время как while. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.2.5 Делать/пока do/while. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.3 Типы доступных переменных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3.1 Логическое значение boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.3.2 Чар char против Без знака unsigned char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3.3 Байт byte. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3.4 Int против Unsigned int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.3.5 Long против Длинный без знака unsigned long . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.3.6 Число с плавающей точкой float против Двойной double. . . . . . . . . . . . . . . . . . . . 33
3.3.7 Массив array против Строки string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4 Цифровой вход/выход . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4.1 Режим вывода pinMode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.4.2 Цифровая запись digitalWrite. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.4.3 Цифровое чтение digitalRead. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.5 Аналоговый вход/выход . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.5.1 Аналоговое считывание analogRead. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.5.2 Аналоговая запись analogWrite. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.6 Время . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.6.1 миллисекунды millis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.6.2 микропроцессоры micros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.6.3 задержка delay. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.6.4 задержка составляет микросекунды delayMicroseconds . . . . . . . . . . . . . . . . . . 42
3.7 Математические функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.7.1 мин min . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.7.2 макс max . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.7.3 абс abs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.7.4 ограничивать constrain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.7.5 карта map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.7.6 степень pow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.7.7 квадратный корень sqrt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.8 Тригонометрические функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.8.1 сен sen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.8.2 косинус cos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.8.3 тан tan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.9 Случайные числа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.9.1 Случайный посев randomSeed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.9.2 случайный random. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.10 Прерывает . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.10.1 Прерывание подключения attachInterupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.10.2 Отсоединить прерыватель detachInterupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.10.3 прерывания interupts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.10.4 Отсутствие помех noInterupts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.11 Последовательная связь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.11.1 Серийный номер.доступен Serial.available . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.11.2 Серийный номер.начать Serial.begin. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.11.3 Серийный номер.считайте Serial.read . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.11.4 Последовательный сброс Serial.flush . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.11.5 Serial.print против Serial.println . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.11.6 Серийный номер.запись Serial.write. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
III
Глава 4 ДОПОЛНИТЕЛЬНЫЕ РЕСУРСЫ СТРАНИЦА 59
4.1 Флэш-память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.1.1 Запись данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.1.2 Считывание данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.2 Память EEPROM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.2.1 Запись данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.2.2 Считывание данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.3 Серводвигатель . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.3.1 Конфигурация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.3.2 Контроль . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.3.3 Считывание угла наклона . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
4.4 Последовательная связь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.4.1 Конфигурация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.4.2 Считывание данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.4.3 Передача данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.5 Введение в визуальный дизайн . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.6 Получение сигнала . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.6.1 Теоретические концепции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.6.2 Анализ Arduino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
ГЛАВА 5 ВЫВОДЫ СТРАНИЦA 81
БИБЛИОГРАФИЧЕСКИЙ СПИСОК стр. 82
1 ВВЕДЕНИЕ
Это учебное пособие было создано для того, чтобы быть понятным руководством по использованию платы разработки Arduino [1] не только для тех, кто делает свои первые шаги в этой области, но и для для тех, кто ищет более продвинутых знаний. Первоначальная версия этого руководства (на португальском языке) была выпущена в 2009 году [2], когда приложения для Arduino только развивались это было необходимо для быстрой разработки англоязычной версии (лучше позже...).
Arduino - это инструмент разработки с открытым исходным кодом, появившийся в результате академического проекта, который быстро завоевал мировой успех [3]. Arduino обычно ассоциируется с философией физических вычислений [4] как инструмент для быстрого создания прототипов и простой разработки систем. Физические вычисления предполагают создание физических объектов/ систем, способныx реагировать на входные данные из реального мира, используя комбинацию аппаратного и программного обеспечения, что позволяет полностью разработать систему [5, 6].
Мы можем описать Arduino просто как аппаратную часть с соответствующим программным обеспечением для разработки (рис. 1.1), но это гораздо больше. Благодаря его успеху с течением времени, в настоящее время по всему миру существует обширное сообщество пользователей / последователей [7], и он широко используется в качестве учебного пособия в школах и университетах [8]. Основными причинами такого успеха являются, прежде всего, его низкая стоимость, учитывая его потенциал, простота использования и возможность кроссплатформенности, поскольку программное обеспечение для разработки может работать на нескольких вычислительных платформах - Windows, Linux и macOS.
Рисунок 1.1: Прототипирование и разработка системы - упрощенная иллюстрация.
Используя Arduino, мы можем разработать целую систему с нуля без особых усилий, одновременно повышая наши навыки программирования [9]. Эта простота открывает двери для широкого спектра применений, поскольку мы можем создавать практически все, просто проявив фантазию, от роботов до домашней автоматизации и многого другого [10].
Как уже говорилось ранее, благодаря своей обширной области применения, Arduino стал практически обязательным предметом для изучения любителями электроники и энтузиастами [11]. Таким образом, ожидается, что это руководство поможет вам приобрести необходимые знания для разработки прототипов и приложений. Это учебное пособие состоит из пяти глав, включая это введение, имеющее следующее содержание:
• Аппаратное обеспечение в сравнении с Программным обеспечением (глава 2) - В этой главе рассматривается Arduino как комбинация аппаратного и программного обеспечения. Понимание каждого компонента и того, как мы можем их комбинировать, имеет важное значение для разработки наших приложений;
• Указатель инструкций (глава 3) - В этой главе описаны наиболее важные инструкции, используемые интегрированной средой разработки Arduino (IDE), обеспечивающий необходимый практический подход к обучению;
• Дополнительные ресурсы (глава 4) - В этой главе подробно представлены некоторые расширенные ресурсы, которые мы можем использовать. Этот список не претендует на то, чтобы быть обширным , поскольку практически ежедневно появляется множество новых реализаций;
• Выводы (глава 5) - В этой главе описываются некоторые выводы и соображения, которые могут мотивировать или вдохновить на будущую работу или исследования в этой области.
2 АППАРАТНОЕ И ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ
2 АППАРАТНЫЕ СРЕДСТВА ПРОТИВ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
Прежде чем приступить к быстрому созданию прототипов и разработке систем, важно понять, как работает платформа разработки Arduino. Понимание взаимосвязи между аппаратным и программным обеспечением имеет решающее значение при использовании Arduino, чтобы правильно оценить его потенциал и ограничения. Мы должны максимально использовать его потенциал и одновременно смягчать ограничения при его использовании. Аппаратное и программное обеспечение подобны кусочкам головоломки, которые мы должны использовать вместе для проектирования системы. Эта глава состоит из следующих двух разделов:
• Аппаратное обеспечение (раздел 2.1) - Этот раздел начинается с изучения некоторых основных концепций аппаратного обеспечения, например, что такое микропроцессор или микроконтроллер. Также анализируется распиновка платы разработки Arduino, типы и объемы памяти, чтобы лучше понять используемое оборудование. Понимание используемого
аппаратного обеспечения необходимо для того, чтобы заранее знать, возможно ли разработать нужную нам систему, учитывая существующие возможности и ограничения;
• Программное обеспечение (раздел 2.2) - В этом разделе описывается установка и использование Arduino IDE, обычно используемый цикл разработки sketch (программы), и кратко описывает возможности взаимодействия с другим программным обеспечением. Объединив аппаратное обеспечение с соответствующим программным обеспечением, мы получаем полноценный инструмент разработки, способный быстро создавать прототипы и разрабатывать системы.
2.1 Оборудование
В этом разделе мы сосредоточим наш подход на Arduino Uno Revision (Rev) 3, который с точки зрения использования очень похож на Arduino Mega 2560 Rev 3 (рис. 2.1). Однако существуют незначительные различия, такие как объем памяти в зависимости от различных типов памяти, количество доступных аналоговых и цифровых контактов и их размеры [1, 2, 12, 13, 14].
Рисунок 2.1: Arduino Uno Rev 3 (слева) и Arduino Mega 2560 Rev 3 (справа) [1, 12, 13].
После этапа создания прототипа мы должны выбрать оборудование, которое наилучшим образом подходит для желаемого приложения. В идеале мы не хотим использовать оборудование с функциями и возможностями, которые мы не собираемся использовать, поскольку конечная стоимость системы возрастет. Когда мы используем оборудование с большими возможностями, чем требуется, у нас, как правило, повышается потребность в электроэнергии и требуется больше свободного пространства (большие размеры). Имея это в виду, мы должны выбрать плату Arduino, которая больше подходит для нашего конечного применения при разработке системы. Как было описано ранее, и для лучшего понимания используемого оборудования, этот раздел разделен на следующие подразделы:
• Микропроцессор (подраздел 2.1.1) - В этом подразделе кратко описывается определение микропроцессора, который является критически важным компонентом, поскольку он может выполнять обработку, являясь мозгом системы.;
• Микроконтроллер (подраздел 2.1.2) - В этом подразделе рассматривается общее определение микроконтроллера и кратко представлена структурная схема микроконтроллер ATmega328P [15], используемый в Arduino Uno Rev 3 [12];
• Доступные типы и объемы памяти (подраздел 2.1.3) - В этом подразделе описываются доступные типы памяти в Arduino Uno, а также Mega boards [12, 13], также объясняющие, как это может ограничить их производительность при разработке некоторых типов приложений (конструктивные ограничения).;
• Доступная распиновка (подраздел 2.1.4) - В этом разделе представлена распиновка Arduino, которая необходима для быстрого создания прототипов и разработки систем.
Как описано выше, зная возможности и ограничения аппаратного обеспечения
это имеет решающее значение для максимального его использования.
2.1.1 Микропроцессор
Микропроцессор - это интегральная схема, способная выполнять определенные инструкции [16] (рис. 2.2). Скорость его обработки определяется схемой, которая генерирует тактовый сигнал - внешний сигнал, синхронизирующий его работу. На его вычислительную мощность, как правило, влияют такие характеристики, как размер коммуникационной шины (количество используемых битов), количество ядер и тип команд (Глава 3), а также многие другие. Микропроцессор считывает и выполняет программы, хранящиеся во внешней памяти. В сочетании с другими компонентами он может использоваться для разработки и создания автономных систем - встраиваемых систем [17].
Рисунок 2.2: Упрощенная схема микропроцессора.
Одного микропроцессора недостаточно для создания прототипов и разработки системы, поскольку он должен быть объединен с внешним оборудованием (рисунок 2.2). Благодаря постоянному развитию интегральных схем мы можем использовать микроконтроллеры (подраздел 2.1.2), которые объединяют микропроцессоры с необходимыми компонентами (периферийными устройствами) в единую интегральную схему. Объединение всех компонентов в одном чипе упростило реализацию этой технологии, которая теперь доступна в готовых коммерческих решениях, таких как Arduino (рис. 2.1).
2.1.2 Микроконтроллер
Как кратко описано в предыдущем подразделе, микроконтроллер спроектирован
и собран для интеграции нескольких компонентов (периферийных устройств) в единую интегральную схему. Такая интеграция позволяет избежать использования внешних компонентов при реализации стандартной системы на базе микроконтроллера (встраиваемой системы). На рис. 2.3 показаны примеры доступных компонентов внутри микроконтроллера,
объединяющих ресурсы, необходимые для стандартной работы, в единую интегральную схему [18, 19].
Рисунок 2.3: Упрощенная схема микроконтроллера.
Arduino Uno Rev 3 оснащен микроконтроллером ATmega328P [15], в то время как Arduino В Mega Rev 3 установлен микроконтроллер ATmega2560 [20] (рис. 2.1). На рис. 2.4 представлена структурная схема микроконтроллера ATmega328P (аналогичная схеме на Микроконтроллер ATmega2560), где можно идентифицировать его основные компоненты. Сравнивая рисунок 2.3 и рисунок 2.4, мы видим, что в ATmega328P присутствует большинство стандартных компонентов. Основные компоненты ATmega328P
можно кратко описать следующим образом (рис. 2.4) [15]:
• AVR CPU - Центральный процессор (CPU) или микропроцессор [15, 20];
6
• Генераторные схемы/генерация тактовых импульсов - сигнал (clock), который используется для синхронизации операций микропроцессора (синхронная работа) [21];
• Статическая оперативная память (SRAM) - это основная память, данные
в которой теряются при отключении питания - удаляются (зависимая память) [22].;
• Электрически стираемое программируемое постоянное запоминающее устройство (EEPROM) - используется для хранения данных, которые сохраняются при отключении питания - удаляются (энергонезависимая память) [23, 24];
• Flash - в нем хранятся загрузчик Arduino и sketch или программа для запуска (энергонезависимая память). Загрузчик - это программное обеспечение, используемое для управления загрузкой sketch на плату Arduino [25, 26];
• 8-битный или 16-битный таймер/счетчик (T/C) - Таймер/счетчик, который может использоваться для измерения временных интервалов или количества повторений определенного события [27];
• Универсальный синхронный асинхронный приемник-передатчик (USART)
- Используется для реализации связи через последовательный порт (сокет,
реализующий последовательный интерфейс) с использованием стандарта RS232 [28];
• Последовательный периферийный интерфейс (SPI) - используется для реализации синхронного последовательного интерфейса связи на коротких расстояниях [29].;
• Двухпроводной интерфейс (TWI) - используется для реализации простого
протокола последовательной связи, в котором используются всего два контакта (провода) [30];
• Аналого-цифровой преобразователь (АЦП) - используется для преобразования аналоговых сигналов в цифровые для выполнения обработки данных с помощью микропроцессора [31, 32];
• Сторожевой таймер - отслеживает запущенную программу через определенные промежутки времени, проверяя, не останавливается ли она или не проявляет ли неожиданного поведения [33, 34].
Этот раздел не предназначен для подробного обзора микроконтроллера.
Для получения более подробного описания его компонентов и режимов работы вам следует обратиться к техническому описанию используемого микроконтроллера [1, 15, 20].
7
Рисунок2.4.Структурная схема микроконтроллера ATmega328P [15].
8
2.1.3 Доступные типы и объемы памяти
Одним из основных различий между различными платами Arduino является их различный
объем памяти. Важно проанализировать это различие, поскольку оно может представлять
собой решающий фактор производительности в окончательно разработанной системе (проектные ограничения). Доступные типы памяти описаны в таблице 2.1, а объемы доступной памяти - в таблице 2.2.
Таблица 2.1: ATMEGA328P в сравнении с ATMEGA2560 - Описание типов памяти [12, 13].
FLASH используется для хранения эскиза и загрузчика (энергонезависимый)
SRAM используется для хранения переменных во время выполнения программы (энергозависимый)
EEPROM может использоваться для хранения информации (энергонезависимый)
Таблица 2.2: Доступная память ATMEGA328P в сравнении с ATMEGA2560 [12, 13, 15, 20].
ATMEGA328P ATMEGA2560
Вспышка \Флеш 32 килобайт 256 килобайт
(загрузчик объемом 0,5 килобайта)(загрузчик объемом 8 килобайт)
SRAM 2 килобайта 8 килобайт
EEPROM 1 килобайт 4 килобайта
Проанализировав таблицу 2.2, можно убедиться в том, что ATMEGA2560 имеет явное преимущество в плане объема памяти. Одним из основных типов памяти, помимо Flash, где мы храним sketch (программу для запуска) и загрузчик (программное обеспечение, управляющее загрузкой sketch), является SRAM, где программа создает и изменяет все необходимые переменные во время своего выполнения. В отличие от EEPROM и Flash (энергонезависимых), в памяти этого типа хранятся данные только во время
работы (энергозависимые). Иногда нам приходится управлять большими переменными и сохранять их во время выполнения программы. Чтобы сэкономить SRAM, мы можем сохранить эти константы во Flash или EEPROM. Для доступа к этим константам мы можем легко использовать внешние библиотеки, которые обеспечивают быстрый и безопасный доступ, как описано в главе 4.
9
2.1.4 Доступная распиновка
Анализ имеющейся распиновки Arduino Uno Rev 3 необходим для понимания
того, что можно использовать для быстрого создания прототипов и разработки систем с использованием этой модели (Рисунок 2.5). Данная модель имеет несколько аналоговых и цифровых выводов (таблица 2.3), обеспечивающих максимальный ток 40 мА. Единственным исключением является вывод 3,3 В (3V3), который обеспечивает максимальный ток 50 мА.
Рисунок 2.5: Arduino Uno Rev 3 - Схематическое изображение.
Таблица 2.3: Arduino Uno Rev 3 - Доступная распиновка [12].
Цифровой вход/Выход 14 (6 с широтно-импульсной модуляцией - ШИМ)
Аналоговый вход 6
Заземление (GND) 3
5В 1
3,3 В 1
Аналоговый эталон (AREF) 1
Сброс (ПЕРВЫЙ ) 1
Большинство цифровых контактов Arduino Uno Rev 3 (рис. 2.5) поддерживают широтно-импульсную модуляцию (ШИМ) [35, 36]. Используя ШИМ, мы можем получить эквивалентное аналоговое напряжение из цифрового сигнала, который может принимать только логическое состояние 0 (0 В) или 1 (5 В). ШИМ-сигнал характеризуется постоянной частотой и переменным рабочим циклом (рис. 2.6).
10
Рисунок 2.6: Представление ШИМ-сигнала.
Полученное эквивалентное напряжение постоянного тока (DC), Vdc, для ШИМ-сигнала задается как:
где T обозначает период, а V (t) - напряжение сигнала в зависимости от времени. Анализируя рисунок 2.7, мы можем упростить уравнение 2.1, получив:
где tp представляет собой длительность импульса (переменный рабочий цикл), а Vpulse
- импульсное напряжение ШИМ-сигнала (5 В при использовании Arduino).
Рисунок 2.7: Пример сигнала широтно-импульсной модуляции.
Применяя концепции, описанные ранее (рис. 2.7), и комбинируя уравнения 2.1
и 2.2, мы получаем:
11
Анализируя уравнение 2.3, мы можем заключить, что полученное эквивалентное напряжение постоянного тока прямо пропорционально скважности ШИМ-сигнала (tp). Эта функция позволяет нам легко изменять среднее значение напряжения в диапазоне от 0 В до 5 В при использовании Arduino. После краткого описания функционирования ШИМ-сигнала мы также рассмотрим аналого-цифровое преобразование. Понимание этого преобразования важно для интерпретации значений, полученных из показаний аналоговых выводов. Аналого-
цифровой преобразователь ATMEGA328P имеет разрешение 10 бит (res) [2, 14, 15], и при использовании 5 В в качестве используя аналоговый эталон (Aref), мы получаем следующее разрешение по напряжению (Vres ) [2, 14, 37]:
Анализируя уравнение 2.4, мы можем видеть, что мы будем обнаруживать только колебания напряжения (изменение полученного значения на входе), превышающие 5 мВ. При использовании аналоговых датчиков в некоторых приложениях возможно, что 5 мВ не являются приемлемым значением разрешения по напряжению, поскольку изменение выходного сигнала датчика может быть меньше этого значения. Возможным решением без использования внешней электроники является изменение аналогового значения с помощью вывода AREF на плате (рис. 2.5). Вывод AREF позволяет изменять аналоговое опорное напряжение (Aref) на его входное напряжение, создавая другое разрешение по напряжению. Если мы используем 2 В в качестве Aref, мы получаем следующее разрешение по напряжению (Vres).:
Важно помнить, что при использовании другого Aref все аналоговые контакты будут иметь эту ссылку, что также необходимо для объявления ее использования в Arduino IDE
(Пример 2.1). После настройки Arduino на использование контакта AREF в качестве эталонного, контакты 3,3 В и 5 В становятся недоступными.
Аналоговая ссылка(тип) //"ПО УМОЛЧАНИЮ", "ВНУТРЕННЯЯ" или "ВНЕШНЯЯ"
Аналоговая ссылка (ПО УМОЛЧАНИЮ) //Сохраняет значение по умолчанию 5 В Аналоговая ссылка (ВНУТРЕННЯЯ) //Изменяет значение на 1,1 В (ATmega328P)
Аналоговая ссылка (ВНЕШНЯЯ) //В качестве ссылки используется входной контакт AREF
Пример 2.1: analogReference() - Описание [15, 37].
12
При выборе аналоговой ссылки с помощью Arduino IDE (пример 2.1) мы меняем выбор мультиплексора аналого-цифрового преобразователя (ADMUX). Зарегистрируйте содержимое [15, 20]. Важно подключить язык высокого уровня, используемый в Arduino IDE, к низкоуровневым операциям. Установив это подключение, мы сможем повысить производительность нашей системы на этапе проектирования.
Питание платы Arduino можно осуществлять с помощью порта универсальной последовательной шины (USB), разъема питания или вывода Vin для ввода напряжения. При использовании внешнего источника питания для автономной работы рекомендуется использовать входное напряжение от 7 до 12 вольт [12]. Вывод ввода напряжения Vin (рис. 2.5) выполняет двойную функцию, поскольку вы можете использовать его как входной или выходной источник питания. Подача входного напряжения будет доступна на этом выводе при использовании USB-входа или разъема питания для включения питания платы. Более подробная информация о конфигурации описана в главе 4.
2.2 Программное обеспечение
В этом разделе описывается установка и использование Arduino IDE (подраздел 2.2.1), цикл разработки приложения (подраздел 2.2.2) и кратко описывается возможность взаимодействия с другим программным обеспечением (подраздел 2.2.3).
2.2.1 Установка и использование
В этом подразделе кратко описаны установка и использование Arduino IDE. Arduino IDE проста и интуитивно понятна в установке и использовании. В настоящее время обширное сообщество Arduino может быстро помочь в процессе обучения [7]. Первым шагом является загрузка Arduino IDE (рис. 2.8) с официального сайта [1]. Последняя доступная версия появится вверху страницы (рис. 2.9), и необходимо только выбрать и загрузить правильную версию в соответствии с используемой операционной системой - кроссплатформенную (Windows, Linux и macOS).
Рисунок 2.8: Веб-сайт Arduino - вкладка "Программное обеспечение" [1].
13
Рисунок 2.9: Веб-сайт Arduino - вкладка "Программное обеспечение", доступные параметры загрузки [1].
После загрузки распакуйте файлы в нужную папку назначения. Следующий шаг включает в себя подключение платы разработки Arduino к компьютеру через USB. Это позволит устанавливать устройства будущего по технологии International Драйвер Limited (FTDI), отвечающий за реализацию преобразования между USB и последовательной связью [38]. Этот драйвер можно установить из папки с программным обеспечением Arduino или с официального веб-сайта FTDI [39], чтобы использовать последнюю доступную версию.
Стандартная схема FTDI показана на рисунке 2.10.
Рисунок 2.10: Распиновка FTDI - иллюстрация [38].
14
Чтобы начать использовать Arduino IDE, мы должны убедиться, что выбранная модель соответствует плате Arduino и что коммуникационный порт подключен правильно определеным. Чтобы выполнить эту настройку, мы должны выбрать подходящие параметры на вкладке Инструменты Arduino IDE, как показано на рисунке 2.11. После такой настройки мы готовы к внедрению и завершению цикла разработки, имея возможность скомпилировать эскиз и загрузить его, как описано в подразделе 2.2.2.
Рисунок 2.11: Конфигурация платы Arduino IDE и последовательного порта.
2.2.2 Цикл разработки
Как первоначально описывалось в предыдущем подразделе, цикл разработки имеет решающее значение для создания прототипов и разработки системы. Стандартный цикл разработки может быть разделен на следующие четыре этапа (рис. 2.12 и рис. 2.13):
• Редактирование - На этом этапе мы разрабатываем наш эскиз, или, другими словами, пишем нашу программу. Мы можем использовать дополнительные инструменты, такие как блок-схемы или конечные автоматы, чтобы лучше организовать выполнение программы [40, 41, 42].;
• Компиляция - На этом этапе мы преобразуем наш эскиз, написанный на языке программирования высокого уровня, понятном человеку, в двоичный язык низкого уровня, понятный микроконтроллеру Arduino [43].;
15
• Загрузка - когда мы загружаем эскиз (нашу программу) через USB-кабель. (используя загрузчик) на плату Arduino [44];
• Запуск - когда мы включаем питание или нажимаем кнопку сброса платы Arduino, чтобы запустить загруженный эскиз (программу) с самого начала.
Редактирование компиляция загрузка запуск
Рисунок 2.12: Схема стандартного цикла разработки приложения — иллюстрация.
Рисунок 2.13: Схема цикла разработки - иллюстрация с использованием Arduino.
2.2.3 Взаимодействие с другим программным обеспечением
Если вы хотите использовать платформу разработки Arduino с другим программным обеспечением, вы можете перейти на вкладку playground на официальном веб-сайте Arduino (рис. 2.14). Там вы можете найти несколько ссылок, которые позволяют Arduino взаимодействовать с другим программным обеспечением для разработки, например, Mathematica или Matlab (рис. 2.15). Любое программное обеспечение, которое может получать, отправлять и использовать данные с USB-порта (последовательная связь с использованием чипа FTDI, как описано в подразделе 2.2.1), может использоваться для разработки новых приложений в соответствии с философией физических вычислений, создавая физические системы, способные взаимодействовать с окружающим миром.
16
профессионал обучение магазин поиск в Ардуино.сс расписаться
аппаратное обеспечение программное обеспечение облако документация: ардуино документы давайте начнем ссылки встроенные примеры библиотечные примеры взлом песочница центр помощи общество блог об
Рисунок 2.14: Веб-сайт Arduino - вкладка Playground [1].
Ардуино плайгроунд\песочница только для чтения открыта 31 декабря 2018 . Для большей информации смотрите Почту Форума
Песочница Ардуино
Приветствуем в Ардуино Плайгроунд, вики где все пользователи Ардуино могут внести вклад и получить пользу от коллективного исследования.
Это место для почты и внесения вашего собственного кода, диаграмм схем, руководств, DIY инструкций, советов и трюков, и после всей трудной работы, показать ваш проект! Любой может редактировать и добавить страницу здесь.
Ардуино Песочница — это работа в прогрессе. Мы можем использовать всю помощь, которую вы можете лать, так что пожалуйста прочитайте раздел Членство и начинайте печатать пальцами!
Если вы ищете для вдохновения, вы можете провести ревизию Хаба Ардуино Проекта — платформу для руководства, где вы можете размещать ваши Проекты, Руководства Начать и Статьи. Вы можете комментировать и отметить содержание , которое вам наиболее понравилось.
Дерево Содержания Песочницы
Ардуино на испанском, болгарском, каталонском, немецком, французком, итальянском, португальском и русском.
Руководство и план обучения
- Более Продуктивное начинает располагаться — Связующая документация , что будет через различные темы
Руководство и план обучения
Ардуино Обмен стеками
Конфигурация и настройка платы
Инструменты развития
Ардуино на других чипах
Сопряжение с аппаратным обеспечением
Вывод
Ввод
Пользовательский интерфейс
Хранилище
Связь
Подключение питания
Главное
Интерфейс с программным обеспечением
Библиотека пользовательского кода
- Отрывки и Эскизы
- Библиотеки
-Руководства
Предложения и ошибки
Методы электроники
Источники для электронных частей
Связанное аппаратное обеспечение и инициативы
Ардуино Люди\Группы и Сайты
Выставка
Идеи Проекта
Языки
Участие
- Руководства шаблоны
- Все недавние изменения
Рисунок 2.15: Содержимое веб-сайта Arduino - вкладка Playground [1].
17
ИНДЕКС ИНСТРУКЦИЙ 3
В этой главе будут описаны инструкции на языке высокого уровня, используемые в Arduino IDE, не прибегая к внешним библиотекам. Перед описанием инструкций мы кратко рассмотрим одну из возможных классификаций микроконтроллеров, основанную на характеристиках их набора команд. Основываясь на характеристиках их наборов команд, мы можем разделить типы микропроцессоров на две основные группы [45, 46, 47].:
• Компьютеры с комплексным набором инструкций (CISC) - В этой архитектуре используются инструкции со сложными режимами адресации, что позволяет создавать очень компактные программы, используя меньшее количество инструкций. Как недостаток, эта архитектура требует высокой тактовой частоты для быстрого выполнения своих функций и, как правило, имеет несколько различных режимов адресации, что увеличивает ее сложность;
• Компьютеры с сокращенным набором команд (RISC) - эта архитектура использует минимум простых и быстрых инструкций. Поскольку мы используем большее количество инструкций с меньшим временем выполнения для выполнения одной и той же задачи, используя эту архитектуру и оптимизируя программу, мы, как правило, получаем более высокую скорость обработки по сравнению с архитектурой CISC.
18
Как правило, микропроцессоры RISC в их простейшей версии содержат следующие типы команд [45, 46, 47]: (i) логические и арифметические команды для регистров, (ii) команды для передачи данных между памятью и регистрами и (iii) команды управления. Модели микроконтроллеров, используемые в платах Arduino, основаны на продвинутой архитектуре RISC [20, 15], разработанной методом Микропроцессор Без использования Технологий Степеней Замкнутого Трубопровода Microprocessor Without Interlocked Pipeline Stages (MIPS) [48]. Поскольку мы используем Arduino IDE, в которой используется язык высокого уровня, аналогичный универсальному языку программирования C, классификация микропроцессоров не будет касаться непосредственно программиста. Эта глава разделена на следующие разделы:
• Базовые функции (раздел 3.1) - В этом разделе описываются основные функции, которые необходимо реализовать в Arduino sketch\набросок\эскиз (программе).;
• Циклы (раздел 3.2) - В этом разделе описываются циклы (loops), которые можно использовать для настройки процесса создания эскиза в соответствии с некоторыми предопределенными условиями;
• Типы доступных переменных (раздел 3.3) - В этом разделе описываются типы переменных и способы их определения и использования в нашем эскизе.;
• Цифровой вход/выход (раздел 3.4) - В этом разделе описаны функции, используемые для считывания или изменения состояния цифровых выводов;
• Аналоговый вход/выход (раздел 3.5) - В этом разделе описаны функции, используемые для считывания аналоговых выводов;
• Время (раздел 3.6) - В этом разделе описаны функции, которые можно использовать для подсчета времени и выполнения определенных временных задержек в процессе работы программы;
• Математические функции (раздел 3.7) - В этом разделе описаны функции, которые можно использовать для выполнения математических операций с переменными данных;
• Тригонометрические функции (раздел 3.8) - В этом разделе описываются функции, которые могут быть использованы для выполнения тригонометрических операций с данными переменными;
19
• Случайные числа (раздел 3.9) - В этом разделе описываются функции, которые могут быть использованы для генерации случайных (на самом деле псевдослучайных) чисел, которые могут быть полезны в некоторых приложениях;
• Прерывания (раздел 3.10) - В этом разделе описываются прерывания, которые представляют собой события, временно приостанавливающие работу основной программы и которые могут быть использованы для выполнения определенных изменений в потоке основной программы.;
• Последовательная связь (раздел 3.11) - В этом разделе описываются функции, которые можно использовать для связи через последовательный порт, отправки или получения данных.
В этой главе будет кратко описана каждая из функций, которые могут быть использованы
для разработки нашего эскиза и выполнения разработки системы. Для каждой из функций будет предоставлено краткое описание и наглядный пример, которые будут полезны для лучшего понимания использования и режима работы.
3.1 Базовые функции
Как и было описано ранее, в этом разделе будут рассмотрены две основные функции, которые необходимо использовать, как реализовано при разработке нашего эскиза - настройка setup и цикл loop.
Использование этих функций является обязательным, даже если их использование считается ненужным (чего не бывает). Функция setup (подраздел 3.1.1) используется для выполнения инициализации, а функция loop (подраздел 3.1.2) используется для создания цикла, содержащего набор инструкций, которые будут выполняться непрерывно. Обе функции обязательно относятся к типу void, поскольку они не могут возвращать какое-либо значение после выполнения. Реализация обеих функций описана в примере 3.1.
void setup() _BOS_ //Набор команд, выполняемых при запуске системы (платы)
(.....) //Программный код
}
void loop() _BOS_ //Набор команд, выполняющийся в цикле
(.....) //Программный код
}
Пример 3.1: Настройка и циклические функции - Описание.
20
3.1.1 Установка Setup
Функция настройки setup выполняется только один раз во время запуска платы (system start)
и повторяется только при сбросе настроек или при подтверждении нового запуска (выключение/включение питания). Эта функция инициализирует системные параметры, такие как входные или выходные контакты и последовательная связь (пример 3.2). Как описано ранее, это функция относится к типу void, поскольку после выполнения она не может вернуть никакого значения.
int button=3; //Целочисленная переменная "button" инициализируется значением "3".
(.....) //Инициализация глобальных переменных
void setup() _BOS_ //Набор команд, выполняемых при запуске системы (платы)
Serial.begin(9600); //Инициализация последовательной связи -
режим вывода со скоростью передачи данных в бодах
pinMode/режим крепления (кнопка,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(13,ВЫВОД); //Позволяет использовать вывод 13 в качестве "ВЫВОДА"
(.....) //Программный код
}
void loop(){ //Набор команд, выполняющийся в цикле
(.....) //Программный код
}
Пример 3.2: Функция настройки - Пример.
3.1.2 Петля loop
Функция loop позволяет выполнять определенный набор инструкций в последовательном цикле (пример 3.3). Этот непрерывный цикл позволяет, например, непрерывно отслеживать входное значение с внешнего датчика и выполнять определенные действия в соответствии с заранее заданными условиями. Последовательное считывание и проверка состояния значения конкретного pin-кода (мониторинг) называется опросом \polling. Во время разработки эскиза вы должны проявить творческий подход, чтобы гарантировать, что разработанный прототип будет соответствовать вашим требованиям. Последовательное считывание и проверка состояния значения определенного pin-кода (мониторинг) называется опросом. Во время разработки эскиза вы должны проявить творческий подход, чтобы гарантировать, что разработанный прототип будет вести себя желаемым образом в качестве встроенной системы. Как было описано ранее, эта функция относится к типу void, поскольку она не может возвращать какое-либо значение после выполнения.
21
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
int f[10]; //Инициализация целочисленного массива с 11 позициями в памяти
float test; //Инициализация переменной float "test"
float analog_read; //Инициализация переменной float "analog_read"
(.....) //Инициализация глобальных переменных
void setup() _BOS_ //Набор команд, выполняемых при запуске системы (платы)
Serial.begin(9600); //Инициализация последовательной связи -
режим вывода скорости передачи данных в бодах
pinMode(датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(12,ВХОД); //Разрешает использовать вывод 12 в качестве "входного"
pinMode(13,ВЫХОД); //Разрешает использовать вывод 13 в качестве "ВЫХОДНОГО"
(.....) //Программный код
}
void loop() _BOS_ //Набор команд, выполняющийся в цикле
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
if(val>=500) _BOS_ //Проверьте, больше ли значение "val" или равно 500
digitalWrite(13,HIGH); //Если значение true, цифровой вывод 13 становится "ВЫСОКИМ" (5 В).
}
if(val<500) _BOS_ //Проверьте, не превышает ли значение "val" 500
digitalWrite(13,НИЗКИЙ уровень); //Если значение true, цифровой вывод 13 становится "НИЗКИМ" (0 В) }
(.....) //Программный код
}
Пример 3.3: Функция цикла - Пример.
3.2 Циклы
В этом разделе будут описаны часто используемые циклы (loops), которые могут быть использованы для выполнения определенных инструкций в соответствии с предопределенными условиями. Как будет показано ниже как описано, мы можем использовать цикл if/else для проверки определенного условия (подраздел 3.2.1), цикл for - для выполнения определенного набора инструкций определенное количество раз (Подраздел 3.2.2), цикл переключения/cверки для проверки значения переменной с учетом
22
определенного количества условий (подраздел 3.2.3), цикл while для выполнения определенного набора инструкций до тех пор, пока не будет выполнено определенное условие (подраздел 3.2.4), и цикл do/while, который аналогичен циклу while, но условие проверяется только в конце после итерации (подраздел 3.2.5)..
3.2.1 Если/Иначе If/Else
Этот цикл описывает и тестирует конкретные условия (пример 3.4). Мы можем использовать
несколько связанных между собой циклов if/else для последовательной проверки нескольких условий.
if(условие){ //Тестовое условие
Инструкция 1; //Если верно
(.....) //Программный код
} else{ //Использование инструкции "else" необязательно
Инструкция A; //Если false
(.....) //Программный код
}
Пример 3.4: Описание цикла If/Else.
Согласно принятой структуре, определенные инструкции (набор инструкций) могут выполняться, когда переменная условия равна, больше, меньше или отличается от определенного значения, как описано в таблице 3.1.
Таблица 3.1: Возможные условия - X и Y.
X == Y X равно Y
X != Y X не равно Y
X >Y X больше Y
X >= Y X больше или равно Y
X <Y X меньше Y
X <= Y X меньше или равно Y
Пример реализации цикла if можно увидеть в примере 3.5, где непрерывно проверяется целочисленная переменная val. Если эта переменная достигает значения, превышающего
23
больше или равно 500, цифровой вывод 13 переходит на высокое значение HIGH (5 В). С другой стороны, если значение этой переменной меньше 500, цифровой вывод 13 переходит на НИЗКОЕ значение LOW (0 В). Как описано в примере 3.4, использование инструкции else необязательно.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
(.....) //Инициализация глобальных переменных
аннулирует настройку(){
pinMode(датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(12,ВЫВОД); //Разрешает использовать вывод 12 в качестве "ВЫВОДА"
pinMode(13,ВЫВОД); //Разрешает использовать вывод 13 в качестве "ВЫВОДА"
(.....) //Программный код
}
void loop(){
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
if(val>=500) _BOS_ //Проверьте, больше ли значение "val" или равно 500
digitalWrite(13,HIGH); //Если значение true, цифровой вывод 13 становится "ВЫСОКИМ" (5 В).
} else{
digitalWrite(13,НИЗКИЙ уровень); //Если значение false, цифровой вывод 13 становится "НИЗКИМ" (0 В)
}
if(val>=800) _BOS_ //Проверьте, не превышает ли значение "val" значение 800
digitalWrite(12,HIGH); //Если значение true, цифровой вывод 12 становится "ВЫСОКИМ" (5 В)
(.....) // Программный код
}
Пример 3.5: Цикл If/Else - Пример.
3.2.2 Для for
Этот цикл используется, когда мы хотим выполнить определенный набор команд несколько раз. Чтобы использовать этот цикл, мы должны выполнить инициализацию переменной, определить тест условие и определите приращение, которое необходимо внести в переменную (пример 3.6). Например, мы можем использовать этот тип цикла для заполнения целочисленного массива данными, полученными от аналогового датчика.
24
for(Инициализация переменной; Условие; Определение приращения переменной){
(.....) //Программный код
}
//Пример 1
для(int i=10; i==0; i--) //Оператор уменьшения "i--"
//Пример 2
для(int i=0; i>10; i++) //Оператор инкремента "i++"
Пример 3.6: Описание цикла Для for.
Иллюстрацию реализации цикла for можно увидеть в примере 3.7. целочисленная переменная i инициализируется только один раз в начале цикла. При каждом выполнении цикла проверяется выполнение условия. Если условие не выполняется (false), выполняется приращение, а если условие выполняется (true), цикл завершается.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
int f[10]; //Инициализация целочисленного массива с 11 позициями в памяти
(.....) //Инициализация глобальных переменных
void setup(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
pinMode(датчик,ВХОД); //Разрешает использовать вывод 3 в качестве "ВХОДНОГО сигнала"
pinMode(12,ВЫХОД); //Разрешает использовать вывод 12 в качестве "ВЫХОДНОГО сигнала"
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "выходного"
(.....) //Программный код
}
void loop()
_BOS_ for(int i=0;i<=10;i++) _BOS_ //Выполняется до тех пор, пока значение "i" не станет меньше или равно 10
val=analogRead(датчик); //Значение аналогового вывода 3 присвоено "val".
f[i]=val; //Присвоить значение "val" массиву "f" в позиции "i"
}
(.....) //Программный код
}
Пример 3.7: Пример цикла Для for.
25
3.2.3 Выключатель/вариант switch/case
Этот цикл используется, когда мы хотим объявить и протестировать список возможных условий (cases \вариантов) для конкретной переменной (пример 3.8). Каждое условие проверяется (тестируется) и выполняется только тогда, когда переменная соответствует объявленному условию. Условие прерывания break гарантирует, что цикл завершится после выполнения этого условия (true). В противном случае цикл будет продолжен из проверенного состояния.
переключатель(переменный){
случай 1:
//Инструкции, которые должны выполняться, когда "переменная" равна 1 (переменная == 1)
break;
случай 2:
//Инструкции, которые должны выполняться, когда "переменная" равна 2 (переменная == 2)
перерыв;
(.....) //Программный код
по умолчанию:
//Выполняется, если не выполнено ни одно из предыдущих условий (true)
//Это условие необязательно
}
Пример 3.8: Описание цикла переключения/варианта.
Иллюстрацию реализации цикла переключения/варианта switch/case можно увидеть в примере 3.9. Целочисленная переменная val постоянно тестируется, и если она достигает значения, равного 500, цифровой вывод 13 становится ВЫСОКИМ HIGH(5 В). Если условие не выполняется (false), и поскольку мы определили, что происходит в этом случае с помощью условия по умолчанию, цифровой вывод 13 становится разряженным (0 В). Если вывод 13 уже находится в разряженном состоянии LOW, то система выходные данные не изменяет, даже если условие не будет выявлено (выполнение по умолчанию). Поскольку все циклы включены в функцию loop, условия постоянно проверяются (опрос polling). При разработке эскиза мы должны учитывать это, чтобы гарантировать ожидаемое поведение системы.
int sensor=3; //Целочисленная переменная "button" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
(.....) //Инициализация глобальных переменных
26
не нуль настройка(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
pinMode(датчик,ВХОД); //Разрешает использовать вывод 3 в качестве "входного сигнала"
pinMode(13,ВЫХОД); //Разрешает использовать вывод 13 в качестве "выходного сигнала"
(.....) //Программный код
}
void loop(){
val=analogRead(датчик); //Значение аналогового вывода 3 присвоено значению "val"
переключатель(val){
случай 500: //Проверка, соответствует ли значение "val" значению 500
digitalWrite(13,HIGH); //Если значение true, цифровой вывод 13 отключает "HIGH" (5 В)
; //Инструкция, позволяющая завершить цикл
по умолчанию: //Если не выполняется ни одно из условий (его использовать необязательно)
digitalWrite(13,НИЗКИЙ уровень); //Цифровой вывод 13 становится "НИЗКИМ" (0 В)
}
(.....) //Программный код
}
Пример 3.9: Пример цикла переключения/вариант switch/case-
3.2.4 Пока while
Этот цикл обычно используется для выполнения определенного набора инструкций (пример 3.10)до тех пор, пока не будет выполнено определенное условие (true). Если условие выполнено (true), цикл завершается. В случаях, когда условие не выполняется (false), мы застреваем в бесконечном цикле, подобном описанному для функции loop (подраздел 3.1.2). Мы должны учитывать это на этапе проектирования, гарантируя, что такой ситуации не возникнет.
while(условие){
Инструкция 1;
Инструкция 2;
Инструкция 3;
Инструкция 4;
(.....) //Программный код
}
Пример 3.10: Описание цикла пока While.
27
Иллюстрацию реализации цикла while можно увидеть в примере 3.11. Цикл выполняется непрерывно до тех пор, пока целочисленная переменная i не станет меньше или равна 10, присваивая аналоговое значение с вывода 13 целочисленному массиву f[i] в позиции i. Цикл заканчивается, когда выполняется условие (true), и выполняются остальные инструкции, включенные в функцию цикла. Как описано ранее, функция loop выполняется непрерывно, и цикл повторяется на каждой итерации.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3".
int val; //Инициализация целочисленной переменной "val"
int f[10]; //Инициализация целочисленного массива с 11 позициями в памяти
int i = 0; //Целочисленная переменная "i", инициализируемая значением "0"
(.....) //Инициализация глобальных переменных
отменяет настройку(){
Serial.begin(9600); //Инициализация последовательной связи -
режим вывода скорости передачи данных в бодах (датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "ВЫХОДНОГО сигнала".
(.....) //Программный код
}
пустой цикл(){
while(i<=10) //Цикл выполняется до тех пор, пока i<=10
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
f[i]=val; //Присвоить значение "val" массиву "f" в позиции "i"
i++; //Увеличить значение "i" (i = i + 1)
}
(.....) //Программный код
}
Пример 3.11: Пример цикла пока While .
3.2.5 Do/While
Этот цикл очень похож на цикл while, описанный в подразделе 3.2.4, и отличается главным образом временем проверки условия. В этом цикле условие только проверяется
28
в конце, а не в начале (пример 3.12). Это означает, что цикл всегда будет выполняться один раз (итерация цикла), даже если условие уже выполнено (true).
выполните{
Инструкцию 1;
(.....) //Программный код
}
while(условие);
Пример 3.12: Описание цикла Do/While.
Пример реализации цикла do/while можно увидеть в примере 3.13. Цикл всегда выполняется один раз, поскольку условие проверяется только в конце цикла. В конце цикла, если целочисленная переменная i меньше или равна 10, тестируемое условие выполняется, и цикл завершается.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3".
int val; //Инициализация целочисленной переменной "val"
int f[10]; //Инициализация целочисленного массива с 11 позициями в памяти
int i = 0; //Целочисленная переменная "i", инициализируемая значением "0"
(.....) //Инициализация глобальных переменных
не нуль настройка(){
pinMode(датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "выходного"
(.....) //Программный код
}
цикл аннулирования(){
выполните{ //Инициализацию цикла
val=analogRead(датчик); //Значение аналогового вывода 3 присваивается "val"
f[i]=val; //Присвоите значение "val" массиву "f" в позиции "i".
i++; //Увеличивать значение "i" (i = i + 1)
}
пока(i<=10); //Цикл выполняется до тех пор, пока "i" не станет меньше или равно 10
(.....) //Программный код
}
Пример 3.13: Цикл Do/While - Пример.
29
3.3 Типы доступных переменных
В этом разделе будут описаны переменные, которые могут быть использованы для разработки нашего эскиза. Разница между ними и то, как мы можем выполнить их объявление, будут основной целью этого раздела. Мы должны использовать правильный тип переменной в соответствии с желаемым поведением - тем, что мы хотим сохранить и обработать. Как будет описано ниже, мы можем использовать boolean логические переменные (подраздел 3.3.1), переменные типа char и беззнаковые переменные типа unsigned char (подраздел 3.3.2), байтовые byte переменные (подраздел 3.3.3), переменные типа int и беззнаковые переменные типа unsigned int (подраздел 3.3.4), переменные типа long и беззнаковые переменные типа unsigned long (подраздел 3.3.5), переменные типа float и double (подраздел 3.3.6), а также переменные типа array и string (подраздел 3.3.7).
3.3.1 Логический boolean
Логическая переменная boolean резервирует один байт памяти и может принимать только два различных значения - true или false (пример 3.14).
логическая переменная = value; //"значение" может быть "true" или "false".
Пример 3.14: Логическая переменная boolean - описание.
Пример использования логической переменной можно увидеть в примере 3.15. Логическая
boolean переменная test инициализируется значением false, которое изменяется (true или false) во время выполнения цикла do. Например, эта переменная может хранить состояние определенного условия во время выполнения программы.
логическое значение test = false; //Логическая переменная "test" со значением "false"
int i = 0; //Целочисленная переменная "i" инициализируется значением "0"
(.....) //Инициализация глобальных переменных
void setup(){
Serial.begin(9600); //Инициализация последовательной связи -
режим вывода скорости передачи данных в бодах(3, ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
(.....) //Программный код
}
30
цикл void(){
выполните{ //
Тест инициализации цикла = !test; //Измените значение логической переменной "test"
на i++; //Увеличьте значение "i" (i = i + 1)
}
while(i<=10); //Цикл выполняется до тех пор, пока "i" не станет меньше или равно 10
(.....) //Программный код
}
Пример 3.15: Логическая переменная - Пример.
3.3.2 Char символ против Unsigned char безнакового символа
Переменная char резервирует один байт памяти и может хранить один символ. Этот символ также может быть сохранен с использованием десятичного значения от 128 до 127, представленного в американском стандартном коде для обмена информацией таблица (ASCII) [49]. Если мы используем переменную char без знака, мы не сможем представить отрицательную часть, поскольку можем хранить десятичные значения (символы) от 0 до 255
(Пример 3.16).
char v = символ //Переменная, инициализируемая символом
char v = dec //Переменная, инициализируемая десятичным значением
unsigned char v = character //Переменная, инициализируемая символом
unsigned char v = dec //Переменная, инициализируемая десятичным значением
Пример 3.16: Символ Char в сравнении с Переменными символ без знака unsigned char - Описание.
Пример использования переменных char и unsigned char можно увидеть в примере 3.17. В соответствии с таблицей ASCII [49] и как описано ранее, символы N и P также могут быть присвоены различным переменным, используя их десятичное значение.
символ example_variable = ’N’; //"N" присваивается "example_variable"
символ example_variable_1 = 78; //"N" присваивается "example_variable_1"
беззнаковый символ ex = ’P’; //"P" присваивается символу "ex"
беззнаковый символ ex_2 = 80; //"P" присваивается символу "ex_2"
Пример 3.17: Сравнение символов с Переменные с символами без знака - Пример.
31
3.3.3 Байт byte
Байтовая переменная byte резервирует один байт памяти и может хранить число без знака в диапазоне от 0 до 255 (28- 1), как описано в примере 3.18.
байтовый тест = значение; //Переменная "тест" инициализируется значением
Пример 3.18: Байтовая переменная - Описание.
Пример использования байтовой переменной можно увидеть в примере 3.19. Значение байтовой переменной может быть присвоено с использованием десятичного или двоичного представления чисел.
байт example = B00000001; //Двоичное значение присвоено "example"
байт example_1 = B00000011; //Двоичное значение присвоено "example_1"
байт example_2 = 1; //Десятичное значение "1" присваивается "example_2"
Пример 3.19: Байтовая переменная - Пример.
3.3.4 Int против Неподписанный/без знака unsigned int
Целочисленная переменная integer резервирует два байта памяти и может хранить целое значение в диапазоне от 32768 до 32767. Если мы объявим эту переменную как целое число без знака unsigned integer , у нас больше не будет отрицательной части, позволяющей хранить значения от 0 до 65535 (216 -1), как описано в примере 3.20.
int test = value; //Переменная "test", инициализируемая значением "value"
беззнаковый int test_2 = val; //Переменная "test_2", инициализируемая значением "val"
Пример 3.20: Int против Переменные без знака unsigned int - Описание.
Пример использования целых integer и беззнаковых переменных unsigned char можно увидеть в Примере 3.21. Эти переменные могут быть назначены непосредственно с помощью десятичного числа.
int example = -150; //Десятичное число "-150" присваивается "example"
int example_1 = -32768; //Десятичное число "-32768" присваивается "example_1"
unsigned int ex_3 = 65535; //Десятичное число "65535" присваивается "ex_3"
Пример 3.21: Int против Переменные типа int без знака - Пример.
32
3.3.5 Длинный long против Unsigned long
Переменная long резервирует четыре байта памяти и может хранить числовое значение в диапазоне от 2147483648 до 2147483647. Если мы объявим эту переменную беззнаковой unsigned long, у нас больше нет отрицательной части, позволяющей хранить значения от 0
до 4294967295 (232 1), как описано в примере 3.22.
long test = value; //Переменная "test" инициализируется значением "value".
беззнаковый длинный test_2 = val; //Переменная "test_2" инициализируется значением "val"
Пример 3.22: Длинный long по сравнению с Длинные переменные без знака unsigned long- Описание.
Пример использования длинных переменных long и беззнаковых переменных unsigned long можно увидеть в Примере 3.23. Эти переменные могут быть назначены непосредственно с помощью десятичного числа.
длинное значение ex = -15000000; //Десятичное значение "-15000000" присваивается "ex".
беззнаковый длинный ex_1 = 4000000; //Десятичное число "4000000" присваивается "ex_1"
Пример 3.23: Длинный по сравнению с Длинные переменные без знака - Пример.
3.3.6 Плавающая float против Двойной double
Переменная с плавающей запятой float резервирует четыре байта памяти и может хранить десятичное значение в диапазоне от 3.4028235;1038 до 3.4028235;1038 . С другой стороны, когда мы используем двойную переменную double, мы должны получить переменную более высокой точности. Однако при использовании Arduino обе переменные имеют одинаковое разрешение и занимают одинаковое пространство в памяти, пример 3.24.
float test = значение; //Переменная "test" инициализируется значением "value"
двойной тест_2 = val; //Переменная "тест_2" инициализируется значением "val"
Пример 3.24: Float против Двойные double переменные - Описание.
Пример использования переменных float и double можно увидеть в примере 3.25. Как описано ранее, оба типа переменных имеют одинаковое разрешение и занимают одинаковое пространство памяти при использовании Arduino.
33
float example = 1.589; //Десятичное значение "1.589" присваивается "примеру".
double example_1 = 1,589; //Десятичное значение "1,589" присваивается "example_1"
Пример 3.25: Значения с плавающей точкой float против Двойных double переменных - пример.
3.3.7 Массив array против Строки string
Переменная-массив - это вектор, содержащий несколько однотипных переменных, к которым можно получить доступ, используя индексный номер. Строковая переменная обычно используется для обозначения массива переменных типа char (пример 3.26).
тип переменной variable_name[index] = val; //Инициализация массива
Пример 3.26: Массив в сравнении с Строковыми переменными - описание.
Пример использования массива array и строковых string переменных можно увидеть в примере 3.27. Когда мы объявляем значение индекса, равное десяти, мы резервируем одиннадцать областей памяти, поскольку мы должны учитывать нулевой индекс.
float ex[10]; //Инициализация массива с плавающей точкой
int ex_2[] = {1,2,3,4,5}; //Массив целых чисел с присвоенным набором символов
char ex_3[11] = "Привет"; //Массив символов с присвоенным набором символов
char ex_4[] = "Песанья"; //Массив символов с присвоенным набором символов
Пример 3.27: Массив против Строковыx переменныx - Пример.
3.4 Цифровой вход/выход
В этом разделе будут описаны функции, которые могут управлять интерфейсом с цифровыми выводами, позволяя считывать (вводить) или записывать (выводить) цифровые значения. Мы
должны знать, как взаимодействовать с окружающим миром, и очень важно читать, обработайте и действуйте в соответствии с этим. Как будет описано ниже, мы можем использовать функцию pinMode() (Подраздел 3.4.1) для определения цифрового pin-кода в качестве входного или выходного, digitalWrite() функция (подраздел 3.4.2) для определения высокого HIGH (5 В) или НИЗКОГО LOW (0 В) напряжения на выводе, а функция
34
digitalRead() (подраздел 3.4.3) для считывания значения (входного напряжения), поступающего на цифровой вывод, - 0 В (НИЗКОЕ) или 5 В (ВЫСОКОЕ).
3.4.1 pinMode
Используя функцию pinMode(), можно настроить цифровые контакты в качестве входных или
выходных (пример 3.28). Это определение должно быть сделано в функции настройки.
pinMode(номер Pin-кода, режим); //"Режим" может быть "ВХОДНЫМ" или "ВЫХОДНЫМ"
Пример 3.28: pinMode() - Описание.
Пример использования функции pinMode() можно увидеть в примере 3.29. Мы можем определить цифровые контакты как ВХОДНЫЕ или ВЫХОДНЫЕ в соответствии с желаемым поведением системы.
(.....) //Инициализация глобальных переменных
аннулирует настройку(){
pinMode(3,INPUT); //Позволяет установить контакт 3 в качестве "ВХОДНОГО".
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "ВЫХОДНОГО сигнала".
(.....) //Программный код
}
oпустошить цикл(){
(.....) //Программный код
}
Пример 3.29: pinMode() - Пример.
3.4.2 Цифровая запись digitalWrite
Используя функцию digitalWrite(), можно установить выходное напряжение цифровых контактов равным 0 В (НИЗКОЕ) или 5 В (ВЫСОКОЕ), как описано в примере 3.30.
digitalWrite(пин-код, режим); //"Режим" может быть "ВЫСОКИМ" или "НИЗКИМ"
Пример 3.30: digitalWrite() - Описание.
35
Пример использования функции digitalWrite() можно увидеть в примере 3.31. Эта функция полезна для того, чтобы действовать в окружающем мире в соответствии с желаемым поведением системы.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
(.....) //Инициализация глобальных переменных
не нуль настройку(){
Serial.begin(9600); //Инициализация последовательной связи -
режим вывода скорости передачи данных в бодах
Мода крепления(датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(12,ВЫВОД); //Разрешает использовать вывод 12 в качестве "ВЫВОДА"
pinMode(13,ВЫВОД); //Разрешает использовать вывод 13 в качестве "ВЫВОДА"
(.....) //Программный код
}
процедура void loop(){
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
if(val>=500) _BOS_ //Проверьте, больше ли значение "val" или равно 500
digitalWrite(13,HIGH); //Если значение true, цифровой вывод 13 становится "ВЫСОКИМ" (5 В).
digitalWrite(12,НИЗКИЙ уровень); //Если значение равно true, цифровой вывод 12 становится "НИЗКИМ" (0 В)
}
(.....) //Программный код
}
Пример 3.31: Записать число digitalWrite() - Пример.
3.4.3 digitalRead Прочитать число
Используя функцию digitalRead(), можно считывать определенный цифровой pin -код, возвращая целое значение (пример 3.32). Если входное напряжение равно 5 В (ВЫСОКОЕ HIGH), мы получаем целое значение 1 (логическое значение 1). Если это не так, и у нас есть входное значение 0 В (НИЗКОЕ LOW), мы получаем целое значение 0 (логическое значение 0).
Целочисленная переменная = digitalRead(пин-код);
Пример 3.32: digitalRead() - Описание.
36
Пример использования функции digitalRead() можно увидеть в примере 3.33. Эта функция позволяет считывать определенные входные данные в режиме реального времени, выполнять обработку и понимать изменения в окружающем мире.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
(.....) //Инициализация глобальных переменных
аннулирует настройку(){
pinMode(датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "выходного"
(.....) //Программный код
}
цикл аннулирования(){
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
if(val==1) _BOS_ //Проверить, равен ли "val" 1 ("ВЫСОКИЙ")
digitalWrite(13,ВЫСОКИЙ); //Если значение равно true, цифровой вывод 13 становится "ВЫСОКИМ" (5 В)
}
else{
digitalWrite(13,НИЗКИЙ уровень); //Если значение false, цифровой вывод 13 становится "НИЗКИМ" (0 В)
}
(.....) //Программный код
}
Пример 3.33: Чтение числом digitalRead() - Пример.
3.5 Аналоговый вход/выход
В этом разделе будут описаны функции, которые могут управлять интерфейсом с аналоговыми выводами, позволяя выполнять чтение (ввод) и запись (вывод). Подавляющее большинство датчиков, которые мы можем использовать для получения данных из окружающего мира, являются аналоговыми, и очень важно уметь считывать их измерения. Как будет описано ниже, мы можем использовать функцию analogRead() (подраздел 3.5.1) для считывания значения напряжения, поступающего на аналоговый вывод
37
, и функцию analogWrite() (подраздел 3.5.2), которая может использоваться для эмуляции ШИМ-сигнала, как описано в подразделе 2.1.4.
3.5.1 Аналоговое считывание analogRead()
Используя функцию analogRead(), можно выполнить аналого-цифровое преобразование и считывать определенный аналоговый входной сигнал (значение напряжения) с разрешением 10 бит (пример 3.34). Разрешение в 10 бит (210 ) означает, что значение входного напряжения в диапазоне от 0 до 5 В будет преобразовано в целое значение в диапазоне от 0 до 1023.
Integer_variable = analogRead(номер вывода).;
Пример 3.34: analogRead() - Описание.
Пример использования функции analogRead() можно увидеть в примере 3.35. Эта функция может быть полезна для считывания аналоговых входных данных из окружающего мира, таких как в качестве датчика, для выполнения обработки и обеспечения желаемого поведения системы.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int val; //Инициализация целочисленной переменной "val"
(.....) //Инициализация глобальных переменных
аннулирует настройку(){
pinMode(датчик,ВХОД); //Позволяет установить вывод 3 в качестве "ВХОДНОГО сигнала".
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "ВЫХОДНОГО сигнала".
(.....) //Программный код
}
опустеет цикл(){
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
if(val>=500) _BOS_ //Проверить, больше ли значение "val" или равно 500
digitalWrite(13,ВЫСОКИЙ); //Если значение равно true, цифровой вывод 13 становится "ВЫСОКИМ" (5 В)
}
(.....) //Программный код
}
Пример 3.35:Чтение Аналогово сигнала analogRead() - Пример.
38
3.5.2 Записать аналог analogWrite
Используя функцию analogWrite(), можно эмулировать ШИМ-сигнал с постоянной частотой приблизительно 490 Гц (пример 3.36). Мы можем изменять полученное эквивалентное напряжение постоянного тока, изменяя рабочий цикл сигнала, как описано в Подразделe 2.1.4.
Аналоговая запись(номер вывода, значение); //"значение" от 0 (0 В) до 255 (5 В)
Пример 3.36: Записать аналог analogWrite() - Описание.
Пример использования функции analogWrite() приведен в примере 3.37. Эта функция позволяет изменять выходное напряжение с помощью ШИМ-сигнала и может использоваться в различных приложениях, например, для обеспечения напряжения, пропорционального конкретному входу.
int sensor=3; //Целочисленная переменная "sensor" инициализируется значением "3"
int out=9; //Целочисленная переменная "out" инициализируется значением "9"
int val; //Инициализация целочисленной переменной "val"
(.....) //Инициализация глобальных переменных
void setup(){
Serial.begin(9600); //Инициализация последовательной связи - скорость передачи данных в бодах
pinMode(датчик,ВХОД); //Разрешает использовать вывод 3 в качестве "входного сигнала"
pinMode(13,ВЫХОД); //Разрешает использовать вывод 13 в качестве "выходного сигнала"
(.....) //Программный код
}
void loop(){
val=analogRead(датчик); //Показание аналогового вывода 3 присвоено значению "val".
if(val>=500) _BOS_ //Проверьте, больше ли значение "val" или равно 500
для аналоговой записи(out,255); //Если значение true, аналоговый вывод 9 становится "ВЫСОКИМ" (5 В)
}
else{
analogWrite(out,0); //Если значение false, аналоговый вывод 9 становится "НИЗКИМ" (0 В)
}
(.....) //Программный код
}
Пример 3.37: Записать аналог analogWrite() - Пример.
39
3.6 Время
В этом разделе будут описаны функции, которые можно использовать для подсчета времени или для выполнения временных задержек. Как будет описано ниже, мы можем использовать функцию millis() (Подраздел 3.6.1) для возврата количества времени в миллисекундах с момента запуска программы, функция micros() (Подраздел 3.6.2) для возврата количества времени в микросекундах с момента запуска программы, функция delay() (Подраздел 3.6.3), который может быть использован для выполнения временной задержки в миллисекундах в запущенной программе, и функция delayMicroseconds() (подраздел 3.6.4), которая может быть использована для выполнения временной задержки в микросекундах в запущенной программе.
3.6.1 Миллисекунды millis
Используя функцию millis(), можно вернуть количество времени в миллисекундах с момента запуска программы (пример 3.38). Счетчик переполнится (вернется к нулю) примерно через 50 дней после выполнения при использовании переменной unsigned long.
unsigned long time = millis(); //"время" будет указано в миллисекундах
Пример 3.38: миллисекунды millis() - Описание.
Пример использования функции millis() можно увидеть в примере 3.39. Как указывалось
ранее, эта функция возвращает время в миллисекундах с момента запуска программы.
долгая без знака время; //Длинная переменная "time" без знака
(.....) //Инициализация глобальных переменных
void setup(){
(.....) //Программный код
}
void loop(){
time = millis(); //Время в миллисекундах с момента запуска программы
(.....) //Программный код
}
Пример 3.39: миллис millis() - Пример.
40
3.6.2 микросекунды micros
Используя функцию micros(), можно вернуть количество времени в микросекундах с момента запуска программы (пример 3.40). Счетчик переполнится (вернется к нулю) примерно через 70 минут после выполнения при использовании переменной unsigned long длинной без знака.
долгое время без знака = micros(); //"время" будет указано в микросекундах
Пример 3.40: микросекунды micros() - Описание.
Пример использования функции micros() можно увидеть в примере 3.41. Как указывалось ранее, эта функция возвращает время в микросекундах с момента запуска программы.
беззнаковое длительное время; //Беззнаковая длинная переменная "time".
(.....) //Инициализация глобальных переменных
void setup(){
(.....) //Программный код
}
void loop(){
time = micros(); //Время в микросекундах с момента запуска программы
(.....) //Программный код
}
Пример 3.41: микросекунды micros() - Пример.
3.6.3 задержка delay
Используя функцию delay(), можно выполнить заданное количество миллисекунд временной задержки в запущенной программе (пример 3.42). Например, эта функция может быть полезна для поддержания состояния в течение определенного периода времени.
задержка(t); //Временная задержка в миллисекундах задается символом "t"
Пример 3.42: delay() - Описание.
41
Пример использования функции delay() можно увидеть в примере 3.43. Это может быть полезно для приостановки работы программы на заданный интервал времени в соответствии с желаемым поведением системы.
int led=13; //Целочисленная переменная "led" инициализируется значением "13".
(.....) //Инициализация глобальных переменных
аннулирует настройку(){
Режим вывода (светодиод,ВЫХОД); //Позволяет установить вывод 13 в качестве "выходного"
(.....) //Программный код
}
void loop(){
Цифровая запись(светодиод,ВЫСОКИЙ УРОВЕНЬ); //Цифровой вывод 13 становится "ВЫСОКИМ" (5 В)
задержка(200); //Задержка на 200 миллисекунд
цифровая запись (индикатор, НИЗКИЙ уровень); //Цифровой вывод 13 переключает задержку на "НИЗКИЙ уровень" (0 В)
задержка (600); //Задержка на 600 миллисекунд
(.....) //Программный код
}
Пример 3.43: задержка delay() - Пример.
3.6.4 Задержка в микросекундах delayMicroseconds()
С помощью функции delayMicroseconds() можно выполнить указанную количество микросекунд временной задержки в запущенной программе (пример 3.44). Например, как описано ранее, эта функция может быть полезна для поддержания состояния в течение определенного периода времени.
delayMicroseconds(t); //Временная задержка в микросекундах задается через "t"
Пример 3.44: задержка в Микросекундах delayMicroseconds() - Описание.
Иллюстрацию использования функции delayMicroseconds() можно увидеть в Примере 3.45. Это может быть полезно для приостановки работы программы на заданный интервал времени в соответствии с желаемым поведением системы.
42
(.....) // Инициализация глобальных переменных
void setup(){
pinMode(13,ВЫХОД); //Позволяет установить вывод 13 в качестве "выходного"
(.....) //Программный код
}
void loop(){
digitalWrite(13,HIGH); //Цифровой вывод 13 становится "ВЫСОКИМ" (5 В)
Задержка в микросекундах(200); //Задержка в 200 микросекунд
цифровая запись (13,НИЗКИЙ уровень); //Цифровой вывод 13 переключается в положение "НИЗКИЙ уровень" (0 В)
задержка в микросекундах(600); //Задержка в 600 микросекунд
(.....) //Программный код
}
Пример 3.45: задержка в микросекундах delayMicroseconds() - Пример.
Свидетельство о публикации №125123103106