Arduino Sketches: как устроена программа для Arduino
Разбираем структуру скетча Arduino: комментарии, переменные, функции setup() и loop(), а также команды pinMode(), digitalWrite() и delay().
В руководстве по началу работы (Windows, MacOS, Linux) вы уже загрузили скетч, который мигает светодиодом. В этом уроке разберём, как устроена каждая часть этой программы и почему она написана именно так.
Скетч — это то, как Arduino называет программу. Именно скетч загружается на плату и выполняется на ней.
Комментарии
Первые несколько строк скетча Blink — это комментарий:
/*
* Blink
*
* Базовый пример для Arduino. Включает светодиод на одну секунду,
* затем выключает на одну секунду, и так далее... Используется pin 13, потому что,
* в зависимости от платы Arduino, на нём есть либо встроенный светодиод,
* либо встроенный резистор, так что достаточно подключить только светодиод.
*
* http://www.arduino.cc/en/Tutorial/Blink
*/
Всё, что находится между /* и */, Arduino полностью игнорирует при выполнении программы. Символ * в начале каждой строки — просто украшение, он не обязателен. Комментарии существуют для людей: они объясняют, что делает программа, как она работает и почему написана именно так.
Хорошая привычка — комментировать свои скетчи и обновлять комментарии при изменении кода. Это помогает другим людям разобраться в вашей работе или доработать её.
Есть и второй стиль — короткий однострочный комментарий. Он начинается с // и продолжается до конца строки. Например, в строке:
int ledPin = 13; // светодиод подключён к цифровому pin 13
фраза «LED connected to digital pin 13» — это однострочный комментарий.
Практическое замечание: если вы работаете в команде или возвращаетесь к своему коду спустя несколько недель, хорошие комментарии сэкономят вам много времени. Не пренебрегайте ими даже в простых проектах.
Переменные
Переменная — это именованное место для хранения данных. У неё есть имя, тип и значение. Например, строка из скетча Blink выше объявляет переменную с именем ledPin, типом int и начальным значением 13. Она указывает, к какому пину Arduino подключён светодиод. Каждый раз, когда в коде встречается имя ledPin, программа берёт его значение.
Автор скетча мог бы не создавать переменную ledPin и просто писать число 13 везде, где нужен номер пина. Но использование переменной удобнее: если нужно перенести светодиод на другой пин, достаточно изменить одну строку — там, где переменной присваивается начальное значение.
Значение переменной нередко меняется в процессе работы скетча. Например, можно сохранить в переменную значение, считанное с датчика. Подробнее об этом — в разделе Variables tutorial.
Типичная ошибка: объявить переменную внутри одной функции и попытаться использовать её в другой. Переменные, объявленные внутри функции, видны только в ней. Если переменная нужна в нескольких функциях — объявляйте её в начале скетча, до setup().
Функции
Функция (её также называют процедурой или подпрограммой) — это именованный блок кода, который можно вызывать из других мест скетча. Например, вот определение функции setup() из примера Blink:
void setup()
{
pinMode(ledPin, OUTPUT); // настраивает цифровой pin как выход
}
Первая строка описывает функцию: её имя — «setup». Текст до и после имени указывает тип возвращаемого значения и параметры — об этом подробнее позже. Код между { и } называется телом функции: именно здесь описывается, что функция делает.
Функцию можно вызвать, если она уже определена — либо в вашем скетче, либо как часть Arduino language. Например, строка pinMode(ledPin, OUTPUT); вызывает функцию pinMode() и передаёт ей два параметра: ledPin и OUTPUT. Эти параметры говорят функции pinMode(), какой пин настраивать и в каком режиме.
pinMode(), digitalWrite() и delay()
Функция pinMode() настраивает пин как вход или выход. Ей нужно передать номер пина и константу INPUT или OUTPUT. Пин, настроенный как вход, позволяет считывать состояние датчика — например, кнопки. Об этом рассказывается в разделе Digital Read Serial tutorial. Пин, настроенный как выход, может управлять исполнительным устройством — например, светодиодом.
Функция digitalWrite() выводит значение на пин. Например, строка:
digitalWrite(ledPin, HIGH);
устанавливает на пине ledPin (пин 13) уровень HIGH, то есть 5 вольт. Если записать LOW, пин подключится к земле — 0 вольт.
Функция delay() заставляет Arduino ждать указанное количество миллисекунд перед переходом к следующей строке. В одной секунде 1000 миллисекунд, поэтому строка:
delay(1000);
создаёт паузу в одну секунду.
Как это работает: во время выполнения delay() Arduino не делает ничего другого — она просто ждёт. Для простых проектов это удобно, но в более сложных программах долгие задержки могут мешать обрабатывать другие события. Тогда используют другие подходы, например функцию millis().
setup() и loop()
В каждом скетче Arduino есть две особые функции: setup() и loop(). Функция setup() вызывается один раз при запуске скетча. Это подходящее место для начальной настройки: задать режимы пинов, инициализировать библиотеки и так далее. Функция loop() вызывается снова и снова — она является сердцем большинства скетчей.
Обе функции обязательно должны присутствовать в скетче, даже если вам нечего в них писать. Если убрать одну из них, компилятор выдаст ошибку.
Практическое замечание: начинающие иногда путаются, почему код в setup() выполняется только раз, а в loop() — постоянно. Представьте setup() как утреннюю подготовку перед работой, а loop() — как саму работу, которую вы повторяете снова и снова в течение дня.
Как проверить результат
После загрузки скетча Blink на плату светодиод (обычно встроенный, на пине 13) должен мигать с интервалом одна секунда: секунду горит, секунду не горит. Если этого не происходит — проверьте, правильно ли выбраны плата и порт в меню Arduino IDE, и нет ли ошибок при компиляции.
Упражнения
1. Измените код так, чтобы светодиод горел 100 миллисекунд, а не горел — 1000.
2. Измените код так, чтобы светодиод включился при старте скетча и больше не выключался.