ЗАДАЧА
Требуется создать свою библиотеку. Библиотеки предоставляют удобный способ использования одного и того же кода во многих скетчах, а также дают другим разработчикам возможность использовать ваш код.
РЕШЕНИЕ
Библиотека представляет собой набор методов и переменных, объединенных в формате, предоставляющем пользователю стандартный способ доступа к этим функциям и переменным.
Большинство библиотек Arduino создаются в виде класса. Те из вас, кто знаком с языком С++ или Java, должны знать, что такое класс. Однако библиотеки можно также создавать и без использования классов, и здесь мы увидим, как это сделать.
Итак, давайте модифицируем скетч решения из разд. 7.1, чтобы включить функцию BlinkLED() в библиотеку.
Схема подключения светодиодов приводится на рис. 7.2, а описание ее работы — в разд. 7.1. Создаваемая нами библиотека будет содержать функцию blinkLED() из этого решения. В листинге 16.5 приводится код скетча blinkLibTest, с помощью которого будет выполняться тестирование созданной библиотеки.
Листинг 16.5. Скетч для тестирования созданной библиотеки
/*
* Скетч blinkLibTest
*/
#include "blinkLED.h"
const int firstLedPin = 3; // Контакты для подключения светодиодов
const int secondLedPin = 5;
const int thirdLedPin = 6;
void setup(){
pinMode(firstLedPin, OUTPUT); // Задаем выходной режим работы для
// контактов светодиодов
pinMode(secondLedPin, OUTPUT);
pinMode(thirdLedPin, OUTPUT);
}
void loop(){
// Мигаем каждым светодиодом один раз в 1,000 мс (1 секунду)
blinkLED(firstLedPin, 1000);
blinkLED(secondLedPin, 1000);
blinkLED(thirdLedPin, 1000);
}
Функцию blinkLED() нужно удалить из скетча решения, приведенного в разд. 7.1, и поместить в отдельный файл с названием blinkLED.cpp, как показано в листинге 16.6 (файлы *.cpp рассматриваются более подробно далее — в разд. «Обсуждение работы решения и возможных проблем» этого раздела).
Листинг 16.6. Код библиотеки blinkLED
/* blinkLED.cpp
* Простая библиотека для мигания светодиодом с периодом в миллисекундах
*/
#include "Arduino.h" // Для версий среды Arduino IDE более ранних,
// чем версия 1.0, используйте файл Wprogram.h
#include "blinkLED.h"
// Мигаем светодиодом на этом контакте в течение duration миллисекунд
void blinkLED(int pin, int duration)
{
digitalWrite(pin, HIGH); // Включаем светодиод
delay(duration);
digitalWrite(pin, LOW); // Выключаем светодиод
delay(duration);
}
![]() |
Большинство библиотек разрабатывается программистами, которые используют для этого свою среду разработки, но их с таким же успехом можно создавать и в любом обычном текстовом редакторе типа Блокнот. |
А теперь создайте заголовочный файл blinkLED.h и скопируйте в него следующий код:
/*
* blinkLED.h
* Заголовочный файл для библиотеки BlinkLED
*/
#include "Arduino.h"
void blinkLED(int pin, int duration); // Прототип функции
Обсуждение работы решения и возможных проблем
Наша библиотека будет называться blinkLED и храниться в папке libraries (см. разд. 16.2). Создайте в этой папке вложенную папку blinkLED и переместите в нее файлы blinkLED.h и blinkLED.cpp. Затем создайте в папке blinkLED вложенную папку examples, а в ней — вложенную папку blinkLibTest. Создайте из скетча для тестирования библиотеки (см. листинг 16.5) файл с именем blinkLibTest.ino и поместите его в папку blinkLibTest. Путь к этому файлу должен выглядеть так: examples/blinkLibTest/ blinkLibTest.ino.
В результате мы переместили функцию blinkLED() скетча решения из разд. 7.1 в файл библиотеки blinkLED.cpp (расширением cpp обозначаются файлы с исходным кодом, созданным на языке С++, — С plus plus).
![]() |
Используемые в документации библиотек Arduino термины функция и метод обозначают блоки кода — такие как blinkLED(). Термин метод служит для обозначения функциональных блоков классов. Оба термина обозначают именованные функциональные блоки, доступ к которым предоставляется посредством библиотек. |
Файл blinkLED.cpp содержит исходный код функции blinkLED(), который идентичен коду этой функции в скетче из листинга 7.1, за исключением следующих двух строк в начале кода:
#include "Arduino.h" // Подключение заголовочного файла Arduino.h
#include "blinkLED.h"
Оператор #include “Arduino.h” требуется для библиотек, использующих любые функции или константы языка Arduino. При отсутствии этого оператора компилятор будет выдавать сообщения об ошибке для всех функций, используемых в скетче.
![]() |
Заголовочный файл Arduino.h был добавлен в версии 1.0 среды Arduino IDE, заменив заголовочный файл WProgram.h, используемый в более ранних версиях среды. При работе с такими более ранними версиями среды Arduino IDE можно использовать следующую конструкцию, чтобы подключать правильный заголовочный файл:
#if ARDUINO >= 100
#include "Arduino.h // для версий 1.0 и более поздних
#else
#include "WProgram.h" // для более ранних версий
#endif
|
Следующая строка кода: #include “blinkLED.h” — содержит определение функции (которое также называется прототипом функции) для нашей библиотеки. Компилятор Arduino автоматически создает прототипы для всех функций в скетче при его компилировании, но не создает прототипов для функций, содержащихся в библиотеках, поэтому при создании библиотеки необходимо самому создать заголовочный файл, содержащий эти прототипы. При подключении библиотеки к скетчу в него добавляется именно этот заголовочный файл (см. разд. 16.1).
![]() |
Каждая библиотека должна иметь файл, в котором объявляются названия предо- ставляемых функций. Такой файл называется заголовочным (header file) или включаемым (include file), а его название имеет формат НазваниеБиблиотеки.h. В рассматриваемом примере заголовочный файл называется blinkLED.h и размещается в той же папке, что и файл blinkLED.cpp. |
Содержимое заголовочного файла для нашей библиотеки очень простое — объявление одной функции:
void blinkLED(int pin, int duration); // Прототип функции
Это объявление почти такое же, как и объявление этой функции в файле blinkLED.cpp:
void blinkLED(int pin, int duration)
Однако разница между этими двумя объявлениями функции хотя и тонкая, но критическая. Объявление прототипа функции в заголовочном файле завершается точкой с запятой. Это сообщает компилятору, что это просто объявление формата для функции, но не ее кода. А отсутствие завершающей точки с запятой в объявлении функции в файле исходного кода blinkLED.cpp сообщает компилятору, что это собственно исходный код функции.
![]() |
Библиотеки могут содержать несколько заголовочных файлов и несколько файлов исходного кода. Но они должны иметь минимум один заголовочный файл, название которого должно быть идентичным названию библиотеки. Название именно этого файла вставляется вверху скетча при подключении библиотеки. |
Более подробную информацию по использованию заголовочных файлов и файлов *.cpp для создания модулей кода можно получить, прочитав какую-либо хорошую книгу по языку C++ (в разд. «Дополнительная информация» этого раздела рекомендуется несколько таких весьма популярных книг).
Разместив файлы blinkLED.cpp, blinkLED.h и blinkLibTest.ino в соответствующие вложенные папки в папке libraries, закройте среду разработки Arduino IDE, а затем снова запустите ее. Структура задействованных папок и файлов должна выглядеть следующим образом:
libraries/
└── blinkLED/
├── blinkLED.cpp
├── blinkLED.h
└── examples/
└── blinkLibTest/
└── blinkLibTest.ino
![]() |
Среда Arduino IDE обновляет список доступных библиотек только при ее запуске. Чтобы установленная вручную библиотека отобразилась в этом списке, необходимо закрыть, а затем снова запустить среду Arduino IDE. И хотя среду Arduino IDE нужно перезапустить при исходном добавлении библиотеки в папку libraries, впоследствии — после модифицирования библиотеки — перезапуск не требуется. |
Выполнив команду меню Файл | Примеры (Примеры из пользовательских библиотек) | blinkLED | blinkLibTest, откройте в окне Arduino IDE тестовый скетч blinkLibTest. Загрузите этот скетч в свою плату Arduino, и подключенные к ней светодиоды должны начать мигать так же, как и при исполнении скетча решения из разд. 7.1.
Добавить новую функциональность в существующую библиотеку не составляет никаких проблем. Предположим, например, что вы хотите добавить в нее несколько постоянных, наиболее часто используемых значений задержки, чтобы пользователи библиотеки могли применять описательные названия констант вместо значений в миллисекундах.
Эта задача решается добавлением в заголовочный файл библиотеки трех строк кода со значениями констант, которые обычно размещаются непосредственно перед кодом объявления прототипа функции:
// Константы для периода мигания светодиодов
const int BLINK_SHORT = 250;
const int BLINK_MEDIUM = 500;
const int BLINK_LONG = 1000;
void blinkLED(int pin, int duration); // Прототип функции
Затем надо модифицировать код в функции loop() скетча примера, как показано в листинге 16.7. Загрузив модифицированный скетч в плату, мы увидим, что каждый светодиод мигает с другой частотой.
Листинг 16.7. Модифицированный код функции loop() для мигания светодиодами с разной частотой
void loop(){
blinkLED(firstLedPin, BLINK_SHORT);
blinkLED(secondLedPin, BLINK_MEDIUM);
blinkLED(thirdLedPin, BLINK_LONG);
}
Также легко добавляются в библиотеку и новые функции. В листинге 16.8 приводится код главного цикла loop(), который мигает каждым светодиодом заданное для него количество раз.
Листинг 16.8. Код цикла loop() для мигания каждым светодиодом в течение заданного для него периода
void loop(){
blinkLED(firstLedPin, BLINK_SHORT, 5); // Мигает 5 раз
blinkLED(secondLedPin, BLINK_MEDIUM, 3); // Мигает 3 раза
blinkLED(thirdLedPin, BLINK_LONG); // Мигает один раз
}
Чтобы добавить эту функцию в библиотеку, в файл blinkLED.h нужно добавить ее прототип, как показано в листинге 16.9.
Листинг 16.9. Добавление прототипа новой функции в заголовочный файл
/*
* blinkLED.h
* Заголовочный файл для библиотеки blinkLED
*/
#include "Arduino.h"
// Константы для периода мигания светодиодов
const int BLINK_SHORT = 250;
const int BLINK_MEDIUM = 500;
const int BLINK_LONG = 1000;
void blinkLED(int pin, int duration);
// Определение новой функции для мигания заданного количества раз
void blinkLED(int pin, int duration, int repeats);
А в файл blinkLED.cpp добавляем исходный код функции, как показано в листинге 16.10.
Листинг 16.10. Исходный код функции мигания светодиодами заданное количество раз
* blinkLED.cpp
* Простая библиотека для мигания светодиодом с периодом в миллисекундах
*/
#include "Arduino.h"
#include "blinkLED.h"
// Мигаем светодиодом на этом контакте в течение duration миллисекунд
void blinkLED(int pin, int duration)
{
digitalWrite(pin, HIGH); // Включаем светодиод
delay(duration);
digitalWrite(pin, LOW); // Выключаем светодиод
delay(duration);
}
/* Функция для повторения мигания */
void blinkLED(int pin, int duration, int repeats)
{
while(repeats)
{
blinkLED(pin, duration);
repeats = repeats -1;
};
}
Для созданной библиотеки можно добавить возможность выделения цветом ключевых слов при просмотре исходного кода скетча в окне редактора скетчей среды IDE. Для этого нужно создать специальный файл keywords.txt. Это обычный текстовый файл, который содержит список ключевых слов и их типов: каждый тип ключевого слова выделяется другим цветом. Ключевые слова и типы разделяются табуляцией, а не просто пробелом. В листинге 16.11 приводится пример файла keywords.txt, в котором задается выделение цветом констант периода мигания светодиода.
Листинг 16.11. Файл keywords.txt для библиотеки blinkLED
#######################################
# Methods and Functions (KEYWORD2)
#######################################
blinkLED KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
BLINK_SHORT LITERAL1
BLINK_MEDIUM LITERAL1
BLINK_LONG LITERAL1
Сохраните его в папке blinkLED и перезапустите среду Arduino IDE. Если теперь открыть файл скетча blinkLibTest.ino в среде Arduino IDE, то константы BLINK_SHORT, BLINK_MEDIUM и BLINK_LONG будут выделяться цветом.
Дополнительная информация
Дополнительные примеры создания библиотек рассматриваются в разд. 16.5.
Дополнительная информация по созданию библиотек для Arduino приводится в справочном документе «Writing a Library for Arduino» (https://oreil.ly/vLNvx).
Рекомендуем также следующие книги по программированию на C++:
- «Practical C++ Programming» («Практическое программирование на языке C++»), автор Steve Oualline, издательство O’Reilly;
- «C++ Primer Plus» («Язык программирования С++»), автор Stephen Prata, издательство Sams;
- «C++ Primer» («Учебник C++ для начинающих»), авторы Stanley B. Lippman, Josee Lajoie и Barbara E. Moo, издательство Addison-Wesley Professional.










