Інкрементальний екодер ЕС11 ( або інкрементний, від англ. Increment - « збільшення») енкодер ( датчик кута повороту) - це пристрій, який перетворює обертальний рух вала в серію електричних імпульсів, що дозволяють визначити напрямок і кут його обертання. Також, виходячи з знайдених величин, можна визначити і швидкість обертання. Основною відмінністю інкрементальних енкодерів від абсолютних є те, що вони можуть повідомляти лише про величину зміни їхнього кутового положення, а не про абсолютний свій стан. Найпопулярнішим прикладом використання інкрементального енкодера в повсякденному житті, є ручка регулювання гучності автомобільної магнітоли.
Також енкодери ідеально підходять для реалізації навігації по різним меню.
Інкрементальні енкодери бувають оптичними, магнітними, механічними і т.д. Незалежно від принципу пристрою все інкрементальні енкодери на виході генерують 2 лінії ( A і B) з імпульсами зміщеними відносно один одного. Саме зі звільнення імпульсів можна судити про направлення обертання. А за кількістю імпульсів - про кути повороту. Енкодер з кнопкою має 5 виходів - 2 виходи ( D і E ) відповідають за перемикач ( кнопку), 1 ( С ) - загальний ( GND , земля), а що залишилися 2 ( A і B ) - імпульсні лінії, які сигналізують про обертання.
Кожен інкрементальний енкодер має наступну основну характеристику - дискретність ( кількість кроків, положень між імпульсами, на один оборот валу). Завдяки дискретності, можна обчислити кут одиничного зміни положення. У нашому прикладі, енкодер ЄС11 за повний оборот генерує 20 серій імпульсів. А це означає, що кожен крок еквівалентний повороту на 18 °. Крім цього, вал енкодера фіксується в кожному положенні між кожною серією імпульсів. Визначення стану пінів енкодера в циклі loop () і подальше обчислення напрямку обертання є неприпустимо витратним по відношенню до ресурсів Arduino, методом. Саме тому буде використаний метод боротьби з іскрінням контактів (брязкіт, дрєбєзг), за допомогою переривань. В Ардуіно УНО їх є 2. На відміну від програмного усунення брязкоту звичайної кнопки брязкіт енкодера можна усунути програмно, при цьому серйозно не навантажуючи ресурси мікроконтролера. І програмне усунення працюватиме на переривання і прапорцях.
Сигнальні лінії енкодера підключені до 2 і 3 піну Arduino Uno, так як на цих виходах реалізовані переривання. Заміна пинов підключення призведе до непрацездатності прикладу. скетч:
Суть роботи коду можна зобразити графічно:// використання двох переривань для обліку напрямку і кута обертання
// Объявляем переменные
int pinA = 2; // Пины прерываний
int pinB = 3; // Пины прерываний
volatile long pause = 50; // Пауза для борьбы с дребезгом
volatile long lastTurn = 0; // Переменная для хранения времени последнего изменения
volatile int count = 0; // Счетчик оборотов
int actualcount = 0; // Временная переменная определяющая изменение основного счетчика
volatile int state = 0; // Статус одного шага - от 0 до 4 в одну сторону, от 0 до -4 - в другую
volatile int pinAValue = 0; // Переменные хранящие состояние пина, для экономии времени
volatile int pinBValue = 0; // Переменные хранящие состояние пина, для экономии времени
void setup()
{
pinMode(pinA, INPUT); // Пины в режим приема INPUT
pinMode(pinB, INPUT); // Пины в режим приема INPUT
attachInterrupt(0, A, CHANGE); // Настраиваем обработчик прерываний по изменению сигнала
attachInterrupt(1, B, CHANGE); // Настраиваем обработчик прерываний по изменению сигнала
Serial.begin(9600); // Включаем Serial
}
void loop()
{
if (actualcount != count) { // Чтобы не загружать ненужным выводом в Serial, выводим состояние
actualcount = count; // счетчика только в момент изменения
Serial.println(actualcount);
}
}
void A()
{
if (micros() - lastTurn < pause) return; // Если с момента последнего изменения состояния не прошло
// достаточно времени - выходим из прерывания
pinAValue = digitalRead(pinA); // Получаем состояние пинов A и B
pinBValue = digitalRead(pinB);
cli(); // Запрещаем обработку прерываний, чтобы не отвлекаться
if (state == 0 && !pinAValue && pinBValue || state == 2 && pinAValue && !pinBValue) {
state += 1; // Если выполняется условие, наращиваем переменную state
lastTurn = micros();
}
if (state == -1 && !pinAValue && !pinBValue || state == -3 && pinAValue && pinBValue) {
state -= 1; // Если выполняется условие, наращиваем в минус переменную state
lastTurn = micros();
}
setCount(state); // Проверяем не было ли полного шага из 4 изменений сигналов (2 импульсов)
sei(); // Разрешаем обработку прерываний
if (pinAValue && pinBValue && state != 0) state = 0; // Если что-то пошло не так, возвращаем статус в исходное состояние
}
void B()
{
if (micros() - lastTurn < pause) return;
pinAValue = digitalRead(pinA);
pinBValue = digitalRead(pinB);
cli();
if (state == 1 && !pinAValue && !pinBValue || state == 3 && pinAValue && pinBValue) {
state += 1; // Если выполняется условие, наращиваем переменную state
lastTurn = micros();
}
if (state == 0 && pinAValue && !pinBValue || state == -2 && !pinAValue && pinBValue) {
state -= 1; // Если выполняется условие, наращиваем в минус переменную state
lastTurn = micros();
}
setCount(state); // Проверяем не было ли полного шага из 4 изменений сигналов (2 импульсов)
sei();
if (pinAValue && pinBValue && state != 0) state = 0; // Если что-то пошло не так, возвращаем статус в исходное состояние
}
void setCount(int state) { // Устанавливаем значение счетчика
if (state == 4 || state == -4) { // Если переменная state приняла заданное значение приращения
count += (int)(state / 4); // Увеличиваем/уменьшаем счетчик
lastTurn = micros(); // Запоминаем последнее изменение
}
}