Одна из довольно сильных сторон любого программного обеспечени — это возможность единожды написанной программы быть использованной многократно как в виде отдельных частей, так и целиком, что и привело к зарождению концепции «библиотеки».
Можно сказать, что она вполне вписывается в общую парадигму развития цивилизации, которая позволила человеку стать царём дикой природы и обеспечила технический, культурный и интеллектуальный прогресс — это накопление информации и возможность поделиться ею с другими людьми.
Итак, как вы уже поняли, в этом рассказе пойдёт речь о библиотеках. Если бы мы попытались охватить тему библиотек под разные платформы и языки, то это получился бы чудовищных размеров рассказ, поэтому ограничимся небольшой сферой — библиотеками для Arduino.
Рано или поздно любой проект для Arduino сталкивается с тем, что необходимо снова и снова использовать отдельные компоненты кода, так как они не только отработаны и содержат в себе удачные решения, но и к тому же разработчику хорошо знакомы.
Такие фрагменты имеет смысл упаковывать в библиотеки, кроме того, если над одним и тем же проектом работает несколько человек, можно с лёгкостью поделиться своими наработками с другими (не забыв дать им описание API, кстати говоря, подробнее расскажу об этом чуть ниже).
Если вы до этого уже интересовались сутью библиотек и пытались разбирать существующие библиотеки Arduino, то наверняка успели заметить, что они состоят из двух отдельных файлов, один из которых имеет расширение .cpp — что означает «С Plus Plus». Так как язык Wiring для Arduino базируется, по сути, на языке C++, то и решили создавать файлы с таким расширением. Видимо, создатели подумали, что «а ещё это просто красиво» ©. Второй же компонент библиотеки имеет расширение .h ( «Headers»):
- Файл .cpp — называется файлом реализации.
- Файл .h — называется файлом заголовков.
Допустим, что у нас есть некий код, который управляет двигателями. Этот код состоит из ряда участков, среди которых инициализация каких-то переменных и какая-то функция:
Код:
Изначальный код#include <Arduino.h>
#include "esp32-hal-ledc.h"
#include <WiFi.h>
// мотор 1:
int motor1Pin1 = 21;
int motor1Pin2 = 19;
//int enable1Pin = 14;
// мотор 2:
int motor2Pin1 = 23;
int motor2Pin2 = 22;
//int enable2Pin = 32;
const int freq = 30000;
const int pwmChannel = 3;
const int resolution = 8;
int dutyCycle = 0;
const int freq2 = 30000;
const int pwmChannel2 = 4;
const int resolution2 = 8;
int dutyCycle2 = 0;
void setup() {
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
ledcSetup(pwmChannel, freq, resolution); // первый двигатель
ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель
ledcAttachPin(motor1Pin1, pwmChannel);
ledcAttachPin(motor2Pin1, pwmChannel2);
ledcWrite(pwmChannel, dutyCycle);
ledcWrite(pwmChannel2, dutyCycle2);
}
void loop() {
// тут какая то логика работы
}
void Motors (String s)
{
if (s.equals ("Forward") )
{
ledcWrite(pwmChannel, 155);
ledcWrite(pwmChannel2, 155);
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
}
else if (s.equals ("Left") )
{
ledcWrite(pwmChannel, 255);
ledcWrite(pwmChannel2, 0);
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
}
else if (s.equals ("Right") )
{
ledcWrite(pwmChannel, 0);
ledcWrite(pwmChannel2, 255);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
}
else if (s.equals ("Reverse") )
{
ledcWrite(pwmChannel, 125);
ledcWrite(pwmChannel2, 125);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
}
}
В принципе, весь этот код мы можем поместить в файл реализации, то есть с расширением .cpp.
Я специально в качестве кода для примера взял код для esp32 (чуть ниже поясню почему).
Как можно было видеть в коде выше, в его начале расположены стандартные строки #include, которые импортируют библиотеки, используемые в вашем коде. То есть если ваша библиотека является своего рода надстройкой над чужим кодом, то в файле реализации, как и в обычном скетче, необходимо поместить импорты этих библиотек.