Не отступай и не сдавайся !!!

+7(495)233-9079
arduino4home@gmail.com

Урок 9
Создание библиотеки для Ардуино.


Предыдущий урок Ардуино - главная Следуюший урок

Научимся создавать собственную библиотеку для программирования на Ардуино.

В прошлом уроке мы закончили создание класса Button – кнопка. Все проверили, отладили код, и собираемся использовать его в дальнейших проектах для Ардуино. Только как практически пользоваться созданным классом. Не очень удачно получилось.

  • В новую программу надо скопировать описание класса и код методов. При этом необходимо выделить эти блоки из старой программы и ничего не перепутать.
  • Эти части программы давно проверены, отлажены и забыты. Тем не менее, они будут постоянно попадаться на глаза, увеличивать код программы, ухудшать ее структурность и читаемость.
  • Еще в эти модули можно случайно занести ошибку, и потом, скопировать ошибочный вариант в следующие программы.

Красивое и практичное решение – создать библиотеку для объекта типа Button.

Последовательность действий для создания библиотеки в программах для Ардуино.

Библиотека в Ардуино это не что иное, как дополнительный класс. Поэтому, прежде всего, необходимо определить функции для библиотеки как класс. Как это сделать, подробно описано в уроке 7.

Оформите свои функции как класс, прежде чем производить дальнейшие действия, а мы используем готовый класс Button из урока 8.

Библиотека должна иметь как минимум два файла:

  • заголовочный файл (расширение .h);
  • файл с исходным кодом (расширение .cpp).

В первом файле содержится описание самого класса, переменные, константы. Кода программы здесь нет.  А второй файл содержит программный код методов.

Назовем новую библиотеку 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.
  • Файл -> Настройки -> Размещение папки скетчей  задал D:\Arduino Projects.  Это я  указал папку моих проектов Ардуино (D:\Arduino Projects).
  • В этой папке я создал папку libraries (D:\Arduino Projects\libraries).
  • В папке libraries создал папку новой библиотеки Button (D:\Arduino Projects\libraries\Button).
  • И уже в эту папку скопировал файлы Button.h, Button.cpp и keywords.txt.

Для проверки надо закрыть и заново запустить 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 мс

Ничего лишнего. Только объекты, с которыми мы работаем.

Хороший стиль добавить в файлы библиотеки примеры. Но у нас в последующих уроках примеров будет достаточно.

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


Хостинг нашего сайта осуществляется узлом www.cherepovets-city.ru
© 2000-2018 28/1/18 15:54->