Как работать с библиотеками ардуино
Перейти к содержимому

Как работать с библиотеками ардуино

  • автор:

Установка библиотек в Arduino IDE

Многие скетчи (программы) работают с библиотеками. Библиотека облегчает работу с определённым модулем или одним из типов модулей. Например, если Вы хотите вывести текст на LCD дисплей без подключения библиотеки, то Вам нужно передать ему несколько байт команд и данных, что займет несколько строк кода, а главное, что Вам нужно знать тип микроконтроллера под управлением которого работает LCD дисплей, назначение команд которыми он управляется, знать архитектуру его памяти, адреса и назначение регистров, для чего потребуется найти и перечитать его datasheet. В то время как при написании кода с использованием библиотеки (например LiquidCrystal_I2C.h) Вы сможете вывести текст на дисплей вызвав всего одну функцию библиотеки: lcd.print(«my text»);

Перед тем как начать пользоваться методами и функциями библиотеки, её нужно скачать (загрузить на Ваш компьютер), установить (разместить в нужной папке) и подключить (вставить текст «#include » в скетч).

Скачивание библиотеки:

Если в наших уроках, описаниях или примерах используется библиотека, то мы указываем ссылку на скачивание этой библиотеки. Все наши библиотеки находятся в zip архиве, но не спешите доставать файлы из архива, это может не понадобиться, т.к. Arduino IDE сама может распаковывать архивы и размещать библиотеки в нужных папках (см. дальше).

Если Вы скачали архив библиотеки с сайта не указывая путь для сохранения файла, то скаченный (загруженный) Вами файл скорее всего находится в папке: Этот компьютер > Загрузки.

Установка библиотеки:

После того как Вы скачали (загрузили) библиотеку на свой компьютер, её нужно установить. Установить библиотеку можно вручную или сделать это средствами Arduino IDE:

Установка библиотеки средствами Arduino IDE:

Войдите в меню: Скетч > Подключить библиотеку > Добавить .ZIP библиотеку. .

В появившемся окне нажмите на иконку «Этот компьютер» и выберите папку «Загрузки». Если при скачивании ZIP архива с сайта, Вы указывали путь для сохранения файла, то вместо папки «Загрузки» укажите путь к файлу.

Выберите ZIP файл библиотеки, который Вы скачали. Название файла может не соответствовать названию библиотеки. После чего нажмите на кнопку «Открыть» (Open).

На этом установка библиотеки завершена, можно приступить к её подключению в скетч.

Установка библиотеки вручную:

Распакуйте скаченный Вами ZIP архив и поместите папку (имя папки обычно совпадает с названием библиотеки) из данного архива в папку: Этот компьютер > Документы > Arduino > libraries.

Если во время копирования Arduino IDE была запущена (открыта), то нужно закрыть все окна этой программы, после чего запустить (открыть) Arduino IDE и можно приступать к подключению библиотеки в скетч.

Примечание: папка libraries есть не только по указанному выше пути, но и в папке программы Arduino IDE (где находится файл arduino .exe). Скопировав библиотеку в эту папку, она тоже установится, но Мы не рекомендуем это делать. Дело в том, что программа Arduino IDE постоянно развивается и количество её версий постоянно растёт. Если Вы захотите установить новую версию Arduino IDE, то библиотеки находящиеся в папке Этот компьютер > Документы > Arduino > libraries, будут доступны и в старой, и в новой (установленной) версии Arduino IDE, а библиотеки находящиеся в папке libraries программы Arduino IDE старой версии (которая была установлена ранее) будут доступны только в ней (пока Вы их не скопируете в новую).

Подключение библиотеки:

Для того чтобы подключить библиотеку, нужно написать всего одну строку в начале скетча: «#include «, например:

#include // Подключение библиотеки iarduino_4LED для работы с 4 сегментными LED индикаторами.

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

#include // Подключение библиотеки Wire для работы с шиной I2C #include // Подключение библиотеки LiquidCrystal_I2C для работы с LCD дисплеем по шине I2C // Библиотека LiquidCrystal_I2C использует методы и функции библиотеки Wire

Для работы с большинством библиотек, нужно создать объект (экземпляр класса библиотеки), через который будут доступны их функции и методы, например:

LiquidCrystal_I2C lcd(0x27,20,4); // lcd это объект библиотеки LiquidCrystal_I2C // через объект обращаются к функциям и методам библиотеки

Вместо lcd можно написать любое слово или сочетание букв и цифр, это название объекта через который можно обращаться к методам и функциям библиотеки. Если Вместо lcd Вы написали myLCD, то и ко всем методам и функциям библиотеки LiquidCrystal_I2C, нужно обращаться через указанное Вами имя объекта, например: myLCD.print(«my text»);

Примеры из библиотек:

Большинство библиотек содержат примеры. Это небольшие скетчи (программы) которые раскрывают функционал библиотеки. Наиболее удобный способ просмотра примеров, с помощью средств Arduino IDE. Выберите пункт меню: Файл > Примеры, откроется список с названиями библиотек у которых есть примеры. Наведите курсор на название библиотеки и Вы увидите список примеров содержащихся в ней, клик на примере приведёт к появлению нового окна Arduino IDE со скетчем примера.

Альтернативный способ просмотра примеров заключается в запуске файлов скетчей из папки:
путь > libraries > название библиотеки > examples > название примера.

Поиск библиотек:

Библиотеки можно искать самостоятельно, а можно воспользоваться функционалом Arduino IDE.

Выберите пункт меню: Скетч > Подключить библиотеку > Управлять библиотеками. .

Откроется «Менеджер библиотек», в котором можно найти интересующую Вас библиотеку введя её название в строку поиска, дополнительно можно установить пункты «Тип» и «Тема».

Нажатие на описании библиотеки приведёт к появлению вкладки «Версия» и кнопки «Установка». После нажатия на кнопку «Установка» можно приступать к подключению библиотеки в скетч «#include «.

Как работать с библиотеками ардуино

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

Что такое библиотека?

Библиотека — это набор функций, предназначенных для того, чтобы максимально упростить работу с различными датчиками, ЖК-экранами, модулями и пр. Например, встроенная библиотека LiquidCrystal позволяет легко взаимодействовать с символьными LCD-экранами. Существуют сотни дополнительных библиотек, которые можно скачать в Интернете. Стандартные библиотеки Ардуино и ряд наиболее часто используемых дополнительных библиотек перечислены в справке. Но перед тем, как использовать дополнительные библиотеки, необходимо сперва установить их.

Как установить библиотеку

Чаще всего библиотеки выкладываются в виде ZIP-архива или просто папки. Название этой папки является названием библиотеки. Внутри папки будет файл с расширением .cpp, файл с расширением .h, а также текстовый файл keywords.txt, папка с примерами examples и другие файлы, требуемые библиотекой.

Автоматическая установка

Начиная с версии 1.0.5, устанавливать сторонние библиотеки можно прямо в среде разработки.

Не распаковывайте скачанный архив с библиотекой — оставьте его, как есть.

В среде разработки Ардуино выберите меню Sketch > Import Library. В самом верху выпадающего списка выберите пункт Add Library (Добавить библиотеку).

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

Снова откройте меню Sketch > Import Library. Вы должны увидеть новую библиотеку в самом низу выпадающего списка. Теперь библиотеку можно использовать в программах.

zip-файл будет уже распакован в директории libraries внутри вашей рабочей папки Ардуино.

Примечание: после выполнения указанных действий библиотеку можно будет полноценно использовать в своих программах, однако примеры из установленной библиотеки появятся в меню File > Examples только после перезапуска среды Ардуино.

Установка вручную

Перед установкой библиотеки закройте среду разработки Ардуино.

Затем распакуйте ZIP-архив с библиотекой. Допустим, вы устанавливаете библиотеку «ArduinoParty» — распакуйте файл ArduinoParty.zip. В нем должна быть папка ArduinoParty с файлами ArduinoParty.cpp и ArduinoParty.h. (Если файлы с расширением .cpp и .h лежат не в папке, то необходимо ее создать. В данном случае вам нужно создать папку с именем ArduinoParty и перенести в нее все файлы из ZIP-архива, например — ArduinoParty.cpp и ArduinoParty.h).

Перетащите папку ArduinoParty в директорию с библиотеками Ардуино. В Windows она будет лежать примерно здесь: «My Documents\Arduino\libraries», у пользователей Mac — здесь: «Documents/Arduino/libraries», а в Linux-системах директория «libraries» будет внутри рабочей папки со скетчами.

После перемещения ваша директория с библиотеками должна выглядеть примерно так (под Windows):

My Documents\Arduino\libraries\ArduinoParty\ArduinoParty.cpp My Documents\Arduino\libraries\ArduinoParty\ArduinoParty.h My Documents\Arduino\libraries\ArduinoParty\examples .
Documents/Arduino/libraries/ArduinoParty/ArduinoParty.cpp Documents/Arduino/libraries/ArduinoParty/ArduinoParty.h Documents/Arduino/libraries/ArduinoParty/examples .

и аналогично на Linux.

Помимо файлов .cpp и .h здесь могут быть и другие файлы — просто убедитесь, что все они теперь лежат здесь.

(Если файлы .cpp и .h расположены в корне папки «libraries» или вложены внутрь еще одной папки, то скачанная библиотека работать не будет. Например:

Documents\Arduino\libraries\ArduinoParty.cpp and Documents\Arduino\libraries\ArduinoParty\ArduinoParty\ArduinoParty.cpp

— не рабочий пример.)

Перезапустите среду Ардуино. Убедитесь, что новая библиотека появилась в меню Sketch->Import Library.

Вот и все! Вы установили библиотеку!

В основе этого урока лежит текст автора Limor Fried.

Текст данного руководства опубликован под лицензией Creative Commons Attribution-ShareAlike 3.0. Примеры кода, встречающиеся в руководстве, являются свободным контентом.

Arduino.ru

Данный документ описывает создание библиотеки для Arduino. Объяснение начнется с написания скетча передачи кода Морзе посредством светодиода. Затем будет показано как конвертировать скетч в библиотеку. Это позволит другим пользователям легко использовать созданный код, обновлять и дополнять его.

Скетч, воспроизводящий код Морзе:

int pin = 13; void setup() < pinMode(pin, OUTPUT); >void loop() < dot(); dot(); dot(); dash(); dash(); dash(); dot(); dot(); dot(); delay(3000); >void dot() < digitalWrite(pin, HIGH); delay(250); digitalWrite(pin, LOW); delay(250); >void dash()

Данный скетч посредством мигания светодиода на выводе 13 выдает сигнал SOS.

Скетч содержит ряд частей кода, которые необходимо будет перенести в библиотеку. Во-первых, это функции dot() и dash(), которые управляют миганием светодиода. Во-вторых, это переменная ledPin, определяющая какой порт ввод/вывода использовать. И наконец, вызов функции pinMode(), устанавливающий режим вывода на используемом порту ввода/вывода.

Процесс конвертации скетча в библиотеку.

Библиотека содержит два файла: заголовочный файл (с расширением .h) и файлы реализации (с расширением .cpp). Заголовочный файл содержит характеристики библиотеки, т.е. список всего что содержится в ней. Создаваемый заголовочный файл будет называться Morse.h. Для дальнейшей работы с заголовочным файлом необходимо просмотреть содержание файла реализации.

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

class Morse < public: Morse(int pin); void dot(); void dash(); private: int _pin; >;

Класс в данном случае это набор функций и переменных, объеденных в одном месте. Функции и переменные могут быть публичными (public), что означает общий доступ к ним всех, кто использует библиотеку, или частными (private), что означает доступ к ним только внутри класса. Каждый класс имеет специальную функцию конструктор, которая используется для создания экземпляра класса. Конструктор имеет тоже имя, что и класс, но не имеет типа возвращаемого значения.

Также заголовочный файл содержит еще несколько дополнительных строк. Во-первых, это директива #include, которая дает доступ к стандартным типам и постоянным языка программирования Arduino (директива по умолчанию добавляется к каждому скетчу, но не к библиотеке). Директива выглядит следующим образом (и находится выше объявления класса):

#include "WProgram.h"

В версиях Arduino 1.0 и выше нужно еще добавить:

#include Arduino.h

Также принято заключать содержимое заголовочного файла в следующую конструкцию:

#ifndef Morse_h #define Morse_h // директивы #include и код помещается здесь #endif

Это предотвращает повторное подключение нашей библиотеки, если кто-то по ошибке дважды подключит библиотеку директивой #include.

В начале кода библиотеки принято помещать комментарий о ее предназначении, авторе, дате и лицензии на библиотеку.

Готовый заголовочный файл содержит:

/* Morse.h - Library for flashing Morse code. Created by David A. Mellis, November 2, 2007. Released into the public domain. */ #ifndef Morse_h #define Morse_h #include "WProgram.h" class Morse < public: Morse(int pin); void dot(); void dash(); private: int _pin; >; #endif

Рассмотрим файл реализации Morse.cpp.

В начале кода находятся несколько директив #include. Данными директивами разрешается доступ к стандартным функциям Arduino и к характеристикам в головном файле библиотеки:

#include "WProgram.h" #include "Morse.h"

Далее по коду находится конструктор. Он используется для создания экземпляра создаваемого класса. В данном случае пользователь задает номер используемого порта ввода/вывода через параметр. Порта устанавливается в режим вывода, а номер сохраняется в частной переменной для использования в других функциях:

Morse::Morse(int pin)

Код Morse:: означает, что функция принадлежит классу Morse. Нижний пробел в начале имени переменной _ pin — принятое обозначение для частных переменных. Вообще, имя может быть любое, но согласно принятым конвенциям именования для частных переменных принято использовать префикс «_». Это также позволяет отличить от аргумента функции (в данном случае pin).

Далее код, который конвертируется в библиотеку из изначального скетча, добавилось только Morse:: и изменилось имя переменной с pin, на _pin:

void Morse::dot() < digitalWrite(_pin, HIGH); delay(250); digitalWrite(_pin, LOW); delay(250); >void Morse::dash()

Общепринято помещать некоторые поясняющие комментарии в начале кода файла реализации. Полный код библиотеки:

/* Morse.cpp — Library for flashing Morse code. Created by David A. Mellis, November 2, 2007. Released into the public domain. */ #include «WProgram.h» #include «Morse.h» Morse::Morse(int pin) < pinMode(pin, OUTPUT); _pin = pin; >void Morse::dot() < digitalWrite(_pin, HIGH); delay(250); digitalWrite(_pin, LOW); delay(250); >void Morse::dash()

Использование библиотеки.

Во-первых, необходимо создать папку Morse в подпапке libraries директории блокнота. Во-вторых, требуется скопировать файлы Morse.h и Morse.cpp в созданную папку. После запуска программы Arduino в меню Sketch > ImportLibrary будет находиться библиотека Morse. Библиотека будет компилироваться совместно со скетчами, использующими ее. Если при компиляции библиотеки возникли проблемы, то необходимо проверить, чтобы ее файлы были с расширениями .cpp и .h (не должно быть никаких дополнительных расширений .pde и .txt).

Изначальный скетч, переписанный с использованием созданной библиотеки, будет выглядеть следующим образом:

#include Morse morse(13); void setup() < >void loop()

Несколько отличий от изначального скетча:

Во-первых, добавлена директивы #include в начало скетча. Таким образом определяется доступность библиотеки Morse и ее подключение. Неиспользуемую библиотеку можно удалить, убрав директиву #include.

Во-вторых, создается экземпляр класса Morse, называемый morse:

Morse morse(13);

При выполнении данной строки (перед выполнением функции setup()) вызывается конструктор для класса Morse и принимает аргумент, данный в примере (13).

При этом функция setup() ничего не содержит, т.к. вызов функции pinMode() произошел внутри библиотеки (когда был создан экземпляр класса).

В-третьих, для вызова функций dot() и dash() необходимо прибавить префикс morse. – имя используемого экземпляра. Может быть несколько экземпляров класса Morse, каждый со своим номером порта, хранящимся в локальной переменной _pin. Вызовом функции конкретного экземпляра определяются какие переменные, используются во время вызова. При наличии следующих двух строк:

Morse morse(13); Morse morse2(12);

внутри вызова morse2.dot(), переменная _pin будет иметь значение 12.

К сожалению автоматическая подсветка кода не работает с подключаемыми библиотеками. Для того чтобы подсветка заработала необходимо создать файл с названием keywords.txt. Пример:

Morse KEYWORD1 dash KEYWORD2 dot KEYWORD2

Напротив каждой строки через табуляцию стоит зарезервированное слово, и опять через табуляцию тип слова. Классы соответствуют зарезервированному слову KEYWORD1 и окрашены в оранжевый цвет; функции – KEYWORD2 и окрашены в коричневый. Для распознавания слов необходимо перезапустить среду разработки Arduino.

Созданную библиотеку желательно всегда сопровождают примером ее применения. Для этого создается папка examples в директории Morse. Затем копируется созданный ранее скетч SOS в данную папку. (Файл скетча можно найти через меню Sketch > ShowSketchFolder). После перезапуска Arduino в меню File > Sketchbook > Examples будет находиться пункт Library-Morse, содержащий пример. Также необходимо добавить комментарии о том, как лучше использовать библиотеку.

Пишем свою библиотеку под Arduino

Одна из довольно сильных сторон любого программного обеспечени — это возможность единожды написанной программы быть использованной многократно как в виде отдельных частей, так и целиком, что и привело к зарождению концепции «библиотеки».

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

Итак, как вы уже поняли, в этом рассказе пойдёт речь о библиотеках. Если бы мы попытались охватить тему библиотек под разные платформы и языки, то это получился бы чудовищных размеров рассказ, поэтому ограничимся небольшой сферой — библиотеками для Arduino.

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

Такие фрагменты имеет смысл упаковывать в библиотеки, кроме того, если над одним и тем же проектом работает несколько человек, можно с лёгкостью поделиться своими наработками с другими (не забыв дать им описание API, кстати говоря, подробнее расскажу об этом чуть ниже).

Если вы до этого уже интересовались сутью библиотек и пытались разбирать существующие библиотеки Arduino, то наверняка успели заметить, что они состоят из двух отдельных файлов, один из которых имеет расширение .cpp — что означает «С Plus Plus». Так как язык Wiring для Arduino базируется, по сути, на языке C++, то и решили создавать файлы с таким расширением. Видимо, создатели подумали, что «а ещё это просто красиво» ©. Второй же компонент библиотеки имеет расширение .h ( «Headers»):

  • Файл .cpp — называется файлом реализации.
  • Файл .h — называется файлом заголовков.

Допустим, что у нас есть некий код, который управляет двигателями. Этот код состоит из ряда участков, среди которых инициализация каких-то переменных и какая-то функция:

Изначальный код

#include #include "esp32-hal-ledc.h" #include // мотор 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 , которые импортируют библиотеки, используемые в вашем коде. То есть если ваша библиотека является своего рода надстройкой над чужим кодом, то в файле реализации, как и в обычном скетче, необходимо поместить импорты этих библиотек.

Те, кто давно работает с esp32, знают, что у неё некоторые функции отличаются от стандартных Arduino, теоретически мы могли бы не помещать в этот код импорт стандартных функций Arduino (ведь железка-то отличается!), но это будет неверно, так как в любом случае для инициализации пинов мы используем стандартную функцию pinMode() , кроме того, используется стандартная digitalWrite() . Поэтому, хочешь не хочешь, нам придётся включить строку:

#include

Повторюсь, всё как и в обычном скетче: подключаем только те библиотеки, которые реально используются в вашем коде.

Далее мы обратим внимание вот на какой момент. Дело в том, что любая работа с какой-либо периферией требует её подключения с использованием вышеназванной функции pinMode() как минимум, а есть ещё разнообразные настройки, как в нашем случае.

На первый взгляд всё хорошо и в файле присутствует подключение периферии. Однако самые внимательные уже заметили, что обычно подключение периферии в скетче у нас происходит внутри блока setup () <> .

Однако в данном случае мы работаем над созданием библиотеки, и здесь никакого блока setup () <> не существует, и если мы попытаемся оставить всё как есть, и функции подключения периферии останутся лежать «просто так, снаружи», то код с подключённой нашей самодельной библиотекой не сможет скомпилироваться, и компилятор выдаст ошибку, если мы используем вот такое содержимое файла реализации (.cpp):

Код с ошибкой

#include #include "esp32-hal-ledc.h" #include // мотор 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; 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 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); >>

Я сейчас говорю вот об этом участке, который лежит как «не пришей кобыле хвост»:

 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);

И что же делать в таком случае? А вот что: необходимо функции инициализации пинов обернуть в функцию! То есть они не должны лежать снаружи, их нужно поместить внутрь функции (setupMotors() ) :

Правильный код реализации

#include #include "esp32-hal-ledc.h" #include // мотор 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 setupMotors() < 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 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); >>

Такой код благополучно скомпилируется, после того как мы создадим библиотеку, подключим её, а после вызовем вот эту функцию, внутри блока setup :

#include void setup() < setupMotors(); >void loop() < // Какой-то код >

Есть общее правило: если требуется некий функционал, который должен быть вызван внутри блока setup (для инициализации чего-либо), то он обязательно должен быть обёрнут в функцию.

По сути, ваш файл реализации готов, и мы перейдём к файлу заголовков — с расширением .h.

Для создания файла заголовков вам всего лишь нужно перенести туда названия ваших функций из файла с расширением .cpp в виде простого списка, с точкой с запятой в конце каждой строки:

void Motors (String s); void setupMotors();

Файл тоже готов.

Кстати говоря, тут интересный момент: вы сами определяете, какие функции будут доступны «снаружи» для пользователей! То есть этот набор функций, перечисленных в файле с расширением .h — и есть Application Programming Interface (API), то есть набор способов, с помощью которых можно взаимодействовать с вашей программой. Причём, как я уже говорил, у вас в файле реализации могут внутри быть ещё и другие функции, которые вы просто не пожелали дать для использования. Имеете право, почему нет.

А теперь посмотрим чуть более сложный пример, «объектно-ориентированное программирование» у нас или где 🙂

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

На самом деле, даже в этой ситуации, код ненамного усложнится:

  • Принципиально подобная библиотека, содержащая класс, также будет состоять из двух отдельных файлов, сохранённых с расширениями .cpp и .h.
  • Вся реализация методов также будет собрана в файле .cpp.
  • Сами методы также будут перечислены в файле с расширением .h.

Чтобы всё это было несколько интересней, мы можем даже немного усугубить ситуацию, добавить модификаторы доступа: public и protected .

В результате всё это будет выглядеть примерно так. Файл реализации (.cpp):

#include #include void Murlicat(String gladit) < //. некая реализация >void DatPogladitPuziko(int x, int y, int l) < //. некая реализация >void TrogatZadniyeLapki(int a, int b) < //. некая реализация >
class Kotofey < public: void Murlicat(String gladit); protected: void DatPogladitPuziko(int x, int y, int l); void TrogatZadniyeLapki(int a, int b); >;

Ну и напоследок, если мы хотим, чтобы наша библиотека была «совсем модной», то можем включить туда предварительно настроенные примеры, чтобы люди могли сразу понять, как им взаимодействовать с этой библиотекой. Для этого необходимо в директории, где находится два основых файла этой библиотеки (.cpp и .h), создать ещё и отдельную папку под названием examples, внутри которой в отдельную, совпадающую по названию со скетчем папку, положить код вашего примера.

Таким образом, путь до вашего примера будет выглядеть следующим образом:

Ваша_библиотека/examples/пример.ino

Но мало создать библиотеку, необходимо её ещё и положить в специальное место, для того чтобы среда разработки могла её увидеть:

  • В первом случае вы можете подключить заархивированную библиотеку изнутри Arduino IDE, пройдя по пути: скетч-подключить библиотеку-добавить zip. библиотеку .
  • Во втором случае вы можете просто положить её стандартную папку библиотек Arduino: C:\Arduino\libraries
  • Или если вы используете portable-версию среды разработки (т.к. я, например, ношу её везде с собой на флешке, и она не требует установки), то положить сюда: C:\arduino-1.8.19\portable\sketchbook\libraries (в моём случае используется версия Arduino 1.8.19 – у вас может быть другая).

В этом файле мы пишем, разделяя с помощью TAB-клавиши клавиатуры, определённое понятие и цвет его подсветки.

У нас есть 3 варианта подсветки:

  • KEYWORD1: толстый оранжевый шрифт (классы, типы данных).
  • KEYWORD2: оранжевый шрифт (методы, функции).
  • LITERAL1: голубой шрифт (константы).
Kotofey KEYWORD1 Murlicat KEYWORD2 DatPogladitPuziko KEYWORD2 TrogatZadniyeLapki KEYWORD2 KoluchestvoLapok LITERAL1 

Вот таким нехитрым образом мы можем обеспечить как многократное использование удачного кода, так и лёгкое его «расшаривание» тем, кто работает в этом же направлении.

НЛО прилетело и оставило здесь промокод для читателей нашего блога:

— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS .

  • FirstVDS
  • arduino
  • библиотеки
  • ардуино
  • ардуино головного мозга
  • разработка
  • разработка под arduino
  • Блог компании FirstVDS
  • Программирование
  • Разработка под Arduino

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *