Файл: Методические указания к выполнению лабораторных работ по дисциплине Основы электротехники в робототехнике.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 08.11.2023
Просмотров: 176
Скачиваний: 5
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
1 Перечень необходимых средств для выполнения лабораторных работ
2.1 Как подключить светодиод к Arduino
2.3 Меняем цвет по нажатию кнопки
2.5 Классы в программах Ардуино. Кнопка как объект.
3.1 Подключение семисегментного индикатора
3.2 Подключение LED индикатора с TM1637
3.3 Подключение LCD 1602 (HD44780) к Arduino
3.4 Подключение LCD1602 по I2C к Ардуино
4.1 Подключение матричной клавиатуры к Arduino
4.2 Подключение клавиатуры 4*4 и пьезоизлучателя к Arduino
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) { //кнопка нажата
tone(BUZZER_PIN, 1000); //частота 1000 Гц на пищалку
delay (300); //задержка 0,3 сек
noTone(BUZZER_PIN);//прекращаем генерацию;
delay (300); //задержка 0,3 сек
else { //кнопка отпущена
noTone(BUZZER_PIN);//прекращаем генерацию;
}
}
2.5 Классы в программах Ардуино. Кнопка как объект.
( http://mypractic.ru/urok-7-klassy-v-programmax-arduino-knopka-kak-obekt.html )
На предыдущем этапе написали рабочий, отлаженный программный блок, который можно вполне использовать в последующих программах. Но как-то не совсем красиво получилось.
-
Программный блок для обработки сигнала размещается вместе с другими блоками и ухудшает читаемость программы. -
Надо определить для него переменные, ничего не забыть. -
А если нам необходимо подключить несколько кнопок. Для каждой из них надо завести свои переменные, свои программные блоки, свои функции. И ничего не перепутать. -
При каждом использовании программного блока обработки сигнала кнопки придется вспоминать, как он работает, какие переменные требует и, самое главное, менять имена переменных в тексте блока.
И это притом, что мы используем один и тот же простой объект – кнопку. Для красивого решения этих проблем в языке программирования Ардуино существуют классы.
Классы в C++ для Ардуино.
Классы позволяют программисту создавать новые типы объектов. Они состоят из свойств и методов. Свойства – это данные, которыми можно характеризовать объект класса. Методы – это функции, которые могут выполнять действия над свойствами класса.
-
Свойства класса это его переменные. -
Методы класса это его функции.
Определение класса выглядит так:
class имя_класса { члены класса };
Члены класса это переменные, функции, другие классы и т.п.
Создание класса для обработки сигналов кнопок Button.
Создадим класс для нашего объекта кнопки. Назовем его Button.
Нам необходимы такие же переменные, как и в предыдущем уроке, только они становятся свойствами класса. Напомню, что тогда мы создали следующие переменные:
boolean flagPress= false; // признак кнопка сейчас нажата
boolean flagClick= false; // признак кнопка была нажата (клик)
byte buttonCount= 0; // счетчик подтверждений стабильного состояния
#define TIME_BUTTON 15 // время стабильного состояния (* 2 мс)
К этим переменным необходимо добавить номер вывода, к которому подключена кнопка, и константу TIME_BUTTON надо объявить переменной, чтобы для каждой кнопки можно было задавать свое время подтверждения.
Оформим перечисленные переменные как свойства класса.
// Описание класса обработки сигналов кнопок
class Button {
boolean flagPress; // признак кнопка сейчас нажата
boolean flagClick; // признак кнопка была нажата (клик)
byte buttonCount; // счетчик подтверждений стабильного состояния
byte timeButton; // время подтверждения состояния кнопки
byte _pin; // номер вывода
};
Button – это имя класса, а в скобках указаны его свойства (переменные).
Модификаторы доступа private и public.
Все свойства и методы класса имеют права доступа. Например, счетчик buttonCount используется только самим классом для собственных вычислений. Никогда к нему не будут обращаться другие программные модули. Логично запретить доступ к нему всех функций, кроме методов своего класса Button.
Для этого в языке C++ существуют модификаторы private и public.
-
Функции и переменные, которые находятся после модификатора public, доступны из любого места программы. -
После модификатора private размещаются закрытые функции и переменные. С ними могут работать только методы собственного класса. Если отсутствует модификатор public, то все члены класса считаются закрытыми.
Нам надо выбрать, какие переменные (свойства) сделать открытыми, а какие – закрытыми. Хороший стиль объектно-ориентированного программирования предполагает, что все переменные должны быть закрытыми. А обращение к ним происходит через методы (функции) класса. Но надо сделать поправку на то, что мы пишем программу для микроконтроллера с ограниченной производительностью. А вызов любой функции занимает определенное время. Поэтому, свойства, к которым программа обращается часто, следует сделать открытыми и обращаться к ним явно. Это уменьшит время выполнения программы.
В нашем случае это признаки flagPress и flagClick. К ним постоянно обращается программа для контроля состояния кнопок. А номер вывода _pin и время подтверждения timeButtonобычно устанавливаются только один раз. Сделаем эти переменные закрытыми. Устанавливать их будем из дополнительного метода.
С учетом вышесказанного наш класс будет выглядеть так.
// Описание класса обработки сигналов кнопок
class Button {
public:
boolean flagPress; // признак кнопка сейчас нажата
boolean flagClick; // признак кнопка была нажата (клик)
private:
byte _buttonCount; // счетчик подтверждений стабильного состояния
byte _timeButton; // время подтверждения состояния кнопки
byte _pin; // номер вывода
};
Переменные timeButton и pin нам придется заявлять как аргументы метода для установки значений. Поэтому мы добавили _ перед именами, чтобы отличать аргументы метода и переменные класса.
Созданный нами класс пока состоит только из свойств. Надо добавить в него методы – функции.
Нам необходим метод для проверки состояния сигнала кнопки, тот самый, что мы вызывали в цикле каждые 2 мс. Назовем его scanState (проверка состояния).
Принято названия классов писать в смешанном регистре, начиная с большой буквы, а названия методов - в смешанном регистре, начиная с маленькой буквы, первая часть – глагол.
Т.к. переменные номер вывода и время подтверждения мы сделали закрытыми, то необходима функция установки их значений. Например, setPinTime.
Т.е. для класса Button необходимы два метода. С методами наш класс будет выглядеть так.
// Описание класса обработки сигналов кнопок
class Button {
public:
boolean flagPress; // признак кнопка сейчас нажата
boolean flagClick; // признак кнопка была нажата (клик)
void scanState(); // метод проверки состояние сигнала
void setPinTime(byte pin, byte timeButton); // метод установки номера вывода и времени подтверждения
private:
byte _buttonCount; // счетчик подтверждений стабильного состояния
byte _timeButton; // время подтверждения состояния кнопки
byte _pin; // номер вывода
};
Метод void scanState() не имеет аргументов и ничего не возвращает. Метод void setPinTime(byte pin, byte timeButton) ничего не возвращает и имеет два аргумента: номер вывода и время подтверждения стабильного состояния кнопки.
Таким образом, мы объявили класс. Остается написать коды методов. Т.к. методы это функции, то и коды для них оформляются как функции. Можно написать коды прямо внутри класса, но это приведет к плохой читаемости текста программы. Представьте, что в начале программы, где описываются переменные, классы, будут громадные блоки кодов. Поэтому лучше коды методов написать в конце программы. Отличие кодов методов классов от пользовательских функций заключается только в том, что в первом случае надо указать принадлежность метода к конкретному классу.
void Button:: scanState() {
// код метода
}
Button:: означает, что функция scanState() это метод класса Button.
Напишем код метода scanState().
// метод проверки состояния кнопки
// flagPress= true - нажата
// flagPress= false - отжата
// flagClick= true - была нажата (клик)
void Button::scanState() {
if ( flagPress == (! digitalRead(_pin)) ) {
// состояние сигнала осталось прежним
_buttonCount= 0; // сброс счетчика состояния сигнала
}
else {
// состояние сигнала изменилось
_buttonCount++; // +1 к счетчику состояния сигнала
if ( _buttonCount >= _timeButton ) {
// состояние сигнала не менялось заданное время
// состояние сигнала стало устойчивым
flagPress= ! flagPress; // инверсия признака состояния
_buttonCount= 0; // сброс счетчика состояния сигнала
if ( flagPress == true ) flagClick= true; // признак клика на нажатие
}
}
}
Он повторяет код из предыдущего урока, только в качестве переменных используются свойства класса.
Теперь код для метода setPinTime(byte pin, byte timeButton). Он совсем простой. Перегружает аргументы метода в закрытые свойства класса и устанавливает режим вывода.
// метод установки номера вывода и времени подтверждения
void Button::setPinTime(byte pin, byte timeButton) {
_pin= pin;
_timeButton= timeButton;
pinMode(_pin, INPUT_PULLUP); // определяем вывод как вход
}
Мы завершили создание класса Button. Осталось научиться пользоваться им.
Класс это только описание типа объекта, самого объекта еще нет. Его надо создать. Делается это так же, как и создание переменных при использовании встроенных типов данных.
int x; // мы создали переменную типа int с именем x
Button button1; // мы создали объект типа Button с именем button1
Button buttonPlus; // мы создали еще один объект типа Button с именем buttonPlus
Вы поняли, что теперь добавление новой кнопки в систему можно сделать одной строкой.
Для обращения к членам класса из любого места программы необходимо использовать имя объекта, точку и имя свойства или метода.
button1.flagClick= false; // переменная flagClick j, объекта button1 = false
button1.scanState(); // вызов метода scanState(), объекта button1
button1.setPinTime(12, 20); // вызов метода setPinTime (), объекта button1 с параметрами 12, 20
Проверка состояния кнопки button1 из любого места программы будет выглядеть так:
if ( button1.flagPress == true ) {
// кнопка нажата }
Думаю, теперь в программе объяснять ничего не надо. Тем более, что комментариев в ней больше, чем кода.
/*
Программа sketch_7_1 урока 7
* Каждое нажатие кнопки меняет состояние светодиода */
#define LED_PIN 13 // светодиод подключен к выводу 13
#define BUTTON_PIN 12 // кнопка подключена к выводу 12
// Описание класса обработки сигналов кнопок
class Button {
public:
boolean flagPress; // признак кнопка сейчас нажата
boolean flagClick; // признак кнопка была нажата (клик)
void scanState(); // метод проверки состояние сигнала
void setPinTime(byte pin, byte timeButton); // метод установки номера вывода и времени (числа) подтверждения
private:
byte _buttonCount; // счетчик подтверждений стабильного состояния
byte _timeButton; // время подтверждения состояния кнопки
byte _pin; // номер вывода
};
boolean ledState; // переменная состояния светодиода
Button button1; // создание объекта типа Button с именем button1
void setup() {
pinMode(LED_PIN, OUTPUT); // определяем вывод 13 (светодиод) как выход
button1.setPinTime(BUTTON_PIN, 15); // вызов метода установки объекта button1 с параметрами: номер вывода 12, число подтверждений 15
}
// бесконечный цикл с периодом 2 мс
void loop() {
button1.scanState(); // вызов метода сканирования сигнала кнопки
// блок управления светодиодом
if ( button1.flagClick == true ) {
// было нажатие кнопки
button1.flagClick= false; // сброс признака клика
ledState= ! ledState; // инверсия состояния светодиода
digitalWrite(LED_PIN, ledState); // вывод состояния светодиода
}