Arduino и совместимые языки программирования | GeekBrains
Для тех, кто не разделяет железо и код.
https://d2xzmw6cctk25h.cloudfront.net/post/1017/og_cover_image/d546216a36e4dcd612076245e1060f61
Начать свой путь в IT бывает очень сложно хотя бы просто потому, что глядя на окружающие технологии невозможно отделить «железный» интерес от программного. С одной стороны — желание создать устройство с безупречным внешним видом, множеством датчиков и безграничными возможностями, с другой — таинство обработки данных, стремление максимально увеличить быстродействие, не пренебрегая функциональностью. Arduino — первый шаг к большим изобретениям, не требующий ни глубоких знаний схемотехники, ни опыта в программировании.
Что такое Arduino
Если называть вещи своими именами, то Arduino — это конструктор для тех, кому надоело созидать бесполезные образы и захотелось хоть немного наделить их жизнью. В самом простейшем случае Arduino — печатная плата, на которой расположен контроллер, кварцевый генератор, АЦП/ЦАП, несколько разъёмов, диодов и кнопок. Остальное — дело рук хозяина: хотите — создавайте робота, хотите — программно-аппаратную платформу для «умного» дома, ну или забудьте про практическую пользу и развлекайтесь.
Конечно, в зависимости от того. насколько далеко вы хотите зайти в своих экспериментах, хотите ли вы получать фильтрованное удовольствие или сделать из Arduino платформу для собственного заработка, вам придётся совершенствоваться и в проектировании железа, и в изучении языков программирования. О последнем сегодня чуть подробнее.
Arduino достаточно ограниченная платформа в плане возможностей программирования, особенно в сравнении с Raspberry Pi. В силу того, что порог входа неприлично низкий (базовый Tutorial занимает 3 листа формата A4), то рассчитывать на изобилие языков без подключения дополнительных модулей не приходится. За основу здесь принят C/C++, но с использованием различных IDE и библиотек вы получите доступ к оперированию Python, C#, Go, а также таким детским развлечениям, как Snap! и ArduBlock. О том как, когда и кому их использовать, поговорим далее.
C/C++
Базовый язык платформы Arduino, который с некоторыми доработками и упрощениями используется в стандартной программной оболочке. Найти все доступные команды «для новичка» можно здесь, но никто не мешает вам воспользоваться исходными возможностями языка C++, никаких надстроек не потребуетс. Если же есть желание поиграть с «чистым» C, то к вашим услугам программа WinAVR, предназначенная, как следует из названия, для взаимодействия ОС Windows и МК серии AVR, которые и используются на Arduino. Более подробное руководство можете прочитать вот здесь.
Использование C/C++ рекомендуется тем, кто уже имеет представление о программировании, выучил в школе пару языков и хочет создать на Arduino что-то большее, чем светодиодную «мигалку» или простую машинку.
Ardublock
Временно отойдем от языков взрослых к любимому ребятней языку Scratch, а вернее к его адаптации — Ardublock. Здесь всё тоже самое, но с адаптацией к вашей платформе: цветные блоки, конструктор, русские названия, простейшая логика. Такой вариант здорово подойдет даже тем, кто с программированием не знаком вовсе. Подобно тому, как в языке Logo вы можете перемещать виртуальную черепашку по виртуальной плоскости, здесь с помощью нехитрых операций вы можете заинтересовать ребенка реальной интерпретацией его программных действий.
Да, кстати, для использования необходимо на вашу стандартную среду Arduino IDE установить плагин. Последние версии лучше не хватать, они довольно сложные, для начала подойдет датированная концом 2013 года. Для установки скачанный файл переименовываем в «ardublock-all» и запихиваем в папку «Мои документы/Arduino/tools/ArduBlockTool/tool». Если её не существует – создаем. Если что-то не поняли, то вот здесь более подробно.
Snap!
По сравнению с Ardublock, Snap! имеет расширенные возможности в виде дополнительных блоков, возможности использования списков и функций. То есть Snap! в общем и целом уже похож на взрослый язык программирования, не считая, что вам по прежнему необходимо играть в конструктор кода.
Для того, чтобы использовать этот язык, придется сходить на сайт snap4arduino.org и скачать необходимые компоненты для вашей ОС. Инструкции по установке, использованию и видеопримеры ищите здесь же.
Рекомендуется младшей возрастной группе, тем, кто учил программирование так давно, что уже ничего не помнит и тем, кто хочет завлечь своего ребенка в IT через Scratch и Snap!.
Python
Формально программировать на Arduino вы можете используя хоть язык Piet, просто потому что при должном упорстве вы скомпилируете в машинный код что угодно. Но в силу того, что Python — один из наиболее популярных языков с практически оптимальным сочетанием сложность\возможности, то обойти стороной его применяемость в Arduino было бы нелепо. Начать изучение Python вы можете с нашего бесплатного интенсива “Основы языка Python”.
Итак, для этого вам понадобится библиотеки PySerial (ранее, возможно, вы использовали её для общения с портами компьютера) и vPython. О том, как правильно всё настроить и заставить в конечном счёте работать, можете соответственно почитать здесь и здесь.
Go и другие языки.
Подобно тому, как Arduino взаимодействует с Python через библиотеку PySerial, он может взаимодействовать и с Go, и c Java, и с HTML, и с чем только захотите. Arduino — достаточно популярная платформа, чтобы такой банальный вопрос, как выбор удобного языка, не остановил очередного исследователя. Единственное, что требуется от владельца этой маленькой платы — задумать что-нибудь удивительно интересное, а удобный инструмент неизбежно найдётся.
Рассмотрим пример минимально возможной программы на C++ для Arduino, которая ничего не делает:
void setup() { } void loop() { }
Разберёмся что здесь написано и почему это обязательно: почему нельзя обойтись просто пустым файлом.
Из чего состоит программа
Для начала стоит понять, что программу нельзя читать и писать как книгу:
от корки до корки, сверху вниз, строку за строкой. Любая программа состоит
из отдельных блоков. Начало блока кода в C/C++ обозначается левой фигурной
скобкой {
, его конец — правой фигурной скобкой }
.
Блоки бывают разных видов и какой из них когда будет исполняться зависит от внешних условий. В примере минимальной программы вы можете видеть 2 блока. В этом примере блоки называются определением функции. Функция — это просто блок кода с заданным именем, которым кто-то затем может пользоваться из-вне.
В данном случае у нас 2 функции с именами setup
loop
. Их присутствие обязательно
в любой программе на C++ для Arduino. Они могут ничего и не делать, как в нашем случае,
но должны быть написаны. Иначе на стадии компиляции вы получите ошибку.Классика жанра: мигающий светодиод
Давайте теперь дополним нашу программу так, чтобы происходило хоть что-то. На Arduino, к 13-му пину подключён светодиод. Им можно управлять, чем мы и займёмся.
void setup() { pinMode(13, OUTPUT); } void loop() { digitalWrite(13, HIGH); delay(100); digitalWrite(13, LOW); delay(900); }
Скомпилируйте, загрузите программу. Вы увидите, что каждую секунду светодиод на плате помигивает. Разберёмся почему этот код приводит к ежесекундному миганию.
В наши ранее пустые функции мы добавили несколько выражений. Они были размещены между
фигурными скобками функций setup
и loop
. В setup
появилось одно выражение, а в loop
сразу 4.
Каждое выражение — это приказ процессору сделать нечто. Выражения в рамках одного блока исполняются одно за другим, строго по порядку без всяких пауз и переключений. То есть, если мы говорим об одном конкретном блоке кода, его можно читать сверху вниз, чтобы понять что делается.
Теперь давайте поймём в каком порядке исполняются сами блоки, т.е. функции setup
и loop
.
Не задумывайтесь пока что значат конкретные выражения, просто понаблюдайте за порядком.
Как только Arduino включается, перепрошивается или нажимается кнопка
RESET
, «нечто» вызывает функциюsetup
. То есть заставляет исполняться выражения в ней.Как только работа
setup
завершается, сразу же «нечто» вызывает функциюloop
.Как только работа
loop
завершается, сразу же «нечто» вызывает функциюloop
ещё раз и так до бесконечности.
Если пронумеровать выражения по порядку, как они исполняются, получится:
void setup() { pinMode(13, OUTPUT); ❶ } void loop() { digitalWrite(13, HIGH); ❷ ❻ ❿ delay(100); ❸ ❼ … digitalWrite(13, LOW); ❹ ❽ delay(900); ❺ ❾ }
Ещё раз напомним, что не стоит пытаться воспринимать всю программу, читая сверху вниз.
Сверху вниз читается только содержимое блоков. Мы вообще можем поменять порядок объявлений setup
и loop
.
void loop() { digitalWrite(13, HIGH); ❷ ❻ ❿ delay(100); ❸ ❼ … digitalWrite(13, LOW); ❹ ❽ delay(900); ❺ ❾ } void setup() { pinMode(13, OUTPUT); ❶ }
Результат от этого не изменится ни на йоту: после компиляции вы получите абсолютно эквивалентный бинарный файл.
Что делают выражения
Теперь давайте попробуем понять почему написанная программа приводит в итоге к миганию светодиода.
Как известно, пины Arduino могут работать и как выходы и как входы. Когда мы хотим чем-то управлять, то есть выдавать сигнал, нам нужно перевести управляющий пин в состояние работы на выход. В нашем примере мы управляем светодиодом на 13-м пине, поэтому 13-й пин перед использованием нужно сделать выходом.
Это делается выражением в функции setup
:
pinMode(13, OUTPUT);
Выражения бывают разными: арифметическими, декларациями, определениями, условными и т.д. В данном
случае мы в выражении осуществляем вызов функции. Помните? У нас есть свои функции setup
и loop
, которые вызываются чем-то, что мы назвали «нечто». Так вот теперь мы вызываем функции,
которые уже написаны где-то.
Конкретно в нашем setup
мы вызываем функцию с именем pinMode
. Она устанавливает заданный по номеру пин
в заданный режим: вход или выход. О каком пине и о каком режиме идёт речь указывается нами в круглых
скобках, через запятую, сразу после имени функции. В нашем случае мы хотим, чтобы 13-й пин работал
как выход.
означает выход, INPUT
— вход.
Уточняющие значения, такие как 13
и OUTPUT
называются аргументами функции. Совершенно не обязательно,
что у всех функций должно быть по 2 аргумента. Сколько у функции аргументов зависит от сути функции,
от того как её написал автор. Могут быть функции с одним аргументом, тремя, двадцатью; функции могут
быть без аргументов вовсе. Тогда для их вызова круглые скобка открывается и тут же закрывается:
noInterrupts();
На самом деле, вы могли заметить, наши функции setup
и loop
также не принимают никакие аргументы.
И загадочное «нечто» точно так же вызывает их с пустыми скобками в нужный момент.
Вернёмся к нашему коду. Итак, поскольку мы планируем вечно мигать светодиодом, управляющий пин должен
один раз быть сделан выходом и затем мы не хотим вспоминать об этом. Для этого идеологически и
предназначена функция setup
: настроить плату как нужно, чтобы затем с ней работать.
Перейдём к функции loop
:
void loop() { digitalWrite(13, HIGH); delay(100); digitalWrite(13, LOW); delay(900); }
Она, как говорилось, вызывается сразу после setup
. И вызывается снова и снова как только сама заканчивается.
Функция loop
называется основным циклом программы и идеологически предназначена для выполнения полезной
работы. В нашем случае полезная работа — мигание светодиодом.
Пройдёмся по выражениям по порядку. Итак, первое выражение — это вызов встроенной функции digitalWrite
.
Она предназначена для подачи на заданный пин логического нуля (LOW
, 0 вольт) или логической единицы (HIGH
, 5 вольт)
В функцию digitalWrite
передаётся 2 аргумента: номер пина и логическое значение. В итоге, первым делом
мы зажигаем светодиод на 13-м пине, подавая на него 5 вольт.
Как только это сделано процессор моментально приступает к следующему выражению. У нас это вызов функции delay
.
Функция delay
— это, опять же, встроенная функция, которая заставляет процессор уснуть на определённое время.
Она принимает всего один аргумент: время в миллисекундах, которое следует спать. В нашем случае это 100 мс.
Пока мы спим всё остаётся как есть, т.е. светодиод продолжает гореть. Как только 100 мс истекают, процессор
просыпается и тут же переходит к следующему выражению. В нашем примере это снова вызов знакомой нам встроенной
функции digitalWrite
. Правда на этот раз вторым аргументом мы передаём значение LOW
. То есть устанавливаем
на 13-м пине логический ноль, то есть подаём 0 вольт, то есть гасим светодиод.
После того, как светодиод погашен мы приступаем к следующему выражению. И снова это вызов функции delay
.
На этот раз мы засыпаем на 900 мс.
Как только сон окончен, функция loop
завершается. По факту завершения «нечто» тут же вызывает её ещё раз
и всё происходит снова: светодиод поджигается, горит, гаснет, ждёт и т.д.
Если перевести написанное на русский, получится следующий алгоритм:
Поджигаем светодиод
Спим 100 миллисекунд
Гасим светодиод
Спим 900 миллисекунд
Переходим к пункту 1
Таким образом мы получили Arduino с маячком, мигающим каждые 100 + 900 мс = 1000 мс = 1 сек.
Что можно изменить
Давайте пользуясь только полученными знаниями сделаем несколько вариаций программы, чтобы лучше понять принцип.
Вы можете подключить внешний светодиод или другое устройство, которым нужно «мигать» на другой пин. Например, на 5-й. Как в этом случае должна измениться программа? Мы должны всюду, где обращались к 13-му пину заменить номер на 5-й:
void setup() { pinMode(5, OUTPUT); } void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); }
Компилируйте, загружайте, проверяйте.
Что нужно сделать, чтобы светодиод мигал 2 раза в секунду? Уменьшить время сна так, чтобы в сумме получилось 500 мс:
void setup() { pinMode(5, OUTPUT); } void loop() { digitalWrite(5, HIGH); delay(50); digitalWrite(5, LOW); delay(450); }
Как сделать так, чтобы светодиод при каждом «подмигивании» мерцал дважды? Нужно поджигать его дважды с небольшой паузой между включениями:
void setup() { pinMode(5, OUTPUT); } void loop() { digitalWrite(5, HIGH); delay(50); digitalWrite(5, LOW); delay(50); digitalWrite(5, HIGH); delay(50); digitalWrite(5, LOW); delay(350); }
Как сделать так, чтобы в устройстве были 2 светодиода, которые мигали бы каждую секунду поочерёдно? Нужно
общаться с двумя пинами и работать в loop
то с одним, то с другим:
void setup() { pinMode(5, OUTPUT); pinMode(6, OUTPUT); } void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); digitalWrite(6, HIGH); delay(100); digitalWrite(6, LOW); delay(900); }
Как сделать так, чтобы в устройстве были 2 светодиода, которые переключались бы на манер железнодорожного светофора: горел бы то один то другой? Нужно просто не выключать горящий светодиод тут же, а дожидаться момента переключения:
void setup() { pinMode(5, OUTPUT); pinMode(6, OUTPUT); } void loop() { digitalWrite(5, HIGH); digitalWrite(6, LOW); delay(1000); digitalWrite(5, LOW); digitalWrite(6, HIGH); delay(1000); }
Можете проверить другие идеи самостоятельно. Как видите, всё просто!
О пустом месте и красивом коде
В языке C++ пробелы, переносы строк, символы табуляции не имеют большого значения для компилятора. Там где стоит пробел, может быть перенос строки и наоборот. На самом деле 10 пробелов подряд, 2 переноса строки и ещё 5 пробелов — это всё эквивалент одного пробела.
Пустое пространство — это инструмент программиста, с помощью которого можно или сделать программу понятной и наглядной, или изуродовать до неузнаваемости. Например, вспомним программу для мигания светодиодом:
void setup() { pinMode(5, OUTPUT); } void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); }
Мы можем изменить её так:
void setup( ) { pinMode(5, OUTPUT); } void loop () { digitalWrite(5,HIGH); delay(100 ) ; digitalWrite(5,LOW); delay(900); }
Всё, что мы сделали — немного «поработали» с пустым пространством. Теперь можно наглядно видеть разницу между стройным кодом и нечитаемым.
Чтобы следовать негласному закону оформления программ, который уважается на форумах, при чтении другими людьми, легко воспринимается вами же, следуйте нескольким простым правилам:
1. Всегда, при начале нового блока между {
и }
увеличивайте отступ. Обычно используют 2 или 4
пробела. Выберите одно из значений и придерживайтесь его всюду.
Плохо:
void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); }
Хорошо:
void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); }
2. Как и в естественном языке: ставьте пробел после запятых и не ставьте до.
Плохо:
digitalWrite(5,HIGH); digitalWrite(5 , HIGH); digitalWrite(5 ,HIGH);
Хорошо:
digitalWrite(5, HIGH);
3. Размещайте символ начала блока {
на новой строке на текущем уровне отступа или в конце предыдущей.
А символ конца блока }
на отдельной строке на текущем уровне отступа:
Плохо:
void setup() { pinMode(5, OUTPUT); } void setup() { pinMode(5, OUTPUT); } void setup() { pinMode(5, OUTPUT); }
Хорошо:
void setup() { pinMode(5, OUTPUT); } void setup() { pinMode(5, OUTPUT); }
4. Используйте пустые строки для разделения смысловых блоков:
Хорошо:
void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); digitalWrite(6, HIGH); delay(100); digitalWrite(6, LOW); delay(900); }
Ещё лучше:
void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); digitalWrite(6, HIGH); delay(100); digitalWrite(6, LOW); delay(900); }
О точках с запятыми
Вы могли заинтересоваться: зачем в конце каждого выражения ставится точка с запятой? Таковы правила C++.
Подобные правила называются синтаксисом языка. По символу ;
компилятор понимает где заканчивается
выражение.
Как уже говорилось, переносы строк для него — пустой звук, поэтому ориентируется он на этот знак препинания. Это позволяет записывать сразу несколько выражений в одной строке:
void loop() { digitalWrite(5, HIGH); delay(100); digitalWrite(5, LOW); delay(900); }
Программа корректна и эквивалентна тому, что мы уже видели. Однако писать так — это дурной тон. Код гораздо сложнее читается. Поэтому если у вас нет 100% веских причин писать в одной строке несколько выражений, не делайте этого.
О комментариях
Одно из правил качественного программирования: «пишите код так, чтобы он был настолько понятным, что не нуждался бы в пояснениях». Это возможно, но не всегда. Для того, чтобы пояснить какие-то не очевидные моменты в коде его читателям: вашим коллегам или вам самому через месяц, существуют так называемые комментарии.
Это конструкции в программном коде, которые полностью игнорируются компилятором и имеют значение только для читателя. Комментарии могут быть многострочными или однострочными:
/* Функция setup вызывается самой первой, при подаче питания на Arduino А это многострочный комментарий */ void setup() { // устанавливаем 13-й пин в режим вывода pinMode(13, OUTPUT); } void loop() { digitalWrite(13, HIGH); delay(100); // спим 100 мс digitalWrite(13, LOW); delay(900); }
Как видите, между символами /*
и */
можно писать сколько угодно строк комментариев.
А после последовательности /
/
комментарием считается всё, что следует до конца строки.
Итак, надеемся самые основные принципы составления написания программ стали понятны. Полученные знания позволяют программно управлять подачей питания на пины Arduino по определённым временны́м схемам. Это не так уж много, но всё же достаточно для первых экспериментов.
Языки программирования [Амперка / Вики]
Итак, у вас есть процессор. Вы наверняка понимаете, что процессор можно как-то запрограммировать, чтобы он делал то, что вы хотите. Для того, чтобы была выполнена полезная работа необходимо (а) написать полезную программу и (б) отдать её процессору для исполнения.
В целом, не важно какой именно у вас процессор: последний Intel Pentium в вашем ноутбуке или микроконтроллер на плате Arduino. Принципы написания программы, т.е. программирования, в обоих случаях одни и те же. Различается лишь быстродействие и объём возможностей по работе с другими устройствами.
Что такое программа и куда её писать
Процессор несмотря на всю сложность производства, по сути своей, довольно простая и прямолинейная вещь. Думать он не умеет. Он умеет лишь слепо, байт за байтом исполнять инструкции, которые ему подсунули. Можно привести грубый пример последовательности инструкций:
Байт инструкции | Что он означает для процессора |
---|---|
00001001 | означает: взять следующий байт и запомнить его в ячейке №1 |
00000110 | …это как раз следующий байт, который мы запоминаем в ячейке №1: число 5 |
00011001 | означает: отнять от значения в ячейке №1 единицу и оставить там обновлённый результат |
00101001 | означает: сравнить значение в ячейке №1 с нулём и если оно ноль — перепрыгнуть через столько байт, сколько указано в следующем байте |
00000100 | …если результат был ноль, мы хотим прыгнуть через 4 байта, к предпоследней инструкции |
10000011 | означает, что мы хотим вывести на экран символ, код которого записан в следующем байте |
01000001 | …букве «A» как раз соответствует этот код |
00101000 | означает, что мы хотим прыгнуть назад на столько байт, сколько указано в следующем байте |
00000110 | …прыгать будем на 6 байт назад, к инструкции №3 |
10000011 | означает, что мы хотим вывести на экран символ, код которого записан в следующем байте |
00100001 | …знаку «!» как раз соответствует этот код |
В результате исполнения такой последовательности инструкций на экран будет выведена паническая фраза «АААА!».
Довольно много кода для такой простой цели! Понятно, что если бы все программы писались вот так, непосредственно, разработка сложных продуктов занимала бы века.
Зачем нужны языки программирования
Для упрощения задачи в миллион раз были придуманы языки программирования. Их очень много и даже из тех, что постоянно на слуху можно быстро вспомнить десяток-другой: Assembler, C, C++, C#, Java, Python, Ruby, PHP, Scala, JavaScript.
Программы на этих языках гораздо ближе к естественному языку человека. А следовательно их проще, быстрее и приятнее писать, а что самое главное, их гораздо проще читать: вам сразу после написания, вам через год или вашему коллеге.
Проблема в том, что такие языки не понятны процессору и перед тем как отдать ему эту программу, её нужно скомпилировать: перевести с естественного языка в те самые инструкции в виде нулей и единиц. Этим занимаются программы, которые называются компиляторами. У каждого языка, если только он не остался на уровне фантазий, есть свой компилятор. Для популярных языков их обычно несколько на выбор, от разных производителей и для разных платформ. Большинство из них свободно доступно в интернете.
Итак, есть программы на вполне понятном человеку языке: их ещё называют «исходным кодом», просто «кодом» или «исходниками». Они пишутся в простые текстовые файлы с помощью любого текстового редактора, хоть с помощью notepad. Затем они превращаются в понятные процессору наборы нулей и единиц с помощью компилятора: компилятор получает на вход исходный код, а на выходе создаёт бинарный исполняемый файл, тот самый, понятный процессору.
Бинарные файлы не пригодны для чтения и предназначены,
в общем, лишь для исполнения процессором. Они могут иметь разный тип в зависимости от того для чего получены: .exe
— это программы для
Windows, .hex
— программы для исполнения микроконтроллером типа Arduino и т.п.
Почему же существует столько языков программирования и в чём разница?
Почему? Потому что на Земле много людей и компаний, и многие считали, что могут сделать лучше всех: удобнее, понятнее, быстрее, стройнее.
В чём разница: разные языки — это разный баланс скорости написания, понятности при чтении и скорости исполнения.
Посмотрим на одну и ту же программу, которая выводит на экран песенку про 99 бутылок пива на разных языках программирования.
Например, язык Perl. Пишется быстро; понять, что имел в виду программист невозможно; исполняется медленно:
sub b{$n=99-@_-$_||No;"$n bottle"."s"x!!--$n." of beer"};$w=" on the wall"; die map{b."$w,\n".b.",\nTake one down, pass it around,\n".b(0)."$w.\n\n"}0..98
Язык Java. Пишется относительно долго; читается просто; исполняется довольно быстро, но занимает много памяти:
class bottles { public static void main(String args[]) { String s = "s"; for (int beers=99; beers>-1;) { System.out.print(beers + " bottle" + s + " of beer on the wall, "); System.out.println(beers + " bottle" + s + " of beer, "); if (beers==0) { System.out.print("Go to the store, buy some more, "); System.out.println("99 bottles of beer on the wall.\n"); System.exit(0); } else System.out.print("Take one down, pass it around, "); s = (--beers == 1) ? "" : "s"; System.out.println(beers + " bottle" + s + " of beer on the wall.\n"); } } }
Язык Assembler. Пишется долго; читается сложно; исполняется очень быстро:
code segment assume cs:code,ds:code org 100h start: ; Main loop mov cx, 99 ; bottles to start with loopstart: call printcx ; print the number mov dx,offset line1 ; print the rest of the first line mov ah,9 ; MS-DOS print string routine int 21h call printcx ; print the number mov dx,offset line2_3 ; rest of the 2nd and 3rd lines mov ah,9 int 21h dec cx ; take one down call printcx ; print the number mov dx,offset line4 ; print the rest of the fourth line mov ah,9 int 21h cmp cx, 0 ; Out of beer? jne loopstart ; if not, continue int 20h ; quit to MS-DOS ; subroutine to print CX register in decimal printcx: mov di, offset numbufferend ; fill the buffer in from the end mov ax, cx ; put the number in AX so we can divide it printcxloop: mov dx, 0 ; high-order word of numerator - always 0 mov bx, 10 div bx ; divide DX:AX by 10. AX=quotient, DX=remainder add dl,'0' ; convert remainder to an ASCII character mov [ds:di],dl ; put it in the print buffer cmp ax,0 ; Any more digits to compute? je printcxend ; if not, end dec di ; put the next digit before the current one jmp printcxloop ; loop printcxend: mov dx,di ; print, starting at the last digit computed mov ah,9 int 21h ret ; Data line1 db ' bottles of beer on the wall,',13,10,'$' line2_3 db ' bottles of beer,',13,10,'Take one down, pass it around,',13,10,'$' line4 db ' bottles of beer on the wall.',13,10,13,10,'$' numbuffer db 0,0,0,0,0 numbufferend db 0,'$' code ends end start
На чём программируется Arduino
Если говорить об Arduino или о микроконтроллерах от компании Atmel, на каком языке можно писать программы для них? Теоретический ответ: на любом. Но на практике, выбор ограничивается языками Assembler, C и C++. Это связанно с тем, что в сравнении с настольным компьютером у них очень ограниченные ресурсы. Килобайты памяти, а не гигабайты. Мегагерцы на процессоре, а не гигагерцы. Это плата за дешевизну и энергоэффективность.
Поэтому нужен язык, который может компилироваться и исполняться эффективно. То есть переводиться в те самые нули и единицы из инструкций как можно оптимальнее, без расходов драгоценных инструкций и памяти в пустую. Подобной эффективностью как раз и обладают названные языки. Используя их даже в узких рамках ресурсов микроконтроллера, можно писать богатые возможностями программы, которые работают быстро.
Assembler, как вы видели, нельзя назвать самым простым и элегантным и, как результат, флагманским языком для Arduino является C/C++.
Во многих источниках говорится, что Arduino программируется на языке Arduino, Processing, Wiring. Это не совсем корректное утверждение. Arduino программируется на C/C++, а то, что называется этими словами — это просто удобный «обвес», который позволяет решать многие типичные задачи, не изобретая велосипед каждый раз.
Почему C и C++ упоминаются в одном предложении? C++ — это надстройка над C. Всякая программа на C является корректной программой для C++, но не наоборот. Вы можете пользоваться и тем и другим. Чаще всего вы даже не будете задумываться о том, что используете, решая текущую задачу.
Ближе к делу: первая программа
Давайте напишем первую программу для Arduino и заставим плату её исполнять. Вам необходимо создать текстовый файл с исходным кодом, скомпилировать его и подсунуть полученный бинарный файл микроконтроллеру на плате.
Пойдём по порядку. Напишем исходный код. Можно написать его в блокноте или любом другом редакторе. Однако для того, чтобы работа была удобной, существуют так называемые среды разработки (IDE: Integrated Development Environment). Они в виде единого инструмента предоставляют и текстовый редактор с подсветкой и подсказками, и компилятор, запускаемый по кнопке, и много других радостей. Для Arduino такая среда называется Arduino IDE. Она свободно доступна для скачивания на официальном сайте.
Установите среду и запустите её. В появившемся окне вы увидите: большая часть места отдана текстовому редактору. В него и пишется код. Код в мире Arduino ещё называют скетчем.
Итак, давайте напишем скетч, который ничего не делает. То есть минимально возможную правильную программу на C++, которая просто прожигает время.
void setup() { } void loop() { }
Не будем пока заострять внимание на значении написанного кода. Скомпилируем его. Для этого в Arduino IDE, на панели инструментов есть кнопка «Verify». Нажмите её и через несколько секунд бинарный файл будет готов. Об этом возвестит надпись «Done compiling» под текстовым редактором.
В результате, у нас получился бинарный файл с расширением .hex
, который может исполнять микроконтроллер.
Теперь необходимо подсунуть его Arduino. Этот процесс называется загрузкой, прошивкой или заливкой. Для выполнения загрузки в Arduino IDE, на панели инструментов есть кнопка «Upload». Соедините Arduino с компьютером через USB-кабель, нажмите «Upload» и через несколько мгновений программа будет загружена в Arduino. При этом программа, которая была там ранее будет стёрта.
Об успешной прошивке возвестит надпись «Done Uploading».
Если при попытке загрузки вы столкнулись с ошибкой убедитесь, что:
В меню Tools → Board выбран тот порт, к которому действительно подключена Arduino. Можете повставлять и повынимать USB-кабель, чтобы понять какой порт появляется и исчезает: это и есть Arduino.
Вы установили необходимые драйверы для Arduino. Это необходимо для Windows, не требуется под Linux и необходимо только для старых плат до Arduino Duemilanove на MacOS.
Поздравляем! Вы прошли весь путь от чистого листа до работающей программы в Arduino. Пусть она ничего и не делает, но это уже успех.
Ardublock для Arduino – язык визуального программирования
Ardublock – это графический язык программирования для Ардуино, предназначенный для начинающих. Эта среда достаточно проста в использовании, ее легко установить, она практически полностью переведена на русский язык. Визуально сконструированную программу,напоминающую блоки Scratch, легко конвертировать в код Arduino IDE. Да и писать можно, не отрываясь от Arduino IDE – эта программа встраивается в среду программирования в виде плагина. В этой статьей мы рассмотрим такие вопросы как установка Ardublock, настройка и примеры программирования
Установка Ardublock
Для начала работы с программой необходимо ее установить. Для этого выполним несколько простых действий, алгоритм таков:
- Скачать архив с сайта ArduBlock
- Открыть Arduino IDE/Menu /Arduino/ Preferences, там вы найдете строку Sketchbook location
- Создайте папку “tools/ArduBlockTool/tool” внутри папки “Arduino” в строке “Sketch location” и скопируйте архив “ardublock-all.jar” в папку “tool”. Например, если имя пользователя “user”, то путь в среде Windows будет таким: “C:\Users\user\Documents\Arduino”
- Перезапустите Arduino IDE и у Вас должен появиться пункт “ArduBlock” в меню “Tool”
При установки на Mac для пользователя user путь будет следующим: “/Users/user/Documents/Arduino/tools/ArduBlockTool/tool/ardublock-all.jar”
При установке на Linux: “/home/user/sketchbook/tools/ArduBlockTool/tool/ardublock-all.jar”
Как запустить ArduBlock
Для начала запускаем сам Arduino, заходим в меню Инструменты и там находим ArduBlock, его и выбираем.
Для начала запускаем сам Arduino, заходим в меню Инструменты и там находим ArduBlock, его и выбираем.Открывается окно ArduBlock дополнительно к окну Arduino.
Открывается окно ArduBlock дополнительно к окну Arduino.Можем начинать программировать.
Интерфейс программы
Настроек в ArduBlock нет, а вот значков для программирования предостаточно и каждый из них несет за собой команду в текстовом формате Arduino IDE. В новых версиях значков еще больше, поэтому разобраться с ArduBlok последней версии сложно и некоторые из значков не переведены на русский.
Блоки ArduBlock разделены на 6 категорий.
Control
ControlВ разделе «Управление» мы найдем разнообразные циклы.
Порты (Pin)
PinВ разделе «Порты» мы можем с вами управлять значениями портов, а также подключенными к ним звукоизлучателя, сервомашинки или ультразвукового датчика приближения.
Цифры, константы и Переменные
Цифры, константы и ПеременныеБлоки категорий “Numbers/Constants” это переменные
Operators
OperatorsЭта категория включает в себя логические и математические операторы.
Utilities
UtilitiesЭти блоки являются функциями, которые обычно используются в скетчах для управления режимом работы с программой.
Модули
BricksКаждый блок данной категории изображает тип реального устройства, который вы можете напрямую подключить к вашему скетчу.
Программирование
Программировать в Ardublock очень просто: нужно только соединять блоки в отдельно выделенном для этого черного поля.
Как посмотреть код и загрузить его на платформу
Все очень просто. Для начала сохраним наше решение (кнопка Сохранить) в формате ArduBlock (это позволит потом запускать ее в модульном виде и продолжать работу с блоками).
Далее жмем кнопку Загрузить, система спрашивает, куда сохранить программу в виде скетча Arduino и далее показывает нам код программы уже в окне Arduino, проходит компиляция, после чего скетч грузится на платформу.
библиотек – Arduino Ссылка
Среда Arduino может быть расширена за счет использования библиотек, как и большинство платформ программирования.
Библиотеки предоставляют дополнительную функциональность для использования в эскизах, например, работа с оборудованием или манипулирование данными. к
используйте библиотеку в эскизе, выберите ее из Эскиз> Импортировать библиотеку .
Ряд
библиотеки
поставляются с IDE, но вы также можете скачать или создать свой собственный.Посмотрите эти инструкции для деталей об установке библиотек.
Там в
также учебник по написанию собственного
библиотеки. Посмотреть стиль API
Руководство для получения информации о создании хорошего API в стиле Arduino для вашей библиотеки.
Стандартные библиотеки
- EEPROM – чтение и запись в «постоянное» хранение
- Ethernet – для подключения к Интернет с использованием Arduino Ethernet Shield, Arduino Ethernet Shield 2 и Arduino Leonardo ETH
- Firmata – для общения с приложения на компьютере с использованием стандартного последовательного протокола.
- GSM – для подключения к GSM / GRPS сеть со щитом GSM.
- LiquidCrystal – для контроля жидкокристаллические дисплеи (ЖК-дисплеи)
- SD – для чтения и записи SD-карт
- Servo – для управления серводвигателями
- SPI – для связи с устройствами с помощью шине последовательного периферийного интерфейса (SPI)
- SoftwareSerial – для серийных общение на любых цифровых пинах.Версия 1.0 и позже Arduino включают библиотеку NewSoftSerial Микала Харта как SoftwareSerial.
- Stepper – для управления степпером моторы
- TFT – для рисования текста, изображений, и фигуры на экране Arduino TFT
- WiFi – для подключения к интернету используя Arduino WiFi Shield
- Wire – двухпроводной интерфейс (TWI / I2C) для отправки и получения данных через сеть устройств или датчиков.
Библиотеки Matrix и Sprite больше не являются частью основного дистрибутива.
101 только библиотеки
- CurieBLE – Взаимодействие со смартфонами и планшеты с Bluetooth Low Energy (BLE).
- CurieIMU – Управление на борту акселерометр и гироскоп.
- CurieTimerOne – позволяет использовать Функции таймера.
- CurieTime – Позволяет контролировать и использование внутренний RTC (часы реального времени)
Должны только библиотеки
- Audio – Воспроизведение аудио файлов с SD открытка.
библиотеки Due, Zero и MKR1000
- USBHost – общение через USB периферийные устройства, такие как мыши и клавиатуры. Планировщик
- – Управление несколькими неблокирующие задачи.
Ноль и все платы на базе SAMD21 MKR библиотеки
- AudioFrequencyMeter – Сэмплируйте аудиосигнал и верните его частоту
- AudioZero – воспроизведение аудиофайлов с SD Card
- RTC – часы реального времени для планирования событий
- ArduinoSound – простой способ воспроизводить и анализировать аудиоданные
- I2S – Для использования протокола I2S на SAMD21
WiFi 101 и библиотека MKR1000
- WiFi101 – библиотека для использования только с участием Wi-Fi щит 101
- WiFi101OTA – беспроводные обновления на MKR1000
MKR WiFi 1010, MKR VIDOR 4000, Arduino NANO 33 IoT и Arduino UNO WiFi Rev.2
- WiFi NINA – библиотека для использования модуля WiFi Nina вышеперечисленных плат.
Arduino Nano 33 BLE, Nano 33 BLE Sense, NANO 33 IoT, Uno WiFi Rev 2, MKR WiFi 1010.
- ArduinoBLE – библиотека для использования BLE Особенности вышеперечисленных плат.
Arduino Nano 33 IoT и UNO WiFi Rev. 2
- ArduinoLSM6DS3 – библиотека для использование LSM6DS3 6-осевой IMU, доступный на Arduino Nano 33 IoT и Arduino UNO WiFi Rev.2.
Arduino Nano 33 BLE и BLE Sense
- ArduinoLSM9DS1 – библиотека для использование 9-осевой IMU LSM9DS1, доступный на Arduino Nano 33 BLE и Arduino Nano 33 BLE Sense.
Arduino Nano 33 BLE Sense
- PDM – библиотека для использования цифрового микрофон MP34DT05, наша библиотека PDM может использоваться также с нашей библиотекой ArduinoSound.
- ArduinoAPDS9960 – библиотека для использовать датчик жеста APDS9960; это чувствует жест, цвет, окружение освещение и близость.
- ArduinoLPS22HB – библиотека для использование барометр и датчик температуры LPS22; это ультракомпактный датчик который функционирует как цифровой выходной барометр.
- ArduinoHTS221 – библиотека для использования датчик относительной влажности HTS221; это ультракомпактный датчик, который использует Плоская полимерная диэлектрическая конденсаторная структура, способная обнаруживать изменения относительной влажности, возвращенная как цифровой выход по последовательному интерфейсу.
MKR Только для автоперевозчиков. Библиотека
MKR FOX 1200 только библиотека
- SigFox – библиотека для использования только с MKRFOX1200
MKR WAN 1300 только библиотека
- MKRWAN – библиотека для использования только с MKR WAN 1300
MKR только GSM 1400 Библиотека
- MKRGSM – библиотека для использования только с МКР GSM 1400
MKR NB 1500 только Библиотека
- MKRNB – библиотека для использования только с МКР NB 1500
MKR 1000, MKR WiFi 1010, MKR GSM 1400, MKR NB 1500, MKR RS485 Shield, UNO WiFI Rev.2, только Ethernet Shield Библиотека
- Arduino Modbus – библиотека для связываться с протоколом Modbus через RS485 и TCP с клиентами Modbus и сервера.
MKR GPS Shield Library
- ArduinoMKRGPS – библиотека будет используется с Arduino MKR GPS Shield
MKR RGB Shield Библиотеки
- ArduinoMKRRGB – библиотека будет используется с Arduino MKR RGB Shield
- ArduinoGraphics – библиотека с участием графические примитивы, работает также с MKR RGB Shield
MKR 485 Щит библиотеки
- ArduinoRS485 – библиотека, которая реализует RS485 на щите Arduino MKR RS485
MKR ENV Shield Library
- ArduinoMKRENV – библиотека для чтения все значения, измеренные датчиками Arduino MKR ENV Shield
MKR THERM Щитовая библиотека
- ArduinoMKRTHERM – библиотека для прочитать датчики, подключенные к Arduino MKR THERM Shield
Esplora Only Library
- Esplora – эта библиотека включена Вы можете легко получить доступ к различным датчикам и исполнительным механизмам, установленным на плате Esplora.
Arduino Robot Library
- Робот
- – эта библиотека позволяет легко доступ к функциям робота Arduino.
Yún устройства Библиотека
- Библиотека мостов
- – Включает связь между процессором Linux и микроконтроллером на Yún.
- Ciao Library – Цели для упрощения взаимодействие между микроконтроллером и ОС Linino, позволяющее устанавливать различные соединения с наиболее распространенными протоколы
USB-библиотеки (Леонардо, Микро, Дуэ, Ноль и Эсплора)
- Клавиатура
- – отправлять нажатия клавиш подключенный компьютер.
- Mouse – управление движением курсора на подключенном компьютере.
Serial – Arduino Ссылка
Описание
Используется для связи между платой Arduino и компьютером или другими устройствами. Все платы Arduino имеют по крайней мере один последовательный порт (также известный как UART или USART), а некоторые имеют несколько.
Борт | USB CDC имя | Серийные контакты | Serial1 pins | Serial2 pins | Serial3 pins |
---|---|---|---|---|---|
Uno, Nano, Mini | 0 (RX), 1 (TX) | ||||
Мега | 0 (RX), 1 (TX) | 19 (RX), 18 (TX) | 17 (RX), 16 (TX) | 15 (RX), 14 (TX) | |
Леонардо, Микро, Юн | Серийный | 0 (RX), 1 (TX) | |||
Uno WiFi Rev.2 | подключен к USB | 0 (RX), 1 (TX) | подключен к NINA | ||
MKR доски | Серийный | 13 (RX), 14 (TX) | |||
Ноль | SerialUSB (только собственный порт USB) | подключен к порту программирования | 0 (RX), 1 (TX) | ||
Должно | SerialUSB (только собственный порт USB) | 0 (RX), 1 (TX) | 19 (RX), 18 (TX) | 17 (RX), 16 (TX) | 15 (RX), 14 (TX) |
101 | Серийный | 0 (RX), 1 (TX) |
В Uno, Nano, Mini и Mega контакты 0 и 1 используются для связи с компьютером.Подключение чего-либо к этим контактам может помешать этому общению, в том числе вызвать неудачные загрузки на доску.
Вы можете использовать встроенный последовательный монитор среды Arduino для связи с платой Arduino. Нажмите кнопку последовательного монитора на панели инструментов и выберите ту же скорость передачи, которая использовалась при вызове begin ()
.
Последовательная связь на контактах TX / RX использует логические уровни TTL (5 В или 3,3 В в зависимости от платы). Не подключайте эти контакты напрямую к последовательному порту RS232; они работают при +/- 12 В и могут повредить вашу плату Arduino.
Чтобы использовать эти дополнительные последовательные порты для связи с вашим персональным компьютером, вам потребуется дополнительный адаптер USB-последовательный порт, так как они не подключены к адаптеру Mega USB-последовательный порт. Чтобы использовать их для связи с внешним последовательным устройством TTL, подключите контакт TX к контакту RX вашего устройства, RX к контакту TX вашего устройства, а заземление вашего Mega – к заземлению вашего устройства.
,analogRead () – Arduino Reference
Описание
Считывает значение с указанного аналогового контакта. Платы Arduino содержат многоканальный 10-битный аналого-цифровой преобразователь. Это означает, что он отобразит входные напряжения между 0 и рабочим напряжением (5 В или 3,3 В) в целочисленные значения от 0 до 1023. Например, на Arduino UNO это дает разрешение между показаниями: 5 вольт / 1024 единиц или 0,0049 вольт (4,9 мВ) на единицу. В таблице ниже приведены используемые контакты, рабочее напряжение и максимальное разрешение для некоторых плат Arduino.
На платах на базе ATmega (UNO, Nano, Mini, Mega) считывание аналогового входа занимает около 100 микросекунд (0,0001 с), поэтому максимальная скорость считывания составляет около 10000 раз в секунду.
Борт | Рабочее напряжение | Используемые булавки | Макс. Разрешение |
---|---|---|---|
Uno | 5 Вольт | от A0 до A5 | 10 бит |
Mini, Nano | 5 Вольт | от A0 до A7 | 10 бит |
Mega, Mega2560, MegaADK | 5 Вольт | от A0 до A14 | 10 бит |
Micro | 5 Вольт | от A0 до A11 * | 10 бит |
Леонардо | 5 Вольт | от A0 до A11 * | 10 бит |
Ноль | 3.3 Вольт | от A0 до A5 | 12 бит ** |
Должно | 3,3 Вольт | от A0 до A11 | 12 бит ** |
MKR Семейные доски | 3,3 Вольт | от A0 до A6 | 12 бит ** |
* от A0 до A5 помечены на плате, A6 – A11 соответственно доступны на выводах 4, 6, 8, 9, 10 и 12
** Стандартное разрешение analogRead ()
для этих плат составляет 10 бит, для совместимость.Вам нужно использовать analogReadResolution (), чтобы изменить его на 12 бит.
Синтаксис
Параметры
вывод
: имя вывода аналогового входа для чтения (от A0 до A5 на большинстве плат, от A0 до A6 на платах MKR, от A0 до A7 на Mini и Nano, от A0 до A15 на Mega).
Возвращает
Аналоговое показание на булавке. Хотя оно ограничено разрешением аналого-цифрового преобразователя (0-1023 для 10 бит или 0-4095 для 12 бит). Тип данных: и
.
analogWrite () – Arduino Reference
Описание
Записывает аналоговое значение (волна ШИМ) на вывод. Может использоваться для освещения светодиодов с различной яркостью или для управления двигателем с различной скоростью. После вызова analogWrite ()
вывод будет генерировать устойчивую прямоугольную волну указанного рабочего цикла до следующего вызова analogWrite ()
(или вызова digitalRead ()
или digitalWrite ()
) на той же булавке.
Доска | PWM Pins | ШИМ Частота |
---|---|---|
Uno, Nano, Mini | 3, 5, 6, 9, 10, 11 | 490 Гц (контакты 5 и 6: 980 Гц) |
Мега | 2 – 13, 44 – 46 | 490 Гц (контакты 4 и 13: 980 Гц) |
Леонардо, Микро, Юн | 3, 5, 6, 9, 10, 11, 13 | 490 Гц (контакты 3 и 11: 980 Гц) |
Uno WiFi Rev.2 | 3, 5, 6, 9, 10 | 976 Гц |
доски MKR * | 0 – 8, 10, A3 (18), A4 (19) | 732 Гц |
MKR1000 WiFi * | 0 – 8, 10, 11, A3 (18), A4 (19) | 732 Гц |
ноль * | 3 – 13, A0 (14), A1 (15) | 732 Гц |
Срок ** | 2-13 | 1000 Гц |
101 | 3, 5, 6, 9 | контакты 3 и 9: 490 Гц, контакты 5 и 6: 980 Гц |
* В дополнение к возможностям ШИМ на контактах, отмеченных выше, платы MKR и Zero имеют настоящий аналоговый выход при использовании analogWrite ()
на выводе DAC0
( A0
).
** В дополнение к возможностям ШИМ на контактах, отмеченных выше, у Due есть истинный аналоговый выход при использовании analogWrite ()
на контактах DAC0
и DAC1
.
Вам не нужно вызывать pinMode ()
, чтобы установить вывод в качестве выхода, прежде чем вызывать analogWrite ()
.
Функция analogWrite
не имеет ничего общего с аналоговыми выводами или функцией analogRead
.
Синтаксис
Параметры
контакт
: Arduino контакт для записи.Разрешенные типы данных: и
.
значение
: рабочий цикл: между 0 (всегда выключен) и 255 (всегда включен). Разрешенные типы данных: и
.