Во всех последних версиях Windows подобные среды программирования предлагают разместить папку с проектами где-нибудь в недрах папки Users (Пользователи). Способ неудобный (проще хранить среду и привязанные к ней документы в одном каталоге) и опасный (потому что потерять пользовательские папки при переустановке системы — как два байта переслать), но вынужденный — по умолчанию писать в системный каталог Program Files пользовательским программам во всех версиях Windows после ХР запрещено. Поэтому я и рекомендовал не распаковывать среду в системный каталог — если вы захотите создать в нем пользовательскую папку с проектами, то для нее придется долго и мучительно возиться с правами доступа. А если он размещен отдельно, то просто создайте внутри папки, содержащей arduino.exe, каталог, с названием, например, Projects, и укажите его в самом первом пункте настроек через кнопку Выбрать.
Много разнообразных настроек доступны через файл preferences.txt (его размещение указано внизу окна настроек). Так, обладателям большого монитора размер окна Arduino IDE по умолчанию покажется мелковатым, а запоминать размер среда почему-то не умеет (ах, если бы это было самым крупным ее недостатком!). Для изменения этого параметра следует отредактировать в файле preferences.txt строки editor.window.height.default И editor.window.width.default (установив, например, 1000 и 800, соответственно). Только не забудьте, что перед внесением изменений в preferences.txt следует создать его резервную копию.
Программы для Arduino (скетчи) пишутся на варианте языка Processing/Wiring, специально разработанном для этой среды. Как и многие другие языки, он основан на языке C/C++, потому в случае затруднений в правилах синтаксиса можете смело обращаться к любому сетевому справочнику по функциям этих популярных языков. В среде Arduino работает большинство стандартных функций языка С, так что проблема будет не в том, чтобы найти способ осуществления какого-либо действия (такого, как извлечение корня или преобразование числа в строку и наоборот), а в том, чтобы выбрать подходящий способ из всего многообразия, которым почему-то так гордятся приверженцы этого языка.
Справку по большинству функций языка С можно найти в соответствующем разделе классического учебника Герберта Шилдта [25]. Основные приемы выполнения арифметических и логических операций на языке С неплохо изложены в книге [26]. Что же касается функций, специфических для Arduino, то они изложены в разделе Программирование официального сайта Arduino, в том числе на русском языке [23].
Если вы с языком С до сих пор не знакомы, то учтите, что логики и стройности в нем немного, зато очень много лишнего и непонятного. Не унывайте — чтобы овладеть Arduino, изучать язык досконально не требуется, Processing и был придуман для тех, кто не хочет углубляться в программирование. Нам сейчас будет достаточно следующих элементарных сведений.
Любая программа в среде Arduino состоит из трех основных блоков: блока определений, функции установок и бесконечного цикла, который и составляет собственно программу. Эти блоки полностью аналогичны структуре нашей ассемблерной программы (см. главу 19, где с блока определений начиналась программа, функция установок у нас следовала за меткой Reset, а бесконечный цикл заключал текст, который выполняется вне прерываний (у нас — то, что между меткой Cykle: и оператором rjmp Cykle). Явное использование прерываний в программах Arduino — скорее исключение, что относится к числу недостатков этой платформы (и мы еще будем об этом говорить).
* * *
Подробности
Но было бы ошибкой считать, что прерывания в Arduino не используются вовсе. Например, в Arduino отсчет времени реализован совершенно так же, как мы делали в главе 19, только не с помощью Time1, как у нас, а через восьмиразрядный Timer0. Здесь тоже устанавливается прерывание таймера по переполнению и тоже с коэффициентом предделителя 64. При обычной тактовой частоте Arduino, равной 16 МГц, прерывания переполнения восьмиразрядного таймера происходят каждые (64/16)·256 = 1024 микросекунды, что позволяет реализовать такие функции, как millis () или delay (). Самый частый отсчет возможен при таком коэффициенте каждые 4 микросекунды, что обуславливает приведенное в справочнике по функциям Arduino максимальное разрешение функции отсчета микросекунд micros (). Любопытно, что задержка в микросекундах (т. е. функция delayMicroseconds ()) при этом реализована в виде простой программной задержки, как мы делали в первом примере главы 19. Функции коммуникационного порта, кстати, также основаны на прерываниях (см. далее).
* * *
Блок определений содержит обычные для почти любого языка программирования ссылки на включаемые библиотеки и определения переменных, например:
#include
int i; //переменная i — 16-разрядный счетчик
byte temp = 0; //рабочая переменная типа byte
float temperature; //переменная — действительное число для значения температуры
Определение наименований выводов, как констант:
#define dataPin 16 //dataPin — цифровой вывод 16[40] (т. е. вывод А2 платы, см. далее)
Выводы можно определять и как переменные целого типа:
int ledPin =3; // цифровой выход управления светодиодом
Строчные и заглавные буквы здесь различаются, например, string () и String () — это разные функции (см. справочник по языку на сайте [23]). В языке С любые определения можно делать в любом месте программы, выносить их в начало необязательно. Только стоит учесть, что, например, вызов переменной, определенной внутри некоей функции (локальная переменная), в другой функции вызовет сообщение об ошибке. Для того чтобы переменная действовала для всей программы, она должна быть определена именно в начале, до всех функций (глобальная переменная). Нюанс заключается в том, что глобальная переменная займет ресурсы контроллера на все время работы программы, тогда как локальная освободит их по окончании действия функции. В условиях ограниченных ресурсов МК это может оказаться существенным фактором, влияющим на скорость выполнения программы.
Наша процедура Reset (блок установок) здесь выглядит, как функция setup:
void setup()
{
< операторы >
}
Следует заметить, что в языке С служебное слово void («пустота») обозначает, что за ним последует то, что в человеческом языке носит название «процедура» — т. е. функция, не возвращающая никакого значения. Между фигурными скобками здесь размещаются те операторы, которые должны выполняться при запуске программы один раз. После setup обычно идет функция (на самом деле тоже процедура) бесконечного цикла, которая обозначается словом loop («петля»):
void loop()
{
< операторы >
}
Кроме этих двух обязательных функций, программа для Arduino может включать в себя любое количество других функций (или процедур), определяемых пользователем, и примеры этого мы увидим далее.
В заключение нашего суперкраткого обзора программирования для Arduino стоит напомнить про некоторые особенности логических операций в языке С, которые почти не играют роли в обычном программировании, но в приложении к микроконтроллерам имеют важное значение. Это касается выполнения базовых логических функций «И», «ИЛИ» и «НЕ» о которых мы упоминали в главе 14 (см. также [25]).
В языке С имеются две разновидности логических операций: обычные («логическое И» &&, «логическое ИЛИ» ||, «логическое НЕ»!) и поразрядные битовые («поразрядное И» &, «поразрядное ИЛИ» |, «поразрядное НЕ» ~). Теперь вы можете с полным пониманием отнестись к этому разделению: обычные логические операции относятся к булевым переменным (т. е. таким, которые принимают только два значения: «ноль»/«не ноль», «ложь»/«правда»), а поразрядные — к числовым переменным, т. е. попросту к нашим родным регистрам контроллера.
В условных операторах (if) должна присутствовать чисто логическая операция с бинарным исходом («правда» — «ложь»), потому там надо ставить символы логических операций, а вот в операциях с числами и регистрами — поразрядных. Например, значок неравенства в языке С запишется, как «!=» (буквально и значит «не равно»), а запись «~=» будет бессмысленной. Но одинарные символы (& вместо положенного && или | вместо положенного ||) все равно часто ставят в условном операторе if, потому что там обычно фигурируют бинарные операции, вроде операций сравнения («больше», «меньше», «равно», «не равно» и т. п.), которые сами по себе в результате дают логическое значение. То есть они фактически состоят из одного двоичного разряда, и применение к ним побитовой операции даст ровно тот же результат, что и обычной логической.
Давайте соорудим для начала на Arduino что-нибудь простенькое. В главе 12 мы уже изобретали термостаты на чисто аналоговых компонентах. Теперь посмотрим, как можно привлечь к этому полезному в хозяйстве делу цифровую технику.
Мы уже упоминали (см. главу 18), что в состав AVR-контроллеров входит 10-разрядный многоканальный АЦП. На платах Arduino его выводы специально помечены, как аналоговые входы (буквой А с цифрами от нуля до пяти). Заметьте, что они могут быть задействованы и как обычные цифровые с номерами от 14 до 18, и мы в таком качестве ими еще воспользуемся. Один из этих входов мы как раз и применим для измерения температуры, а управлять подключением нагрузки будем с одного из цифровых выходов.