Підрахунок імпульсів на інкрементальному енкодері EC11

Теми по керування сервоприводами, управління обертами двигунів, драйвери моторів, перетворювачі струму для моторів, управління кроковими двигунами, шілди для підключення моторів квадрокоптнрів та літаків
Відповісти
Аватар користувача
Arduino
Site Admin
Повідомлень: 98
З нами з: 16 травня 2017 18:18

Підрахунок імпульсів на інкрементальному енкодері EC11

Повідомлення Arduino » 21 серпня 2018 13:56

Інкрементальний екодер ЕС11 дозволяє створювати меню, контролювати напрямок обертання валу, рахувати імпульси при повороті колес тахометрів.
Інкрементальний екодер ЕС11 ( або інкрементний, від англ. Increment - « збільшення») енкодер ( датчик кута повороту) - це пристрій, який перетворює обертальний рух вала в серію електричних імпульсів, що дозволяють визначити напрямок і кут його обертання. Також, виходячи з знайдених величин, можна визначити і швидкість обертання. Основною відмінністю інкрементальних енкодерів від абсолютних є те, що вони можуть повідомляти лише про величину зміни їхнього кутового положення, а не про абсолютний свій стан. Найпопулярнішим прикладом використання інкрементального енкодера в повсякденному житті, є ручка регулювання гучності автомобільної магнітоли.
Також енкодери ідеально підходять для реалізації навігації по різним меню.
Інкрементальні енкодери бувають оптичними, магнітними, механічними і т.д. Незалежно від принципу пристрою все інкрементальні енкодери на виході генерують 2 лінії ( A і B) з імпульсами зміщеними відносно один одного. Саме зі звільнення імпульсів можна судити про направлення обертання. А за кількістю імпульсів - про кути повороту.
EC11-001.jpg
Енкодер з кнопкою має 5 виходів - 2 виходи ( D і E ) відповідають за перемикач ( кнопку), 1 ( С ) - загальний ( GND , земля), а що залишилися 2 ( A і B ) - імпульсні лінії, які сигналізують про обертання.
Кожен інкрементальний енкодер має наступну основну характеристику - дискретність ( кількість кроків, положень між імпульсами, на один оборот валу). Завдяки дискретності, можна обчислити кут одиничного зміни положення. У нашому прикладі, енкодер ЄС11 за повний оборот генерує 20 серій імпульсів. А це означає, що кожен крок еквівалентний повороту на 18 °. Крім цього, вал енкодера фіксується в кожному положенні між кожною серією імпульсів.
EC11-002.jpg
Визначення стану пінів енкодера в циклі loop () і подальше обчислення напрямку обертання є неприпустимо витратним по відношенню до ресурсів Arduino, методом. Саме тому буде використаний метод боротьби з іскрінням контактів (брязкіт, дрєбєзг), за допомогою переривань. В Ардуіно УНО їх є 2.
EC11-003.jpg
На відміну від програмного усунення брязкоту звичайної кнопки брязкіт енкодера можна усунути програмно, при цьому серйозно не навантажуючи ресурси мікроконтролера. І програмне усунення працюватиме на переривання і прапорцях.
Сигнальні лінії енкодера підключені до 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(); // Запоминаем последнее изменение
}
}
Суть роботи коду можна зобразити графічно:
EC11-004.jpg

Відповісти

Повернутись до “Керування двигунами”