В этой статье будет рассмотрена схема подключения инкрементального энкодера к микроконтроллеру AVR ATmega8 и приведена программа на языке C (с пояснениями), обеспечивающая взаимодействие этих устройств. Микроконтроллер ATmega8 (семейство AVR) был специально спроектирован для применения во встраиваемых приложениях (embedded applications).
Принципы работы инкрементального энкодера
Инкрементальный энкодер представляет собой устройство кодирования по углу поворота (в отличие от линейного кодирования). По мере поворота входного вала он генерирует поток импульсов, по числу которых определяется угол поворота. Обычно применяется для определения углового перемещения двигателя или вала (оси). Часто используется для замены аналоговых потенциометров и конденсаторов переменной ёмкости. Имеет от трех до пяти контактов. Внешний вид типового инкрементального энкодера представлен на следующем рисунке.
Представленный на рисунке инкрементальный энкодер имеет следующие контакты:
- земля;
- контакт для подачи питающего напряжения 5В;
- контакт выходного сигнала A;
- контакт выходного сигнала B;
- контакт шкалы или контакт общего назначения.
Если на инкрементальный энкодер подано питающее напряжение и осуществляется вращение его ручки, то он генерирует следующую последовательность импульсов, показанную в следующей таблице.
То есть если мы вращаем ручку кодера по часовой стрелке, то мы будем иметь отрицательный перепад сигнала сначала на контакте A, а потом на контакте B.
Если же мы вращаем ручку кодера против часовой стрелки, то мы будем иметь отрицательный перепад сигнала сначала на контакте B, а потом на контакте A.
Если угловой кодер имеет 20 позиций, то перепад сигнала будет происходить один раз за 360/20 = 18 градусов. Если число позиций инкрементального кодера больше, то и его точность будет также увеличиваться.
Таким образом, мы будем иметь сведения о направлении вращения и угле поворота энкодера. Следовательно мы сможем определить и положение ручки энкодера в каждый момент времени.
Необходимые компоненты
Аппаратное обеспечение
- Микроконтроллер ATmega8 (купить на AliExpress).
- Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
- Инкрементальный энкодер (Rotary Encoder) (купить на AliExpress).
- Конденсатор 100 нФ (3 шт.) (купить на AliExpress).
- Конденсатор 1000 мкФ (купить на AliExpress).
- Резистор 220 Ом (2 шт.) (купить на AliExpress).
- Резистор 1 кОм (купить на AliExpress).
- Светодиод (8 шт.) (купить на AliExpress).
- Источник питания с напряжением 5 Вольт.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Программное обеспечение
- Atmel Studio версии 6.1 (или выше).
- Progisp или flash magic (необязательно).
Работа схемы
Схема устройства приведена на следующем рисунке.
Конденсаторы в данной схеме используются для устранения эффектов биений от углового кодера. Без них могут возникнуть сложности в правильном считывании позиции углового кодера.
Когда ручка энкодера вращается, то возникает разновременность срабатывания между двумя выходными контактами. С помощью микроконтроллера ATmega8 можно распознать эту разновременность срабатывания для вращения ручки энкодера по часовой и против часовой стрелки.
Если вращение происходит по часовой стрелке, то значение двоичного счетчика увеличивается на 1 и это событие отображается с помощью светодиодов, присутствующих в схеме. Если вращение происходит против часовой стрелки, то значение двоичного счетчика уменьшается на 1, что также отображается с помощью светодиодов.
Для данной схемы мы никоим образом не изменяем фьюзы (fuse bits) микроконтроллера atmega8, поэтому он будет работать на частоте 1 МГц от своего внутреннего генератора.
Исходный код программы на языке С (Си) с пояснениями
Программа для рассматриваемой схемы представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
#include <avr/io.h> // заголовок чтобы разрешить контроль данных на контактах #define F_CPU 1000000UL // задание тактовой частоты микроконтроллера #include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе int main(void) { DDRD = 0xFF; // установка portD на вывод данных PORTD =0; DDRC= 0; // установка portC на ввод данных int count =0; int i=0; while(1) { if (i==0) { if ((bit_is_clear(PINC,0))||(bit_is_clear(PINC,1))) // если в течение цикла на каких-нибудь контактах инкрементального энкодера имеет место отрицательный перепад сигнала { i= 1; _delay_ms(10); if (bit_is_clear(PINC,0) ) // если на PINB отрицательный перепад сигнала случился вторым (то есть после PINA) { if (count<255) { count++; // увеличение двоичного счетчика на 1 если его значение менее 255 } } if (bit_is_clear(PINC,1)) // если на PINA отрицательный перепад сигнала случился вторым (то есть после PINB) { if (count>0) { count--; // если значение двоичного счетчика больше 0, то уменьшить его значение на 1 } } } } PORTD = count; if ((bit_is_set(PINC,0))&&(bit_is_set(PINC,1) )) // ждем пока не сбросится позиция ручки кодера { i = 0; } } } |
Здравствуйте, что за среда программирования и компилятор использовался? В mplab xide скорее всего синтаксис bit_is_clear() не пройдет. Там через битовую маску нужно. Вот так
if(~PINC&(1<<0)){ your code...}// Если будет 0 на ноге PC0, то условие выполнится.
Добрый день, насколько я помню использовалась Atmel Studio. Спасибо за уточнение
Для использования энкодера в практических схемах я бы использовал внешние прерывания по спадающему фронту. В примере автора нет работающих таймеров, компараторов, UART со своими прерываниями, режимов энергосбережения и т.п., поэтому считыванию показаний энкодера в основном цикле ничего не мешает
Да, конечно, в большинстве случаев использование прерывания для обработки вращения инкрементального энкодера будет работать лучше. Но это ведь усложнит программу, а статья предназначена для начинающих - они ведь могут и не знать как работать с прерываниями в микроконтроллерах AVR