Управление энкодером на 400 шагов
Дата: 22 Июля 2015. Автор: Алексей
Привет всем! Помниться я уже разок писал про инкрементальный энкодер. Но суть данной статьи сводится к подключению энкодера на 400 шагов. Собственно, а какая разница. А разница вот в чем. Если взять программу которую я описывал в прошлой статье про энкодер, то она с этим работать не будет. Вся затыка уперлась в скорости опрашивания данных с энкодера. Представьте, 400 импульсов за оборот. Если крутануть со всей дури, то можно разогнать до 180 оборотов в минуту. Если посчитать 180/60 то получим 3 оборота в секунду. А теперь 3*400 то получим 1200 импульсов. А мы хотим еще вывести на ЖК, а у ЖК обязательно есть 2 мс задержки. Короче пропусков дофига. А че делать? А есть у нас в МК внешнее прерывание INT0. Данное прерывание стоит первым после сброса. А это значит что все другие прерывания имеют нисший приоритет. То есть сделаем просто, повесим вход энкодера на прерывание и по нему определим что он сдвинулся, а в обработчике узнаем куда. Для теста я решил ограничить шаги от 0 до 400 и выводить их на ЖК дисплей 16х2. Теперь немного о железе.
Друзья из Китая довольно таки не корректно перевели цветовую палитру проводов, что это чуть ли не привело к похоронам энкодера. Но всемогущий гугл оказался круче Китайцев. Были проведены сравнения закорючек на энкодере с гугл переводчиком что дало новые данные по подключению.
Когда все встало на свои места, была собрана следующая схема.
Посмотреть по крупнее.
Что собственно мы видим на схеме. МК Mega8A подключени по классической схеме, здесь я ничего не мудрил. ЖК дисплей подключен к порту D за небольшим моментом. Стробирование ЖК дисплея отдано третьему разряду порта С. Это сделано из-за того, что на порту D пин PD2 является входом внешнего прерывания INT0. Можно было конечно перейти на PD1, но у меня отладочная плата уже разведена и не позволяет что-то менять, ЖК прикручен намертво. Резистор R1 нужен для регулировки контрастности, так что подбирайте для своего дисплея сами по месту. Частота кварца тоже принята из расчета припаянного на глухо. На работу программы не влияет. А вот теперь про энкодер. Красный провод вешаем на 5 вольт. Да кстати я его разобрал и нашел внутри линейный стабилизатор 78M05. При подаче на него 5 вольт, на выходе 3,5 вольта. Я так и не понял почему диапазон питания разрешен от 5 вольт до 24. Я бы начал он 9 до 24. Но это не важно. 3,5 вольт оказалось достаточно для принятия МК импульсов. Черный провод и экран вешаем на общий провод. Белый оказался каналом В, но я его все таки оставил на ножке РС0. Мне было проще в программе поменять значения чем перетыкать провода. Зеленый, канал А вешаем на РС1. Как и для любого энкодера оба канала подтягиваем резисторами на 10К к плюсу. А вот дальше самое интересное. Для того чтобы внешнее прерывание могло контролировать оба канала одновременно, необходимо от каждого канала пробросить на ножку прерывание быстродействующий диод. Катодом к каналу, а анодом к INT0. Это даст нам возможность не мешая друг другу получить изменения на каналах. Логика проста, если на обоих каналах присутствует единица, то диоды не дадут выйти ей на наружу. Но как только на одном из каналов появится ноль, то его перехватит прерывание, а из-за диодов этот ноль не перескочит на другой канал. Правда есть косяк. Когда на каналах две единицы, то INT0 получается висит в воздухе и может наловит помех из вне. Чтобы этого не случилось подтягиваем его к плюсу резистором на 10К. Он на схеме обозначен как R4. Теперь переходим к программированию.
Перед обработчиком прерывания пишем.
#define F_CPU 7372800UL // Частота кварца #include <vr/io.h> #include <stdio.h> #include <axlib/main_init.h> #include <axlib/lcd.h> #include <axlib/timers.h> BYTE str[20]; // Буфер для вывода на ЖК volatile BYTE input = 0; // Текущеее значения энкодера volatile BYTE buf = 0; // Прошлое значения энкодера volatile WORD data = 0; // Количество шаговЗдесь мы подключили необходимые библиотеки и создали необходимые переменные. Далее пишем обработчик прерывания для INT0.
ISR(INT0_vect) { input = (PINC & 0x03); switch(buf) { case 0: { if(input == 2) data++; if(input == 3) data--; break; } case 1: { if(input == 0) data++; if(input == 1) data--; break; } case 2: { if(input == 3) data++; if(input == 0) data--; break; } case 3: { if(input == 1) data++; if(input == 2) data--; break; } buf = input; }Собственно здесь ничего нового. При входе в обработчик берем текущее значение из порта и зная предыдущее значение, выбираем куда нам считать опираясь на текущее значение. Отличие от предыдущей программы заключается в том что здесь мы не сравниваем предыдущее значение с текущем. Это связано с тем что мы попали в обработчик прерывания при изменении на ножках энкодера, а это априори говорит о том что текущее значение разнится с предыдущем. Плюс в сторону прерывания)))
int main(void) { MCUCR |= (1 << ISC00); // Прерывания при любых изменениях на ножке GICR |= (1 << INT0); // Разрешить прерывание от INT0 DDRC = 0x00; // Порт С на вход timers_init(); // Проинициализировали тамер Т2 lcd_init(0); // Проинициализировали ЖК дисплей timer(TIMER_0, 1, ON); // Будем выводить на дисплей каждую 1мсЭтот кусок кода отвечает за инициализацию периферии. Первые две строки разрешают внешнее прерывание по любому изменению на ножке INT0. Далее настраиваем порт С на вход. Следующая строка инициализирует таймеры. Потом сам ЖК дисплей и последняя строчка создает нулевой таймер который будет обрабатываться каждую миллисекунду.
while(1) { if(data > 400) data = 400; if(data < 0) data = 0; if(T0_START) { sprintf(str, "STEP %d ", data); lcd_gotoxy(0,0); lcd_str_out(str); } }А это бесконечный цикл основной программы. Здесь задаем граничные значения нуля и четырехсот. И пишем обработчик для таймера. В нем всего лишь форматируем строку и выводим количество шагов на ЖК дисплей. Вот и вся программа.
Если все таки у кого-то возникнут вопросы, пишите.
Проект для AtmelStudio 6.2 (Требует обязательного наличия библиотеки axlib)
И как всегда видео всего этого безобразия
JW Player goes here
Андрей 02.12.15 12:25
А зачем такой энкодер? Куда его применять?
Алексей 03.12.15 10:33
Для более точной обратной связи.
st 10.07.16 00:38
Добрый день! А можно пример использования энкодера без задействования прерывания. Заранее спасибо!
Алексей 10.07.16 19:17
Можно. Вот например.
Юрий 09.07.17 15:20
Привет можешь написать статью с подключением выводов энкодера на оба прерывания int0 b int1 без диодов на программе CodeVision AVR
Алексей 09.07.17 19:26
Нет. Тоесть на прерываниях могу, но только в студии.