Урок 9
|
Предыдущий урок | Ардуино - главная | Следуюший урок |
Научимся создавать собственную библиотеку для программирования на Ардуино.
В прошлом уроке мы закончили создание класса Button – кнопка. Все проверили, отладили код, и собираемся использовать его в дальнейших проектах для Ардуино. Только как практически пользоваться созданным классом. Не очень удачно получилось.
Красивое и практичное решение – создать библиотеку для объекта типа Button.
Последовательность действий для создания библиотеки в программах для Ардуино.
Библиотека в Ардуино это не что иное, как дополнительный класс. Поэтому, прежде всего, необходимо определить функции для библиотеки как класс. Как это сделать, подробно описано в уроке 7.
Оформите свои функции как класс, прежде чем производить дальнейшие действия, а мы используем готовый класс Button из урока 8.
Библиотека должна иметь как минимум два файла:
В первом файле содержится описание самого класса, переменные, константы. Кода программы здесь нет. А второй файл содержит программный код методов.
Назовем новую библиотеку Button и создадим заголовочный файл Button.h.
Arduino IDE не поддерживает редактирование текстовых файлов. Редактировать файлы библиотеки можно в любой среде разработки для C++ или в текстовом редакторе, желательно с подсветкой синтаксиса. Я использую Notepad.
Заголовочный файл Button.h
Сначала напишем в файл текстовую информацию о библиотеке. Сообщим там все, что считаем нужным: как называется, для чего предназначена, как пользоваться, кто ее создал и т.п. Конечно, текст надо оформить как комментарий.
// информация о библиотеке // Все остальное содержимое h-файла мы должны заключить в конструкцию: // проверка, что библиотека еще не подключена #ifndef Button_h // если библиотека Button не подключена #define Button_h // тогда подключаем ее // ............ #endif
Эти директивы исключают повторное подключение библиотеки. Внутри конструкции следует написать:
#include "Arduino.h"
Директива #include предписывает компилятору включить в код программы текст из файла, имя которого следует после директивы. В данном случае будет включен файл Arduino.h, содержащий стандартные константы и переменные языка Ардуино. В обычных программах он добавляется автоматически, а для библиотеки должен быть указан явно.
Осталось добавить описание нашего класса Button. Полностью файл Button.h выглядит так.
// Button.h - библиотека для цифровой обработки сигналов контактов кнопок и сигналов других компонентов параллельным процессом // В параллельном процессе должен регулярно вызываться один из методов: void scanState(); // метод проверки ожидание стабильного состояния сигнала void filterAvarage(); // метод фильтрации сигнала по среднему значению
В результате формируются признаки:
- для методаscanState(): - при нажатой кнопке flagPress= true - при отжатой кнопке flagPress= false - при нажатии на кнопку flagClick= true - для метода filterAvarage(): - при сигнале низкого уровня flagPress= true - при сигнале высокого уровня flagPress= false - при изменении состояния с высокого на низкий flagClick= true - Объект типа Button при создании имеет параметры: - номер вывода, к которому подключена кнопка или сигнал - время обработки сигнала (умножается на период вызова метода scanState() или filterAvarage() - Button button1(12, 15); // создание объекта для кнопки, подключенной к 12 выводу с временем фильтрации 30 мс (при цикле 2 мс) Библиотека разработана Калининым Эдуардом http://mypractic.ru/urok-8-cifrovaya-filtraciya-signalov-v-programmax-dlya-arduino.html */ // проверка, что библиотека еще не подключена #ifndef Button_h // если библиотека Button не подключена #define Button_h // тогда подключаем ее #include "Arduino.h" // класс обработки сигналов class Button { public: Button(byte pin, byte timeButton); // конструктор boolean flagPress; // признак кнопка нажата (сигнал в низком уровне) boolean flagClick; // признак клика кнопки (фронт) void scanState(); // метод проверки ожидание стабильного состояния сигнала void filterAvarage(); // метод фильтрации по среднему значению void setPinTime(byte pin, byte timeButton); // установка номера вывода и времени фильтрации private: byte _buttonCount; // счетчик времени фильтрации byte _timeButton; // время фильтрации byte _pin; // номер вывода }; #endif
Исходный файл библиотеки Button.cpp.
В начале файла разместим ту же самую текстовую информацию, как и в Button.h. Неизвестно какой из файлов будет изучать пользователь.
Далее пишем директивы #include для включения стандартных функций Ардуино и заголовочного файла.
#include "Arduino.h" #include "Button.h"
А затем коды методов нашего класса.
Полностью файл Button.cpp выглядит так:
/* Button.h - библиотека для цифровой обработки сигналов контактов кнопок и сигналов других компонентов параллельным процессом
В параллельном процессе должен регулярно вызываться один из методов:
void scanState();// метод проверки ожидание стабильного состояния сигнала void filterAvarage(); // метод фильтрации сигнала по среднему значению
В результате формируются признаки:
- для метода scanState(): - при нажатой кнопке flagPress= true - при отжатой кнопке flagPress= false - при нажатии на кнопку flagClick= true для метода filterAvarage() : - при сигнале низкого уровня flagPress= true - при сигнале высокого уровня flagPress= false - при изменении состояния с высокого на низкий flagClick= true Объект типа Button при создании имеет параметры: - номер вывода, к которому подключена кнопка или сигнал - время обработки сигнала (умножается на период вызова метода scanState() или filterAvarage() Button button1(12, 15); //- создание объекта для кнопки, подключенной к 12 выводу с временем фильтрации 30 мс (при цикле 2 мс) Библиотека разработана Калининым Эдуардом http://mypractic.ru/urok-8-cifrovaya-filtraciya-signalov-v-programmax-dlya-arduino.html */ #include "Arduino.h" #include "Button.h" // метод фильтрации сигнала по среднему значению // при сигнале низкого уровня flagPress= true // при сигнале высокого уровня flagPress= false // при изменении состояния с высокого на низкий flagClick= true void Button::filterAvarage() { if ( flagPress != digitalRead(_pin) ) { // состояние кнопки осталось прежним if ( _buttonCount != 0 ) _buttonCount--; // счетчик подтверждений - 1 с ограничением на 0 } else { // состояние кнопки изменилось _buttonCount++; // +1 к счетчику подтверждений if ( _buttonCount >= _timeButton ) { // состояние сигнала достигло порога _timeButton flagPress= ! flagPress; // инверсия признака состояния _buttonCount= 0; // сброс счетчика подтверждений if ( flagPress == true ) flagClick= true; // признак клика кнопки } } } // метод проверки ожидание стабильного состояния сигнала // при нажатой кнопке flagPress= true // при отжатой кнопке flagPress= false // при нажатии на кнопку flagClick= true void Button::scanState() { if ( flagPress != digitalRead(_pin) ) { // признак flagPress = текущему состоянию кнопки // (инверсия т.к. активное состояние кнопки LOW) // т.е. состояние кнопки осталось прежним _buttonCount= 0; // сброс счетчика подтверждений состояния кнопки } else { // признак flagPress не = текущему состоянию кнопки // состояние кнопки изменилось _buttonCount++; // +1 к счетчику состояния кнопки if ( _buttonCount >= _timeButton ) { // состояние кнопки не мянялось в течение заданного времени // состояние кнопки стало устойчивым flagPress= ! flagPress; // инверсия признака состояния _buttonCount= 0; // сброс счетчика подтверждений состояния кнопки if ( flagPress == true ) flagClick= true; // признак фронта кнопки на нажатие } } } // метод установки номера вывода и времени подтверждения void Button::setPinTime(byte pin, byte timeButton) { _pin= pin; _timeButton= timeButton; pinMode(_pin, INPUT_PULLUP); // определяем вывод как вход } // описание конструктора класса Button Button::Button(byte pin, byte timeButton) { _pin= pin; _timeButton= timeButton; pinMode(_pin, INPUT_PULLUP); //- определяем вывод как вход }
Для того чтобы Arduino IDE выделяла цветом новые типы и методы из нашей библиотеки можно создать файл keywords.txt.
Button KEYWORD1 scanState KEYWORD2 filterAvarage KEYWORD2 setPinTime KEYWORD2
Каждая строка содержит ключевое слово, табуляцию (не пробелы) и тип ключевого слова.
KEYWORD1 определяет классы, KEYWORD2 – методы.
Загрузить zip-архив с тремя файлами библиотеки Button можно здесь.
Теперь нужно правильно разместить файлы библиотеки.
Я сделал так:
Для проверки надо закрыть и заново запустить Arduino IDE. Открыть Скетч -> Подключть библиотеку и посмотреть, что в списке библиотек присутствует новая библиотека Button.
Как пользоваться библиотекой.
Очень просто. В начале программы включить заголовочный файл директивой
#include <Button.h>
Теперь можно пользоваться всеми открытыми методами и переменными класса Button абсолютно так же, как в предыдущем уроке.
Перепишем программу управления светодиодами из предыдущего урока. Естественно с использованием библиотеки Button.
/* Программа sketch_9_1 урока 9 * К плате Ардуино подключены 2 кнопки и светодиод * Каждое нажатие кнопки 1 инвертирует состояние светодиода на плате Ардуино * Каждое нажатие кнопки 2 инвертирует состояние светодиода на макетной плате */ #include <Button.h> #define LED_1_PIN 13 // светодиод 1 подключен к выводу 13 #define BUTTON_1_PIN 12 // кнопка 1 подключена к выводу 12 #define BUTTON_2_PIN 11 // кнопка 2 подключена к выводу 11 #define LED_2_PIN 10 // светодиод 2 подключен к выводу 10 boolean ledState1; // переменная светодиода 1 boolean ledState2; // переменная светодиода 2 Button button1(BUTTON_1_PIN, 15); // создание объекта для кнопки 1 Button button2(BUTTON_2_PIN, 15); // создание объекта для кнопки 2 void setup() { pinMode(LED_1_PIN, OUTPUT); // определяем выводы светодиодов как выходы pinMode(LED_2_PIN, OUTPUT); } // цикл с периодом 2 мс void loop() { button1.filterAvarage(); // вызов метода фильтрации по среднему для кнопки 1 button2.scanState(); // вызов метода ожидания стабильного состояния для кнопки 2 // блок управления светодиодом 1 if ( button1.flagClick == true ) { // был клик кнопки button1.flagClick= false; //- сброс признака ledState1= ! ledState1; //- инверсия состояние светодиода digitalWrite(LED_1_PIN, ledState1); //- вывод состояния светодиода } // блок управления светодиодом 2 if ( button2.flagClick == true ) { // был клик кнопки button2.flagClick= false; // сброс признака ledState2= ! ledState2; // инверсия состояние светодиода digitalWrite(LED_2_PIN, ledState2); // вывод состояния светодиода } delay(2); // задержка 2 мс
Ничего лишнего. Только объекты, с которыми мы работаем.
Хороший стиль добавить в файлы библиотеки примеры. Но у нас в последующих уроках примеров будет достаточно.
В следующем уроке мы научимся работать с прерываниями по аппаратному таймеру.