Створення власної бібліотеки управління сервоприводом

Серия-статей: Ардуіно, використання сервоприводів #6

Ми створили клас для керування сервоприводом. Але якщо ми хочемо застосовувати його в кількох проектах, то для кожного потрібно буде скопіювати один і той же код. Тому є сенс виділити весь код, що повторюється, в окрему бібліотеку, яку будемо підключати так само, як і стандартні бібліотеки Arduino

Отже, заходимо до папки /libraries нашого середовища розробки Arduino, і бачимо 10-15 папок, кожна з яких відвіяє за стандартну бібліотеку Arduino. Створимо тут папку для нашої бібліотеки, наприклад, ServoClass. Усередині цієї папки створимо два файли: ServoS.h, ServoS.cpp. На жаль, середовище Arduino IDE не підтримує редагування файлів з роздільною здатністю, відмінною від .ino. Тому редагувати бібліотеку доведеться або в іншому середовищі розробки, яке підтримує з ++ або у звичайному текстовому редакторі з підсвічуванням синтаксису, наприклад, AkelPad.

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

Скопіюємо у файл ServoS.h наш клас ServoClass, точніше лише змінні та назви функцій:

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

#ifndef ServoS // Якщо бібліотека ще не була підключена

#define ServoS // Підключити її

#include "Arduino.h" // Використовуємо стандартну бібліотеку Arduino

#include "Servo.h" // Використовуємо стандартну бібліотеку управління сервоприводами

class ServoClass

{

public:

Servo serv; // Власне сам сервопривід, керований стандартною

// бібліотекою servo

int servPosition; // Поточна позиція сервоприводу, градусів

int posMax; // Максимально допустима межа переміщення сервоприводу, градусів

int posMin; // Мінімальна допустима межа переміщення сервоприводу, градусів

int posInit; // Вихідна позиція сервоприводу, градусів

// Змінні, які відповідають за переміщення

boolean move; // Чи повинен рухатися сервопривід зараз

int movePosition; // Позиція, яку має прийняти сервопривід, градуси

float moveSpeed; // Швидкість, з якою сервопривод повинен рухатися, об/хв

int moveIncrement; // Зміна положення за один інтервал часу, градусів

int moveInterval; // Інтервал між рухами для забезпечення швидкості, мілісекунди

unsigned long lastTimeCheck; // Час останнього руху сервоприводу, мс від початку роботи програми

ServoClass(); // Конструктор класу

void AttachServo (int pin); //Ініціалізація сервоприводу із зазначенням лише номери виходу для підключення

void AttachServo (int pin, int minpos, int maxpos, int initpos); //Ініціалізація сервоприводу із зазначенням мінімальної, максимальної та вихідної позиції

int PositionCheck(int movepos); // Перевірка, чи позиція попадає в заданий інтервал

void MoveTo (int movepos); // Подати команду на переміщення сервоприводу

void MoveTo (int movepos, float movespeed) ; // Подати команду на переміщення сервоприводу із зазначенням швидкості

void Update(); //Обробка переміщень

};

#endif

При створенні бібліотеки можна побачити деякі особливості:

Файл починається з директиви #ifndef ServoS, яка перевіряє, чи не було підключено цю бібліотеку раніше. Якщо ми ніде раніше її не підключали, то до програми буде додано код, що знаходиться між #define ServoS та #endif

Крім того ми визначаємо кілька функцій з одним ім'ям та різними аргументами. Це пов'язано з тим, що при використанні бібліотек виклик функції з меншою, ніж визначено кількістю аргументів призведе до помилок. Задати значення аргументів за умовчанням не вдасться, точніше для кожного випадку потрібно буде описати окрему функцію. Тому у нас по дві функції AttachServo та MoveTo

Тепер залишилося розібратися з файлом ServoS.cpp. Тут знаходиться код для описаних у заголовному файлі функцій. При цьому нам потрібно вказувати, до якого класу відносяться функції, що викликаються. Оскільки в нашій бібліотеці використовується клас ServoClass, всі функції будуть ставитися до нього. У випадку конструктора, ім'я якого збігається з ім'ям класу, це буде виглядати як ServoClass::ServoClass(), решта функцій – відповідно ServoClass::Ім'яФункції();

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

#include "ServoS.h" // Підключаємо заголовний файл

ServoClass::ServoClass() // Конструктор класу

{

posMin = 0;

posMax = 180;

posInit = 0;

servPosition=0;

lastTimeCheck=millis();

}

servoClass::AttachServo (int pin) ////Ініціалізація сервоприводу із зазначенням тільки номери виходу для підключення

{

serv.attach(pin); // Підключаємо сервопривід до вказаного піна

posMin = 0; // Встановлюємо мінімальну позицію

posMax = 180; // Встановлюємо максимальну позицію

posInit = 0; // Встановлюємо вихідну позиціюservPosition = posInit; // Позиція сервоприводу повинна відповідати вихідному положенню

serv.write(servPosition); // Даємо команду змінити положення

}

servoClass::AttachServo (int pin, int minpos, int maxpos, int initpos) //Ініціалізація сервоприводу із зазначенням мінімальної, максимальної та вихідної позиції

{

serv.attach(pin); // Підключаємо сервопривід до вказаного піна

posMin = minpos; // Встановлюємо мінімальну позицію

posMax = maxpos; // Встановлюємо максимальну позицію

posInit = initpos; // Встановлюємо вихідну позицію

servPosition = posInit; // Позиція сервоприводу повинна відповідати вихідному положенню

serv.write(servPosition); // Даємо команду змінити положення

}

int ServoClass::PositionCheck(int movepos) // Перевірка, чи потрапляє позиція в заданий інтервал

{

int CheckedPos;

if (movepos<=posMin) // Якщо вказано більше значення, ніж максимальний

// межа переміщення

CheckedPos = posMin; // Рухатимемося тільки до цієї межі

else

if (movepos>=posMax) // Якщо вказано менше значення, ніж мінімальний

//Межа переміщення

CheckedPos = posMin; // Рухатимемося тільки до цієї межі

else // У будь-яких інших випадках - ми в допустимих для переміщення межах

CheckedPos =movepos; // Просто встановлюємо позицію, в яку має

return CheckedPos;

}

ServoClass::MoveTo (int movepos) // Якщо швидкість не вказана - просто даємо команду на переміщення сервоприводу

{

movePosition = PositionCheck(movepos); // Перевіряємо, чи ми виходимо за допустимі межі преміщення

serv.write(servPosition); // Даємо команду змінити положення

}

void ServoClass::MoveTo (int movepos, float movespeed) // Якщо швидкість вказана - організуємо плавне переміщення

{

movePosition = PositionCheck(movepos); // Перевіряємо, чи ми виходимо за допустимі межі преміщення

moveSpeed=movespeed; // Встановлюємо швидкість, з якою має переміщатися сервопривід

int Angle = abs (movePosition-servPosition); // На скільки має переміститися сервопривід

// незалежно від напрямку

if (movePosition >= servPosition) // Визначаємо, в який бік від поточного положення нам потрібно рухатися

moveIncrement=1; // Якщо вперед - додаватимемо один градус за один інтервал часу

else

moveIncrement=-1; // Якщо назад - то забирати

float RotationSpeed=moveSpeed*360/60; // Переводимо швидкість з оборотів за хвилину в градуси за секунду

moveInterval=(int)1000/RotationSpeed; // Обчислюємо інтервал між переміщеннями на градус.

move = true; // Даємо комнду почати плавне переміщення

}

ServoClass::Update () //// Обробка переміщень

{

if (move) // Якщо дана команда на переміщення

{

if ((millis() - lastTimeCheck)>= moveInterval) // перевіряємо, скільки минуло часу з останнього

//Дії та порівнюємо з потрібним нам інтервалом.

//Якщо часу пройшло більше - чинимо наступну дію

{

servPosition+=moveIncrement; // Змінюємо кут на раніше обчислене значення

serv.write(servPosition); // Посилаємо сервоприводу команду з новим кутом повороту

lastTimeCheck = millis (); // Оновлюємо лічильник часу, щоб наступний відлік часу почався з цього моменту

if (servPosition==movePosition) // Якщо ми досягли потрібної позиції-

move = false; // зупинити рух

}

}

}

Якщо під час створення нашої бібліотеки було включено середовище Arduino IDE, то його необхідно закрити і заново перезапустити, оскільки вона збирає дані про доступні бібліотеки під час запуску і повинна буде побачити нашу нову бібліотеку

Власне, зі створенням бібліотеки ми закінчили, залишилося підключити її до нашої програми. Для цього просто замінимо опис нашого класу з попереднього прикладу на "#include "ServoS.h"" Підключимо два сервоприводи і завантажимо скетч:

Схема підключення двох сервоприводів до Arduino з обмеженням по куту повороту та керуванням через користувальницьку бібліотеку

#include "Servo.h" // Підключаємо бібліотеку для роботи із сервоприводом

#include "ServoS.h" // Підключаємо користувальницьку бібліотеку для роботи з сервоприводом

ServoClass serv1;

ServoClass serv2;

void setup()

{

serv1.AttachServo(2); // Перший сервопривід підключений до другого піну

// Стандартні межі переміщення від 0 до 180 градусів

// Стандартне вихідне положення 0 градусів

serv2.AttachServo(3, 20, 160, 90); // Другий сервопривід підключений до третього піна

// Межі переміщення від 20 до 160 градусів

// Початкове становище - 90 градусів

serv1.MoveTo(20); // Переміщаємо перший сервопривід у положення 20 градусів

serv2.MoveTo(150, 0.5); // Переміщаємо другий сервопривід у положення 150 градусів зі швидкістю 0.5 обороту за хвилину

}

void loop()

{

serv1.Update(); // Обробляємо переміщення першого сервоприводу

serv2.Update(); // Обробляємо переміщення другого сервоприводу

}

Результат роботи програми не змінився - перший сервопривід займе вказане положення відразу, а другий повертатиметься досить повільно (його вихідне положення 90 градусів, для переміщення в положення 150 градусів потрібно повернутися на 60 градусів. Швидкість 0.5 обороту в хвилину відповідає 3 градуси в секунду, т .е переміщення займе 20 секунд).

Залишилося оформити нашу бібліотеку для зручнішого використання. Якщо використовувати Arduino IDE, то функції стандартних бібліотек підсвічуються кольором, а для нашої бібліотеки – ні. Тому потрібно повідомити програму, які функції потрібно підсвічувати, для цього потрібно створити файл keywords.txt у папці нашої бібліотеки

Помістимо туди інформацію про ключові слова, які потрібно підсвічувати:

# Підсвічування синтаксису для бібліотеки ServoS

ServoClass KEYWORD1

AttachServo KEYWORD2

PositionCheck KEYWORD2

MoveTo KEYWORD2

Update KEYWORD2

Слова, що позначені KEYWORD1 будуть підсвічені як тип даних, KEYWORD2 – як функції Між словом та його типом ставиться знак табуляції, між рядками – переклад рядка.

Знову перезавантажимо Arduino IDE, тепер наш клас та його функції підсвічуються відповідним кольором.

Еще:

Подключаем сервопривод к Arduino (Arduino, использование сервоприводов #1)
Создаем класс для управления сервоприводом (Arduino, использование сервоприводов #3)
Программное ограничение перемещения сервопривода (Arduino, использование сервоприводов #4)