Данную статью посвятим подробной инструкции по написанию собственной библиотеки для Arduino IDE и разберем то, как именно взаимодействует код между библиотекой и программой.
Разбираемся с основами
В кратце, библиотека-текстовый файл с программой, которую можно «подсоединить» к существующей программе и используется в первую очередь для упрощения программы. Библиотека может быть как одним файлом, так и совокупностью, однако подключается один единственный-с расширением .h, который в свою очередь соединяет все остальные.
SimpleLib — папка библиотеки
examples — папка с примерами
SimpleLib.h — главный файл
SimpleLib.cpp — файл реализации
keywords.txt — карта подсветки синтаксиса
Как правило, в «профессиональном» программировании файлы с расширениями .h и .cpp хранятся в папке src. Остальные, кроме главного с расширением .h являются необязательными и могут отсутствовать, т.е. библиотека может состоять только из главного файла. В таком виде библиотека лежит в главной папке программы и может быть подключена к программе при помощи команды #include. Конкретная программа ищет библиотеку среди папок с программой и папкой с библиотеками.
Поэтому команда #include имеет два варианта, или же режима написания(поиска файла):
#include <файл.h> — будет искать файл в папке с библиотеками;
#include файл.h — поиск в папке с программой, в случае отсутствия-поиск расширится на папку с библиотеками.
Основа библиотеки
Начнем создание библиотеки с основы, которая требуется для любой библиотеки:
#ifndef testLib_h
#define testLib_h
#include <Arduino.h>
// программа, осуществляющая работу библиотеки
#endif
В целом, следующая часть кода с директивами препроцессора является необязательной, однако, лучше удостовериться, что пользователь не будет дважды подключать библиотеку. Файл библиотеки SimpleLib.h находится в папке SimpleLib в папке со всеми остальными библиотеками. Строчка, подключающая Arduino.h-подключает основной файл Arduino библиотеки для использования стандартных функций Arduino в коде. Если в коде таковых нет-этого можно и не делать. Подключаем SimpleLib.h в тестовую программу. Строки #ifndef-define можно обнаружить почти в любой библиотеке. На текущих версия Arduino IDE можно упростить ее и написать так:
#pragma once // говорим компилятору о том, что запрещено подключать файл более одного раза.
Задача создаваемой библиотеки: избавиться от pinMode и digitalWrite и вызовом одной функции создать программу мигающего светодиода.
SimpleLib.h
#pragma once
#include “Arduino.h”
class SimpleLib {
public:
blk(int pin); // blk передает номер пина, где находится светодиод.
void blink();
private:
int _pin;
};
SimpleLib.cpp
#include “SimpleLib.h”
SimpleLib::blk(int pin){
pinMode(pin, OUTPUT); // переводим пин в режим выхода
_pin = pin; // это сделано для того, чтобы _pin не перепутать с обычным pin’ом и не создавать конфликтов с библиотекой arduino
}
void SimpleLib::blink() {
digitalWrite(_pin, HIGH); //
delay(2000);
digitalWrite(_pin, LOW);
delay(2000);
}
SimpleLib
#include “Arduino.h”
blk flick(13);
void setup() {
}
void loop() {
flick.blink();
}
Библиотека без использования классов
Файлы созданной библиотеки хранятся в общей папке всех библиотек. Для подключения библиотеки “запаковываем” все три файла в архив, заходим в верхнем меню в Скетч-Подключить библиотеку-Добавить ZIP-каталог и выбираем наш ZIP архив. Для проверки работоспособности создайте новый скетч и вызовите функцию.
Однако библиотека может и не иметь класса, а быть просто набором функций. Например, можно реализовать это следующим образом:
libhabib.h
#pragma once
#include <Arduino.h>
void printhasbullah() {
Serial.println(«hasbik»);
}
libhabib.ino
#include <libhabib.h>
void setup() {
Serial.begin(9600);
printhasbullah(); // выведет hasbik
}
void loop() {
}
или же “более правильная” реализация данного вида библиотек:
libhabib.h
#pragma once
#include <Arduino.h>
// объявление
void printhasbullah();
libhabib.cpp
#include <libhabib.h> // подключение заголовка
// реализация
void printhasbullah() {
Serial.println(«hasbik»);
}
libhabib.ino
#include <libhabib.h>
void setup() {
Serial.begin(9600);
printhasbullah(); // выведет hasbik
}
void loop() {
}
Использование namespace
Для того, чтобы избежать конфликтов с другими библиотеками(названия функций могут быть в других библиотеках), вместо написания класса, будем использовать namespace.
libhabib.h
#pragma once
#include <Arduino.h>
// пространство имён myFunc
namespace myFunc {
void printhasbullah();
};
// реализация
void myFunc::printhasbullah() {
Serial.println(«hasbik»);
}
libhabib.ino
#include <libhabib.h>
void setup() {
Serial.begin(9600);
// выведет hasbik из функции скетча
printhasbullah();
// выведет lol из функции библиотеки
myFunc::printhasbullah();
}
void printhasbullah() {
Serial.println(«hesbik»);
}
void loop() {
}
Создание и передача в класс массива
simplelib.h
#pragma once
#include <Arduino.h>
class testClass {
// Передача массива в класс
// Итог:сумма элементов массива
public:
long getSum(int *array, byte length);
private:
};
simplelib.cpp
#include <simplelib.h> // подключаем заголовок обязательно
long testClass::getSum(int *array, byte length) {
long sum = 0;
length = length / sizeof(int); // длина массива
for (byte i = 0; i < length; i++) {
sum += array[i];
}
return sum;
}
testSketch.ino
#include <simplelib.h>
testClass tObj;
void setup() {
// делаем массив
int myArray[] = {5, 33, 58, 251, 91};
// передаём массив и его размер (в байтах)
long arraySum = tObj.getSum((int*)myArray, sizeof(myArray));
// arraySum == 438
}
void loop() {
}
Передача в библиотеку констант
Очень распространенной является библиотека, передающая константы в функцию, например pinMode(13, HIGH), где HIGH является константой, автоматически заменяющейся на 1. Данная константа в файле Arduino.h реализуется как раз через define:
#define HIGH 0x1
SimpleLib.h
#pragma once
#include <Arduino.h>
// постоянные величины
#define MID 0.5
#define FOURTH 0.25
#define EIGHT 0.125
class testClass {
public:
void printer(byte value);
private:
};
SimpleLib.cpp
#include <SimpleLib.h> // подключаем заголовок обязательно
void testClass::printer(byte value) {
switch (value) {
case 0: Serial.println(«MID»);
break;
case 1: Serial.println(«FOURTH»);
break;
case 2: Serial.println(«EIGHT»);
break;
}
}
SimpleProg.ino
#include <SimpleLib.h>
testClass testObject;
void setup() {
Serial.begin(9600);
testObject.printer(MID); // вывод MID
testObject.printer(FOURTH); // выведет FOURTH
testObject.printer(EIGHT); // выведет EIGHT
}
void loop() {
}
Использование библиотеки в программе
Для использования библиотеки следует ввести ее класс, например, из предыдущей программы testClass, к нему следует добавить экземпляр класса, т.е. запись будет выглядеть следующим образом:
testClass testObject;
в случае, если у класса имеются переменные, то пишем их следующим образом:
testClass testObject(1);
В данной статье мы рассмотрели способы создания библиотеки и привели примеры организации основных видов программ, требуемых для реализации собственной библиотеки.