Главная » Статьи » Уроки по программированию stm32fxxx » Уроки по программированию stm32f4xx

Урок 5: Подключение энкодера

Принцип работы

Инкрементный энкодер (рис 1.1) позволяет отследить поворот влево или вправо, но не позволяет отследить точное положение. Энкодер зачастую используется для контроля поворота вала, если не требуется высокая точность или для управления программой. Например, для установки какого то значения: поворот влево - увеличение значения на единицу, поворот вправо - уменьшение этого значения на единицу. Кроме того, энкодер может быть использован как кнопка. Для этого у него присутствуют отдельные выводы.
Выходной сигнал имеет два канала, в которых идентичные последовательности импульсов сдвинуты на 90° относительно друг друга (парафазные импульсы), что позволяет определять направление вращения.


Рис 1

Выводы энкодера pec16-4220f-s0024

Энкодер pec16-4220f-s0024 имеет 5 выводов. 2 вывода, расположенные с одного края, отвечают за кнопку. При нажатии на энкодер эти выводы замыкаются друг на друга. Расположенные с другой стороны три вывода отвечают за поворот. Из которых на выводах А и В (рис 1.2) появляются импульсы при повороте энкодера, в вывод С подключается к земле.


Рис 2

При подключении выводов А и В требуется подтянуть и резистором к питанию, т.к. при повороте энкодера выводы в определённый момент подключаются к земле, создавая тем самым импульсы. В статичном положении на выводы энкодера не подключены ни к чему. Т.е., если выводы подтянуты к питанию, на них будет логическая единица.

Программирование кнопки

Для реализации схемы кнопки каждый из выводов подключается к одному из выводов микроконтроллера. Один из выводов настраивается как выход и устанавливается в 0. Это будет земля.
Второй вывод настраивается на вход и подтягивается к питанию. Теперь, если кнопка не нажата, на этом входе будет единица. Если же кнопка нажата, то на ней будет ноль, т.к. она окажется закороченной на землю. Сам алгоритм программирования кнопки в применении к сигналам энкодера будет рассмотрен ниже.

Программирование вращения энкодера

Как уже было сказано выше, в статичном состоянии на выходах А и В энкодера установлена логическая 1, т.к. оба вывода подтянуты к питанию. При вращении ножки А и В периодически подключаются к земле. В итоге на них появляются импульсы, показанные на рис 2.1.


Рис 3

Как можно видеть, при вращении в одну сторону, сигнал А опережает сигнал В по фазе и на нём раньше устанавливается логический ноль. При вращении в другую сторону, наоборот, сигнал В опережает сигнал А по фазе. В итоге можно отметить, что на выходах А и В появляется так называемый код Грея, который при вращении в одну сторону выглядит так:
А: 1 -> 0 -> 1 -> 1 -> 1
В: 1 -> 1 -> 1 -> 0 -> 1
При вращении в другую сторону:
А: 1 -> 1 -> 1 -> 0 -> 1
В: 1 -> 0 -> 1 -> 1 -> 1
Кроме того, задача обработки усложняется тем, что у энкодера, как у любого другого механического устройства, присутствует дребезг.
Сначала инициализируем выводы микроконтроллера следующим кодом:
Инициализация выводов микроконтроллера.

void encoder_ini(void)
{
GPIO_InitTypeDef GPIO_Init_LED;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

//---------button-------
GPIO_Init_LED.GPIO_Pin = GPIO_Pin_7;
GPIO_Init_LED.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init_LED.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init_LED.GPIO_OType = GPIO_OType_PP;
GPIO_Init_LED.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOE, &GPIO_Init_LED);

GPIO_Init_LED.GPIO_Pin = GPIO_Pin_8;
GPIO_Init_LED.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init_LED.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init_LED.GPIO_OType = GPIO_OType_PP;
GPIO_Init_LED.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_Init(GPIOE, &GPIO_Init_LED);

GPIO_SetBits(GPIOE, GPIO_Pin_7);
//---------end button-------

//---------rotor-------
GPIO_Init_LED.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_Init_LED.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init_LED.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init_LED.GPIO_OType = GPIO_OType_PP;
GPIO_Init_LED.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(GPIOE, &GPIO_Init_LED);
//---------end rotor-------
}


Существует множество вариантов анализа получаемых с энкодера сигналов. Одним из которых является анализ того, какой из сигналов раньше установился в ноль. Сделать это можно следующим образом.
Во-первых, нужно избавиться от дребезга сигналов. Сделать это можно с помощью следующего кода:

Код борьбы с дребезгом.

#define ENC_A() GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_9)
#define ENC_B() GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_10)

uint8_t enc_a=0, enc_b=0, count_a=0, count_b=0;

void SysTick_Handler(void)//0.1ms
{
if (ENC_A() == 1)
{
if (count_a < 10){count_a++;}
else{enc_a = 1;}
} else{
if (count_a > 0){count_a--;}
else {enc_a = 0;}
}
//----------------------
if (ENC_B() == 1)
{
if (count_b < 10){count_b++;}
else {enc_b = 1; }
}
else
{
if (count_b > 0){count_b--;}
else {enc_b = 0;}
}
}


Из кода видно, что вывод А подключен к ножке Е9 микроконтроллера, а вывод В к ножке Е10.
Остальная часть кода реализует борьбу с дребезгом для каждого из этих двух выводов.
Теперь надо отловить какой из выводов раньше стал равным нулю. Для этого вводится ещё одна переменная, назовём её ab. Будем устанавливать эту переменную в 1, когда один из выводов устанавливается в 0. Когда же второй устанавливается в ноль, делается вывод о направлении поворота в зависимости от того в каком порядке устанавливался ноль.

Код для отслеживания поворота энкодера.

uint8_t ab=0, encoder_state=0;
void SysTick_Handler(void)//1ms
{
if (ENC_A() == 1)
{
if (count_a < ENC_DELAY){count_a++;}
else
{
enc_a = 1;
if (enc_b == 1) {ab = 0;}
}
}
else
{
if (count_a > 0){count_a--;}
else
{
enc_a = 0;
if (ab == 0){ab = 1;}
else {if(ab == 1) {encoder_state = 1;ab = 2;}}
}
}
//----------------------
if (ENC_B() == 1)
{
if (count_b < ENC_DELAY){count_b++;}
else {enc_b = 1; if (enc_a == 1) {ab = 0;}}
}
else
{
if (count_b > 0){count_b--;}
else
{
enc_b = 0;
if (ab == 0){ab = 1;}
else { if(ab == 1) {encoder_state = 2;ab = 2;}}
}
}
}

Данный код – это модификация кода, рассмотренного выше. Изменением в нём являются строки:

if (ab == 0){ab = 1;}
else { if(ab == 1) {encoder_state = 2;ab = 2;}}

Переменная ab устанавливается в 1, в том сигнале, который первым установится в 0. Когда же второй сигнал устанавливается 0, в зависимости от того какой это сигнал переменной присваивается значение 1 или 2. А переменная ab устанавливается равной 2. В этом случае encoder_state не будет присваиваться значение повторно, пока ab не будет сброшено в 0. А делать это лучше всего, когда оба сигнала установлены в единицу.
В основной программе проверяется переменная encoder_state. В зависимости от её значения программа выполняет те или иные операции, а сама encoder_state сбрасывается в 0.
Скачать пример работы с энкодером можно от сюда.
Категория: Уроки по программированию stm32f4xx | Добавил: Korvin (06.11.2013)
Просмотров: 10869 | Комментарии: 1 | Рейтинг: 5.0/1
Всего комментариев: 1
1 Angel G  
0
spasibo, very useful!

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]