Классы в ардуино

Классы Arduino

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

Класс подобен шаблону, который позволяет повторно использовать код без необходимости вводить его снова и снова.

Например, вам нужно создать 20 документов с одинаковым шрифтом, заголовком и полями. Было бы слишком много времени, чтобы изменить форматирование всех 20 документов по отдельности. Вместо этого вы можете создать шаблон документа с правильным шрифтом, заголовком и полями, затем добавить текст и сохранить его как отдельный файл.

Классы подобны этому шаблону документа. Классы — это шаблоны кода для того, что называется «объектами». Думайте о классе как о шаблоне документа, а об объекте — как об отдельном документе. Объекты позволяют вам получить доступ к функциям и переменным внутри класса. Объект иногда называют «экземпляром» класса.

Пример «Мигающие светодиоды» без классов и объектов

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

Вот детали, которые вам понадобятся для этого проекта:

  • Arduino Uno
  • Соединительные провода
  • Макетная плата
  • Два резистора 220 Ом
  • Два светодиода

Схема подключения для проекта приведена ниже:

Схема подключения светодиодов для примера

Этот скетч заставит синий светодиод включаться и выключаться в течение трех секунд, а зеленый светодиод включаться и выключаться в течение полторы секунды:

int blue = 9;
int green = 10;

void setup() {
  pinMode(blue, OUTPUT);
  pinMode(green, OUTPUT);
}

void loop() {
  digitalWrite(blue, HIGH);
  delay(3000);
  digitalWrite(blue, LOW);
  delay(3000);

  digitalWrite(green, HIGH);
  delay(1500);
  digitalWrite(green, LOW);
  delay(1500);
}

Пояснения к коду

Сперва в скетче мы объявляем переменные для контактов синего blue и зеленого green светодиодов.

В разделе setup() мы устанавливаем режим вывода для каждого светодиода как OUTPUT (выход).

В разделе бесконечного цикла loop() мы поочередно записали следующее:

  • устанавливаем высокий уровень HIGH для синего светодиода;
  • пауза на 3000 миллисекунд;
  • устанавливаем низкий уровень LOW для синего светодиода;
  • еще раз пауза на 3000 миллисекунд;
  • устанавливаем высокий уровень HIGH для зеленого светодиода;
  • пауза на 1500 миллисекунд;
  • устанавливаем низкий уровень LOW для зеленого светодиода;
  • пауза на 1500 миллисекунд.

Это много кода для такой простой задачи, как включение и выключение пары светодиодов. Мы можем сделать эту программу намного меньше с помощью классов и объектов.

Пример «Мигающие светодиоды», используя классы Ардуино

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

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

Заголовочный файл

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

Шаг 1. Защита от повторного включения

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

#ifndef MyLED_h
#define MyLED_h
   // Здесь будет код
#endif

Вы можете назвать заголовочный файл как угодно, но в этой статье он будет называться MyLED. Файл заголовка должен быть сохранен с расширением .h. В #ifndef и #define за именем файла заголовка должен следовать _h.

Шаг 2. Подключение библиотеки Arduino.h

Далее нам нужно подключить библиотеку Arduino.h. Ардуино.h — это основная библиотека, которая содержит все встроенные функции Arduino. Включение его в заголовочный файл делает эти функции доступными для использования в классе:

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
#endif

Шаг 3. Определение класса

Теперь мы можем определить класс. Чтобы определить класс, напишите class, за которым следует имя класса:

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
   // Здесь код класса
};
#endif

Имя класса в этом примере — MyLED. Код класса заключен в фигурные скобки.

Функции и переменные внутри класса могут быть общедоступными public или приватными private:

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
public:
private:
};
#endif

Ключевые слова public и private известны как модификаторы доступа. Общедоступные функции и переменные можно использовать внутри скетча, но приватные функции и переменные можно использовать только внутри класса.

Шаг 4. Объявление конструктора класса

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

Мы напишем фактический код для конструктора, когда определим его в исходном файле, но нам все равно нужно объявить его в заголовочном файле. Поскольку объекты будут создаваться в скетче, объявление конструктора должно быть общедоступным и иметь тоже имя, что и класс. Класс в этом примере называется MyLED, поэтому объявление конструктора будет MyLED():

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
public:
    MyLED();
private:
};
#endif

В этом примере проекта у нас будет два светодиода, подключенных к Arduino. Поэтому нам нужно установить режим функцией pinMode каждого вывода светодиода как выход OUTPUT. Когда мы напишем код для конструктора в исходном файле, мы поместим в него функцию pinMode(). Эта функция принимает номер вывода в качестве первого параметра. Нам нужно передать этот номер контакта конструктору, чтобы функция pinMode() могла его использовать. Для этого мы объявляем переменную int с именем pin внутри круглых скобок объявления конструктора:

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
public:
    MyLED(int pin);
private:
};
#endif

Шаг 5. Объявление функции

Теперь нам нужно объявить функцию, которая заставит светодиоды мигать. Функции внутри классов объявляются так же, как они объявляются в скетчах. Сначала запишем возвращаемый тип. Эта функция не собирается возвращать никаких значений, поэтому возвращаемый тип — void. Затем напишем имя функции. Давайте назовем ее myBlink():

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
public:
    MyLED(int pin);
    void myBlink();
private:
};
#endif

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

Давайте объявим переменную в myBlink() для хранения этого параметра и назовем ее rate:

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
public:
    MyLED(int pin);
    void myBlink(int rate);
private:
};
#endif

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

Шаг 6. Объявление приватных переменных

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

Соглашение об именах для приватных переменных заключается в нижнем подчеркивании _ перед именем переменной.

Итак, давайте объявим закрытую переменную с именем _pin:

#ifndef MyLED_h
#define MyLED_h
#include "Arduino.h" 
class MyLED {
public:
    MyLED(int pin);
    void myBlink(int rate);
private:
    int _pin;
};
#endif

Это весь код, который нам нужен для заголовочного файла.


Чтобы сохранить заголовочный файл, перейдите в Документы Arduino libraries. Создайте новую папку с тем же именем, что и у класса (в данном примере MyLED). Сохраните заголовочный файл в этой папке. Заголовочный файл необходимо сохранить с расширением .h. В этом примере файл заголовка будет называться MyLED.h.

Где сохранять свои классы в ардуино
Папка для хранения файлов класса

Исходный файл

Исходный файл содержит фактический код функций и определяет, что произойдет при создании объекта. Он должен иметь то же имя, что и файл заголовка, но с расширением “.cpp”.

Давайте пройдемся по процессу написания исходного файла.

Шаг 1. Подключение вспомогательных файлов

Первое, что нужно сделать, это включить библиотеку Arduino.h, чтобы мы могли использовать встроенные в Arduino функции, такие как pinMode(), digitalWrite() и delay():

#include "Arduino.h”

Затем нам нужно включить заголовочный файл, который мы только что написали. Мы делаем это так же, как и все классы, с помощью директивы #include, за которым следует имя заголовочного файла в кавычках:

#include "Arduino.h”
#include "MyLED.h"

Шаг 2. Конструктор класса

Теперь мы можем написать определение конструктора. Этот код будет выполняться каждый раз при создании объекта в скетче. Определение конструктора начинается с имени класса, за которым следуют два двоеточия.

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

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED() {
}

Объекты, которые мы создадим с помощью этого класса, будут представлять контакты Arduino, подключенные к зеленому и синему светодиодам. Каждый раз, когда создается объект, pinMode() каждого вывода необходимо будет установить в качестве выхода. Для этого нам нужно передать конструктору номер контакта Arduino, подключенного к светодиоду, объявив переменную с именем pin внутри конструктора MyLED():

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED(int pin) {
}

Внутри конструктора все, что нам нужно сделать, это установить режимы контактов светодиодов. Номер вывода, хранящийся в переменной pin, будет передан конструктору при создании объекта:

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED(int pin) {
    pinMode(pin, OUTPUT);
}

Помните приватную переменную _pin, которую мы объявили в заголовочном файле?

Теперь мы устанавливаем его равным общедоступной переменной pin, которую мы объявили внутри конструктора MyLED(). Через минуту мы поймем, почему мы хотим это сделать:

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED(int pin) {
    pinMode(pin, OUTPUT);
    _pin = pin;
}

Шаг 3. Создание функции класса

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

Затем напишите имя класса, к которому принадлежит функция. В этом примере функция будет принадлежать классу MyLED. Затем включите оператор разрешения области ::, за которым следует имя функции. Мы уже объявили функцию myBlink() в заголовочном файле, так что мы можем использовать ее:

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED(int pin) {
    pinMode(pin, OUTPUT);
    _pin = pin;
}

void MyLED::myBlink() {
}

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

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED(int pin) {
    pinMode(pin, OUTPUT);
    _pin = pin;
}

void MyLED::myBlink(int rate) {
}

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

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

#include "Arduino.h”
#include "MyLED.h"
MyLED::MyLED(int pin) {
    pinMode(pin, OUTPUT);
    _pin = pin;
}

void MyLED::myBlink(int rate) {
    digitalWrite(_pin, HIGH);
    delay(rate);
    digitalWrite(_pin, LOW);
    delay(rate);
}

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

Таким образом, когда объект LED будет создан, номер вывода будет сохранен в общедоступной переменной вывода и передан конструктору. Этот номер вывода также будет храниться в закрытой переменной _pin и передаваться функции digitalWrite().

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

Это все, что нам нужно для исходного файла.


Чтобы сохранить исходный файл, перейдите в Документы Arduino libraries. Сохраните исходный файл в папке, созданной для MyLED. Исходный файл должен иметь то же имя, что и файл заголовка, но с расширением .cpp. В этом примере файл заголовка будет называться MyLED.cpp.

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

Теперь напишем скетч.

Скетч

В программировании Arduino классы обрабатываются точно так же, как библиотеки. Поэтому мы можем включить класс MyLED в скетч так же, как включаются библиотеки:

#include <MyLED.h>

Чтобы использовать функции, которые были определены в классе, нам потребуется создать объекты. Мы мигаем двумя светодиодами, поэтому у нас будет один объект для синего светодиода и один объект для зеленого светодиода.

Чтобы создать объект, напишите название класса, затем имя объекта. Объекты можно называть как угодно. В этом примере мы создаем объект blue для синего светодиода и объект green для зеленого светодиода. Каждый объект вызывается через класс MyLED:

#include <MyLED.h>
MyLED blue(9);
MyLED green(10);

Когда мы определили конструктор MyLED в исходном файле, мы передали ему общедоступную переменную pin. Итак, теперь мы можем использовать номер вывода Arduino в качестве аргумента объекта, и этот номер вывода будет передан конструктору. В этом примере конструктор установит режим контактов 9 и 10 в качестве выходов.

Теперь мы можем написать раздел loop().

Мы будем мигать синим и зеленым светодиодами с помощью функции myBlink(), которая была определена в исходном файле. Чтобы использовать функции из класса или библиотеки, напишите имя объекта, точку, затем имя функции, которую вы хотите вызвать:

#include <MyLED.h>
MyLED blue(9);
MyLED green(10);

void setup(){
}

void loop(){
    blue.myBlink(3000);
}

Это вызовет функцию myBlink() из класса MyLED и применит ее к синему светодиоду.

Когда мы определили функцию myBlink(), мы передали ей переменную rate, чтобы контролировать, как быстро будут мигать светодиоды. С 3000 в качестве аргумента функция delay() внутри функции myBlink() задержится на 3000 миллисекунд.

Теперь нам осталось вызвать функцию myBlink() для объекта green. Зеленый светодиод будет мигать в течение 1500 миллисекунд.

#include <MyLED.h>
MyLED blue(9);
MyLED green(10);

void setup(){
}

void loop(){
    blue.myBlink(3000);
    green.myBlink(1500);
}

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

После того, как вы загрузите скетч, вы должны увидеть, как синий светодиод загорается и гаснет каждые три секунды, а зеленый светодиод загорается и гаснет каждые полторы секунды.

Результат выполнения кода класса ардуино
Что получилось в результате написания класса

Надеюсь, что эта статья облегчит вам использование классов и объектов на Arduino. Если у вас есть какие-либо вопросы, обязательно оставьте их ниже.

Документация

Компоненты

  • Arduino NANO
  • Arduino UNO
  • Arduino MEGA
  • Набор выводных резисторов
  • Наборы выводных светодиодов
3.7 3 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии