Опубликовано

Создание собственных библиотек

По материалам книги “Arduino. Большая книга рецептов“, 3-е изд. (авторы Джепсон Брайан, Марголис Майкл, Уэлдин Николас Роберт) (глава 16. Использование, модифицирование и создание библиотек)

Arduino. Большая книга рецептов, 3-издание

ЗАДАЧА

Требуется создать свою библиотеку. Библиотеки предоставляют удобный способ использования одного и того же кода во многих скетчах, а также дают другим разработчикам возможность использовать ваш код.

РЕШЕНИЕ

Библиотека представляет собой набор методов и переменных, объединенных в формате, предоставляющем пользователю стандартный способ доступа к этим функциям и переменным.

Большинство библиотек Arduino создаются в виде класса. Те из вас, кто знаком с языком С++ или Java, должны знать, что такое класс. Однако библиотеки можно также создавать и без использования классов, и здесь мы увидим, как это сделать.

Итак, давайте модифицируем скетч решения из разд. 7.1, чтобы включить функцию BlinkLED() в библиотеку.

Схема подключения светодиодов приводится на рис. 7.2, а описание ее работы — в разд. 7.1. Создаваемая нами библиотека будет содержать функцию blinkLED() из этого решения. В листинге 16.5 приводится код скетча blinkLibTest, с помощью которого будет выполняться тестирование созданной библиотеки.

Листинг 16.5. Скетч для тестирования созданной библиотеки

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
* Скетч 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* 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 и скопируйте в него следующий код:

1
2
3
4
5
6
/*
* 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, за исключением следующих двух строк в начале кода:

1
2
#include "Arduino.h" // Подключение заголовочного файла Arduino.h
#include "blinkLED.h"

Оператор #include “Arduino.h” требуется для библиотек, использующих любые функции или константы языка Arduino. При отсутствии этого оператора компилятор будет выдавать сообщения об ошибке для всех функций, используемых в скетче.

 

Заголовочный файл Arduino.h был добавлен в версии 1.0 среды Arduino IDE, заменив заголовочный файл WProgram.h, используемый в более ранних версиях среды. При работе с такими более ранними версиями среды Arduino IDE можно использовать следующую конструкцию, чтобы подключать правильный заголовочный файл:

1
2
3
4
5
#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.

Содержимое заголовочного файла для нашей библиотеки очень простое — объявление одной функции:

1
void blinkLED(int pin, int duration); // Прототип функции

Это объявление почти такое же, как и объявление этой функции в файле blinkLED.cpp:

1
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.

Добавить новую функциональность в существующую библиотеку не составляет никаких проблем. Предположим, например, что вы хотите добавить в нее несколько постоянных, наиболее часто используемых значений задержки, чтобы пользователи библиотеки могли применять описательные названия констант вместо значений в миллисекундах.

Эта задача решается добавлением в заголовочный файл библиотеки трех строк кода со значениями констант, которые обычно размещаются непосредственно перед кодом объявления прототипа функции:

1
2
3
4
5
// Константы для периода мигания светодиодов
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() для мигания светодиодами с разной частотой

1
2
3
4
5
void loop(){
blinkLED(firstLedPin, <strong>BLINK_SHORT</strong>);
blinkLED(secondLedPin, <strong>BLINK_MEDIUM</strong>);
blinkLED(thirdLedPin, <strong>BLINK_LONG</strong>);
}

Также легко добавляются в библиотеку и новые функции. В листинге 16.8 приводится код главного цикла loop(), который мигает каждым светодиодом заданное для него количество раз.

Листинг 16.8. Код цикла loop() для мигания каждым светодиодом в течение заданного для него периода

1
2
3
4
5
void loop(){
blinkLED(firstLedPin, BLINK_SHORT, 5); // <strong>Мигает 5 раз</strong>
blinkLED(secondLedPin, BLINK_MEDIUM, 3); // <strong>Мигает 3 раза</strong>
blinkLED(thirdLedPin, BLINK_LONG); // <strong>Мигает один раз</strong>
}

Чтобы добавить эту функцию в библиотеку, в файл blinkLED.h нужно добавить ее прототип, как показано в листинге 16.9.

Листинг 16.9. Добавление прототипа новой функции в заголовочный файл

1
2
3
4
5
6
7
8
9
10
11
12
/*
* 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);
<strong>// Определение новой функции для мигания заданного количества раз</strong>
<strong>void blinkLED(int pin, int duration, int repeats);</strong>

А в файл blinkLED.cpp добавляем исходный код функции, как показано в листинге 16.10.

Листинг 16.10. Исходный код функции мигания светодиодами заданное количество раз

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
* 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

1
2
3
4
5
6
7
8
9
10
11
#######################################
# 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.
Добавить комментарий