Создание собственной библиотеки управления двигателем постоянного тока

Серия-статей: Arduino, использование двигателей постоянного тока #4

Серия-статей: Создание библиотек для Arduino #2

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

Итак, заходим в папку /libraries нашей среды разработки Arduino, и видим 10-15 папок, каждая из которых отвеяает за стандартную библиотеку Arduino. Создадим здесь папку для нашей библиотеки, например MotorS(путь к ней должен выглаядеть примерно как “/Arduino/libraries/MotorS/"). Внутри этой папки создадим два файла: MotorS.h, MotorS.cpp. К сожалению среда Arduino IDE не поддерживает редактирование файлов с разрешением, отличным от .ino. Поэтому редактировать библиотеку придется либо в другой среде разработки, которая поддерживает с++ или в обычном текстовом редакторе с подсветкой синтаксиса, например AkelPad.

Первый файл, MotorS.h – заголовочный файл (от слова header file), здесь будут описываться сам класс, переменные и функции. При этом здесь располагают только список переменных и функций и их типов, без тела самих функций.

Скопируем в файл MotorS.h наш класс MotorClass, точнее только переменные и названия функций:

/* Пользовательская библиотека управления сервоприводами, заголовочный файл */

#ifndef MotorS // Если библиотека еще не была подключена

#define MotorS // Подключить ее

#include "Arduino.h" // Используем стандартную библиотеку Arduino

class MotorClass

{

public:

byte pinE; // Номер цифрового выхода для управления скоростью – должен поддерживать ШИМ

byte pinI; // Номер цифрового выхода для управления направлением вращения

boolean SpeedChanging; // Включен ли режим ускорения двигателя (обрабатывается функцией UpdateSpeed())

unsigned long StartTimer; // Таймер для плавного пуска

int StartTimeStep; // Интервал изменения мощности двигателя, в мс

int StartPowerStep; // Один шаг изменения мощности двигателя

int ReqPower; // До какого занчения будет меняться мощность двигателя

int Power; // Мощность двигателя (0 - остановка, 255 - полная мощность)

int Direction; // Направление вращения

MotorClass(int pE, int pI) ; // Конструктор класса. Первый аргумент - номер пина управления скоростью, второй - направлением

void RunMotor(int motorpower); // Задаем скоротсь и направления вращения двигателя

// Отрицательное значение - вращение в обратную сторону

void SetSpeed(int newspeed); // Устанавливаем скорость двигателя в процентах от максимума.

void SetSpeed(int newspeed, int smooth); // Плавно меняем скорость двигателя в процентах от максимума.

// Отрицательное значение - вращение в обратную сторону

// Плавность изменения регулируется значнением smooth (время на один шаг изменения скорости, в мс)

void UpdateSpeed(); // Обаработка действий, которые должны производиться с заддержкой, в частности плавного изменения скорости

};

#endif

При создании библиотеки можно заметить некоторые особенности:

Файл начинается с директивы #ifndef ServoS, которая проверяет, не был ли подключена эта библиотека ранее. Если мы нигде ранее ее не подключали, то в программу, будет добавлен код, находящийся между #define MotorS и #endif

Кроме того мы определяем несколько функций с одним именем но разными аргументами. Это связано с тем, что при использовании библиотек вызов функции с меньшим, чем определено, количеством аргументов приведет к ошибк. Задать значения аргументов по умолчанию не получится, точнее для каждого случая нужно будет описать отдельную функцию. Поэтому у нас по две функции SetSpeed(int newspeed) и SetSpeed(int newspeed, int smooth)

Теперь осталось разобараться с файлом MotorS.cpp. Здесь находится код для описанных в заголовочном файле функций. При этом нам нужно указывать, к какому классу относятся вызываемые функции. Поскольку в нашей библиотеке используется класс MotorClass, то все функции будут относиться к нему. В случае конструктора, имя которого совпадает с именем класса, это будет выглядеть как MotorClass:: MotorClass (), остальные функции – соответственно MotorClass::ИмяФункции();

/* Пользовательская библиотека управления сервоприводами */

#include "MotorS.h" // Подключаем заголовочный файл

MotorClass::MotorClass(int pE, int pI) // Конструктор класса. Первый аргумент - номер пина управления скоростью, второй - направлением

{

pinE=pE; // Задаем управляющие пины для скорости

pinI=pI; // И направления вращения

pinMode (pinE, OUTPUT); // Задаем работу соответствующих пинов в качестве выходов

pinMode (pinI, OUTPUT);

Power=0; // по умолчанию двигатель стоит

SpeedChanging=false; // по умолчанию двигатель не ускоряется

}

void MotorClass::RunMotor(int motorpower) // Задаем скоротсь и направления вращения двигателя

// Отрицательное значение - вращение в обратную сторону

{

Direction=(motorpower>0)?HIGH:LOW; // Если указано положительная скорость - на выход направления подается сигнал HIGH

digitalWrite(pinI,Direction); // для отрицательной - LOW

digitalWrite(pinE,abs(Power)); // Подаем на выход управления скоростью сигнал, который соответствует нужной скорости

}

void MotorClass::SetSpeed(int newspeed) // Устанавливаем скорость двигателя в процентах от максимума.

{

Power=(int)newspeed/2.55; // Поскольку скорость меняется от 0 дл 100 %, а мощность - в диапазоне от 0 до 255,

// вычисляем необходимое значение мощности

RunMotor(Power);

}

void MotorClass::SetSpeed(int newspeed, int smooth) // Плавно меняем скорость двигателя в процентах от максимума.

// Отрицательное значение - вращение в обратную сторону

// Плавность изменения регулируется значнением smooth (время на один шаг изменения скорости, в мс)

{

ReqPower=(int)newspeed/2.55; // Поскольку скорость меняется от 0 дл 100 %, а мощность - в диапазоне от 0 до 255, вычисляем нужное значение

if (ReqPower>=Power) // В какую сторону будет меняться мощность?

StartPowerStep=1; // увеличиваться на 1 (1/255 от полной)

else

StartPowerStep=-1; // уменьшаться на 1 (1/255 от полной)

StartTimeStep=smooth;

StartTimer=millis(); // Начинаем отсчет времени для изменения скорости

SpeedChanging=true; // устанавливаем режим изменения скорости, для последующей обработки в функции UpdateSpeed()

}

void MotorClass::UpdateSpeed() // Обаработка действий, которые должны производиться с заддержкой,

{

if (SpeedChanging) // Если установлен режим изменения скорости

if ((millis()-StartTimer)>= StartTimeStep) // Если с предыдущего изменения скорости прошло больше времени, чем задано

{

if (Power!=ReqPower) // Пока не достигли нужной скорости

{

Power+=StartPowerStep; // меняем скорость

RunMotor(Power); // даем команду двигателю

StartTimer=millis(); // устанавливаем таймер для начала отсчета для следующего измеенния мощности

}

else // Если нужная скорость достигнута

SpeedChanging=false; // Выключаем режим изменения скорости

}

}

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

Подключение двух двигателей постоянного тока к Arduino через драйвер L298P для управления пользовательской библиотекой

В коде программы всю часть, которая отвечала за описание нашего класса MotorClass заменим на функцию подключения библиотеки #include "MotorS.h". Размер загружаемых в контроллер данных практически не изменится (ведь мы, фактически, добавляем код из библиотеки к тому, который отображается в поле редактиорвания). Но работать с такой программой намного проще, ведь не нужно каждый раз, когда мы хотим управлять двигателями, копировать все управляющие переменные и функции.Вот что у нас получилось:

/* Управление двигателями постоянного тока пользовательской библиотекой с поддержкой плавного изменения скорости */

#include "MotorS.h" // Подключаем библиотеку для работы с двигателями постоянного тока

MotorClass M1(5,4); // Первый двигатель управляется выходами 5 и 4 (скорость и направление соответственно)

MotorClass M2(6,7); // Второй двигатель управляется выходами 6 и 7

void setup()

{

M1.SetSpeed(50); //Первый двигатель - включить на 50% скорости

M1.SetSpeed(-100, 2); // Второй двигатель - включить на 100% скорости плавно

}

void loop()

{

M1.UpdateSpeed(); // Обработать изменения скорости первого двигателя

M2.UpdateSpeed(); // Обработать изменения скорости второго двигателя

}

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

Осталось только позаботиться о подсветке созданных нами функций в Arduino IDE. Для этого созадим в папке с нашей библиотекой файл keywords.txt (путь к нему должен выглаядеть примерно как “/Arduino/libraries/MotorS/keywords.txt”) В этот файл запишем названия нашего класса и его метода, пометив их «KEYWORD1» для имени класса и «KEYWORD2» для методов:

Поместим туда информацию о ключевых словах, которые нужно подсвечивать:

# Подсветка синтаксиса для библиотеки MotorS

MotorClass KEYWORD1

RunMotor KEYWORD2

SetSpeed KEYWORD2

UpdateSpeed KEYWORD2

Между словом и его типом ставится знак табуляции, между строками – перевод строки.

Опять перезагрузим Arduino IDE, теперь наш класс и его функции подсвечиваются соответствующим цветом:

Без keywords.txt:

Код управления двигателями с помощью пользовательской библиотекой без подсветки синтаксиса

С использованием keywords.txt:

Код управления двигателями с помощью пользовательской библиотекой с правильно созданным файлом keywords.txt

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

Еще:

Подключаем двигатель постоянного тока. Микросхема L298P (Arduino, использование двигателей постоянного тока #1)
Плавный пуск двигателя постоянного тока с использованием таймеров (Arduino, использование двигателей постоянного тока #2)
Создание класса для работы с двигателем постоянного тока (Arduino, использование двигателей постоянного тока #3)
Создание собственной библиотеки управления двигателем постоянного тока (Arduino, использование двигателей постоянного тока #4)