Опубликовано: 12.11.2016 20:35
Автор: jazon
Модуль энкодер KY-040 является механическим датчиком угла поворота, он преобразует угол поворота вращающегося объекта(например вала) в электрические сигналы сдвинутые на 90 градусов относительно друг друга. Данный модуль имеет три вывода - CLK, DT и SW. Сигналы, сдвинутые на 90 градусов относительно друг друга появляются именно на выводах CLK и DT при вращении по/против часовой стрелки, вывод SW используется для получения состояния центральной оси энкодера, которая работает как кнопка.
Итак, не вдаваясь в подробности внутрисхемного устройства энкодера(об этом будет отдельная статья), произведем его подключение к плате Arduino Uno. Схема подключения модуля энкодера в связке с многоразрядным семисегментным индикатором:
Нам достаточно будет просто разобрать состояние сигналов которые дают вывода CLK и DT, для этого есть небольшая схемная диаграмма, которая покажет как сдвинуты сигналы при вращении в ту или иную стороны.
Из диаграммы видно что, каждый раз когда сигнал А(контакт CLK энкодера) переходит от высокого уровня к низкому, считывается состояние сигнала Б(контакт DT энкодера). Если сигнал Б даёт высокий уровень сигнала, это означает что вращение энкодера происходит по часовой стрелке. Если сигнал Б даёт низкий уровень сигнала при переходе сигнала А из низкого в высокий уровень, то это означает что вращение энкодера происходит против часовой стрелки. Считывая оба этих сигнала в программе, можно определить направление вращения, также при подсчете импульсов сигнала Б, можно инкрементировать либо декрементировать программный счетчик импульсов.
Чтобы считывать сигналы А и Б, а также сигналы центральной оси энкодера(напомню - она работает как кнопка), можно применить нижеописанную конструкцию. Эту конструкцию можно встраивать в скетч, добавляя в неё различный функционал, всё ограничивается только желанием и фантазией разработчика. Тело конструкции достаточно хорошо прокомментировано, в дальнейшем для простоты текста скетча можно убрать комментарии. Итак, конструкция для считывания и преобразования сигналов энкодера в полезные данные:
//Временные переменные для хранения уровней сигналов
//полученных от энкодера
unsigned char encoder_A, encoder_B, encoder_A_prev;
//Переменная для отслеживания нажатий кнопки -
//центральной оси энкодера
static bool SW_State = false;
void setup()
{
//Предварительные установки
//Объявления переменных
//Инициализации портов и т.д.
}
void loop()
{
//CLK подключаем к пину 3 на плате Arduino
//DT подключаем к пину 4 на плате Arduino
//Считываем значения выходов энкодера
//И сохраняем их в переменных
encoder_A = digitalRead(3);
encoder_B = digitalRead(4);
//Если уровень сигнала А низкий,
//и в предидущем цикле он был высокий
if(!encoder_A && encoder_A_prev)
{
//Если уровень сигнала В высокий
if(encoder_B)
{
//Значит вращение происходит по часовой стрелке
//Здесь можно вставить операцию инкремента
//Здесь можно вставлять какие либо свои
//операции по обработке данных в нужном направлении
}
//Если уровень сигнала В низкий
else
{
//Значит вращение происходит против часовой стрелки
//Здесь можно вставить операцию декремента
//Здесь можно вставлять какие либо свои
//операции по обработке данных в нужном направлении
}
}
//Обязательно нужно сохранить состояние текущего уровня сигнала А
//для использования этого значения в следующем цикле сканирования программы
encoder_A_prev = encoder_A;
//Работаем с центральной осью энкодера - кнопкой
//Этот кусок кода образует собой как бы перекидной триггер
//Считываем значение пина 2 на плате Arduino
//к которому подключен контакт SW энкодера
//Если центральная ось нажата - то сигнал SW будет иметь низкий уровень
if(!digitalRead(2))
{
//Если переменная SW_State установлена в false то установить её в true
if(!SW_State)
{
//И запомнить состояние
SW_State = true;
}
//И наоборот - если переменная SW_State установлена в true,
//то сбросить её в false
else
{
//И запомнить состояние
SW_State = false;
}
}
}
Скетч, для обработки сигналов энкодера и выводу значения счетчика на дисплей, показан ниже. В этот скетч встроена конструкция для считывания и преобразования сигналов энкодера, которая была описана выше.
#include "LedControl.h"
/*
* Подключаем библиотеку LedControl.h
* и создаём объект класса LedControl
* при этом, 7-ми сегметный дисплей с драйвером MAX72xx
* должен быть подключен к плате Arduino следующим образом:
* Arduino[Pin 5V] -> Display Module MAX72xx[VCC]
* Arduino[PinGND] -> Display Module MAX72xx[GND]
* Arduino[Pin 12] -> Display Module MAX72xx[DIN]
* Arduino[Pin 11] -> Display Module MAX72xx[CLK]
* Arduino[Pin 10] -> Display Module MAX72xx[LOAD/CS]
* Arduino[Pin 4] -> Encoder Module [CLK]
* Arduino[Pin 3] -> Encoder Module [DT]
* Arduino[Pin 2] -> Encoder Module [SW]
*/
LedControl lc = LedControl(12, 11, 10, 1);
//Проименовываем адреса портов на плате Arduino
const int Dir = 4;
const int Step = 3;
const int Switch = 2;
//Counter - переменная для хранения значения счетчика
static long Counter = 0;
//SW_State - флаг триггер отслеживания нажатия центральной оси
static bool SW_State = false;
//Временные переменные для хранения уровней сигналов энкодера
unsigned char encoder_A, encoder_B, encoder_A_prev;
void setup()
{
//Устройство(7-ми сегментный дисплей) выводим из спящего режима
lc.shutdown(0, false);
//Установить яркость дисплея на 8
//Всего возможных режимов яркости от 0 до 15
lc.setIntensity(0,8);
//Очистить дисплей
lc.clearDisplay(0);
//Конфигурируем порты для энкодера
pinMode(Dir, INPUT);
pinMode(Step, INPUT);
pinMode(Switch, INPUT);
}
void loop()
{
//Считываем значения выходов энкодера
//И сохраняем их в переменных
encoder_A = digitalRead(Step);
encoder_B = digitalRead(Dir);
//Если уровень сигнала А низкий,
//и в предидущем цикле он был высокий
if(!encoder_A && encoder_A_prev)
{
//Если уровень сигнала В высокий
if(encoder_B)
{
//Значит вращение происходит по часовой стрелке
//Наше условие:
//Если значение счетчика больше или равно максимальному числу
if(Counter >= 99999999)
{
//Обнулить значение счетчика
Counter = 0;
}
else
{
//Иначе инкрементировать при каждом щелчке на единицу
Counter ++;
}
}
//Если уровень сигнала В низкий
else
{
//Значит вращение происходит против часовой стрелки
//Если значение счетчика меньше или равно нулю
if(Counter <= 0)
{
//проинициализировать значение максимальным числом
Counter = 99999999;
}
else
{
//Иначе декрементировать при каждом щелчке на единицу
Counter --;
}
}
}
//Обязательно нужно сохранить состояние текущего уровня сигнала А
//для использования этого значения в следующем цикле сканирования программы
encoder_A_prev = encoder_A;
//Работаем с центральной осью энкодера - кнопкой
//Этот кусок кода образует собой как бы перекидной триггер
//Считываем значение пина 2 на плате Arduino
//которомый проименован как Switch
//Если центральная ось нажата - то сигнал Switch будет иметь низкий уровень
if(!digitalRead(Switch))
{
//Если переменная SW_State установлена в false то установить её в true
if(!SW_State)
{
//И запомнить состояние
SW_State = true;
}
//И наоборот - если переменная SW_State установлена в true,
//то сбросить её в false
else
{
//И запомнить состояние
SW_State = false;
}
}
//Часть программы которая заполняет разряды
//семисегментного дисплея значением счетчика
long intCounter = Counter;
int divCounter;
for(int i = 0; i < 8; i ++)
{
divCounter = intCounter % 10;
intCounter = intCounter / 10;
if(intCounter == 0 && SW_State)
{
if(divCounter == 0)
{
if(i == 0)
{
lc.setChar(0, 0, '0', false);
}
else
{
lc.setChar(0, i, ' ', false);
}
}
else
{
lc.setDigit(0, i, divCounter, false);
}
}
else
{
lc.setDigit(0, i, divCounter, false);
}
}
}
Видео, как это работает:
Дополню наш материал, если вам интересно как работать с многоразрядными семисегментными индикаторами на базе микросхемы MAX7219, то добро пожаловать в статью по ссылке: Модуль многоразрядного 7-ми сегментного индикатора на базе микросхемы MAX72xx, подключение к Arduino и работа с библиотечными функциями.
Надеемся, что вам понравился материал этой статьи, свои вопросы, пожелания и критику оставляйте в комментариях ниже.
Если у Вас есть опыт в работе с Arduino и собственно есть время для творчества, мы приглашаем всех желающих стать авторами статей публикуемых на нашем портале. Это могут быть как уроки, так и рассказы о ваших экспериментах с Arduino. Описание различных датчиков и модулей. Советы и наставления начинающим. Пишите и размещайте свои статьи в соответсвующей ветке форума.