Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 05.10.2007
Сообщений: 498
1

Обработка сигналов энкодера

25.09.2014, 11:34. Показов 7257. Ответов 0
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Занимаюсь новым интерфейсом для своих систем. Разработал простую и интересную программу для работы с энкодером. Мне она понравилась, и захотелось поделиться удачной программой.
Просматривая аналогичные решения по обработке сигналов от инкрементального энкодера, я увидел три способа решения задачи:
1) с помощью условных переходов и статических переменных, хранящих предыдущие состояния энкодера;
2) с помощью машины состояний, которая переключается по сигналам энкодера, исключая запрещённые состояния.
3) вариация номера два с использованием switch - case с метками возможных состояний.
Однако, все варианты имеют недостатки.
Вариант номер один использует несколько переменных и переключается один раз за четыре возможных состояния энкодера.
Вариант номер два использует одну переменную, в которой хранятся в битовом представлении текущее и предыдущее состояние энкодера. Анализ состояний производится с помощью массива данных. Это вариант мне понравился больше всего. Но в том состоянии алгоритм не защищён от ложных срабатываний и пропуска данных.
Вариант номер три использует такое же представление данных, как и вариант номер два, но вместо массива данных использует переход по множеству case меток. Самый неудобный и трудный для восприятия.
Взяв второй метод за основу, я доработал его до приемлемого вида.
Вначале основы.
При повороте энкодера по часовой стрелке состояние выводов изменяются как
00, 01, 11, 10, 00...
А при повороте против часовой стрелки состояние выводов изменяется в другой последовательности:
00, 10, 11, 01, 00...
Считывать состояния энкодера можно один, два или четыре раза за период, но необходимо учитывать предыдущее состояние. Например, если текущее состояние энкодера 11 и предыдущее значение 01, то энкодер повернули по часовой стрелке. А если предыдущее значение 10, то энкодер повернули против часовой стрелки. Соответственно, предыдущие состояния 00 и 11 будут ошибочными, и их нужно игнорировать.
Итак, мы имеем 4 варианта текущего состояния и 4 варианта предыдущего состояния энкодера. Вместе они дают 16 комбинаций. Если взять переменную из четырёх бит, и в младшие два бита записать текущее состояние, а в старшие два - предыдущее состояние, и использовать получившееся число как индекс в массиве, то с помощью значений чисел в массиве возможно точно определить состояние энкодера. Например, 1 - поворот вправо, -1 - поворот влево, 0 - запрещённая комбинация.
Что самое интересное, это то, что такой алгоритм можно применять как для одного изменения энкодера за период, так и для двух и четырёх изменений. А это важно, потому что встречаются энкодеры с разным количеством периодов за оборот. Например, энкодеру с 12 периодами однозначно понадобится 2 или 4 изменения за период, а энкодеру с 48 периодами не больше 1.
Возможность подстройки под тип энкодера это первое преимущество. Второе - я добавил защиту от повторных срабатываний при одинаковом положении энкодера. Например, встретилось два подряд значения 01. Без фильтрации это вызовет запрещённое состояние 01-01 и ошибку в определении следующего состояния. Почему - ответ в третьем преимуществе. Программа анализирует три последовательные состояния энкодера, и при переходе, например, 00-01-00 (то есть шаг туда, шаг сюда) не будет двух ложных срабатываний энкодера. Без фильтрации мы можем получить последовательность состояний 00-01-01-00 и сравнение текущего и третьего состояний не решит проблему дрожания энкодера. Такая проверка нужна для 1-го и 2-х срабатываний за период энкодера.
Программу я писал для микропроцессора STM8S в среде IAR. Текст приведён ниже:
Код
// определение количества событий за период энкодера (1, 2, 4)
#define   ENC_COUNT      2
// массив правильных значений переходов
// между предыдущим и настоящим значением энкодера
#if (ENC_COUNT == 1)
// для 1-го переключения за период
int8_t enc_array [16] =
{
0,  0,  0,  0,
-1,  0,  0,  0,
1,  0,  0,  0,
0,  0,  0,  0
};
#elif (ENC_COUNT == 2)
// для 2-х переключений за период
int8_t enc_array [16] =
{
0,  0,  0,  0,
-1,  0,  0,  1,
1,  0,  0, -1,
0,  0,  0,  0
};
#else
// для 4-х переключений за период
int8_t enc_array [16] =
{
0,  1, -1,  0,
-1,  0,  0,  1,
1,  0,  0, -1,
0, -1,  1,  0
};
#endif

uint8_t      state         = 0;   // сохранённые состояния энкодера
int8_t      count_encoder   = 0;   // переменная приращения энкодера

/*****************************************************************************
* Настройка энкодера.
* Ножки на вход с подтяжкой к питанию
* Прерывания на этот порт с активацией по фронту и спаду
* Приоритет высокий
*****************************************************************************/
void encoder_init (void)
{
// настройка контроллера прерываний
__disable_interrupt();
EXTI->CR1 &= ~EXTI_CR1_PAIS_MASK;
EXTI->CR1 |= 0x03;   //EXTI_CR1_PAIS_FR;      // Прерывания А по фронту и спаду
// настройка приоритетов прерываний
ITC->ISPR2 &= ~ITC_SPR2_PORTA_MSK;
ITC->ISPR2 |= ITC_SPR2_PORTA_LVL3;         // высокий уровень прерываний порта A
// настройка ножек
GPIO_ConfigInput (ENC_A_PORT1, ENC_A_PIN1, PinPullup, PinIrqOn);
GPIO_ConfigInput (ENC_B_PORT1, ENC_B_PIN1, PinPullup, PinIrqOn);
// установка текущего состояния энкодера
if (ENC_A_PIN)
state |= 0x01;
if (ENC_B_PIN)
state |= 0x02;
__enable_interrupt();
}

/*****************************************************************************
* Прерывание по порту A
* здесь опрашивается состояние энкодера
* результат прерывания сохраняется в переменной count_encoder
*****************************************************************************/
INTERRUPT_HANDLER (Port_A_EXTISR, 3)
{
int8_t   stt;
state <<= 2;                           // освободили место для новых значений
if (ENC_A_PIN)
state |= 0x01;
if (ENC_B_PIN)
state |= 0x02;                        // считали данные энкодера
if ((state & 0x03) != ((state >> 2) & 0x03))   // если разные значения с предыдущим
{
stt = enc_array [state & 0x0F];            // получили условие из таблицы
if (stt)                           // при изменении энкодера
{
#if (ENC_COUNT == 1 || ENC_COUNT == 2)
if ((state & 0x03) != ((state >> 4) & 0x03))   // и если энкодер не вернулся обратно
#endif
{
count_encoder += stt;               // изменим счётчик энкодера
}
}
}
else
{
state >>= 2;                        // если одинаковые значения - вернуть state
}
}

/*****************************************************************************
* функция int_8t encoder() возвращает изменение положения
* энкодера после последнего чтения, если энкодер не двигался, то 0
******************************************************************************/
int8_t encoder (void)
{
int8_t status = count_encoder;
count_encoder = 0;
return status;
}
Позже добавил пропорциональное управление энкодером. В зависимости от скорости вращения переменная count_encoder изменяется или на единицу (медленное вращение), или на десяток (вращение со средней скоростью), или на сотню (быстрое вращение). Это позволило быстро вводить энкодером числа от 1 до 1000. Согласитесь, крутить 50 оборотов, чтобы выставить 1000 - занятие неблагодарное :)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.09.2014, 11:34
Ответы с готовыми решениями:

Обработка энкодера
Имеется трёх импульсный энкодер (если это правильное название), т.е. датчик который имеет три линии...

обработка инкрементального энкодера на прерываниях (asm)
Приветствую сообщество. Пытаюсь нарулить на ассемблере код обработки энкодера, оно вроде...

[MSC-51] Цифровая обработка сигналов по формулам
Доброго времени суток. прошу не кидаться тапками. Помогите с решением задания на 8051 2.2....

Цифровая обработка сигналов. Ортогональность сигналов
Только начала заниматься цифровой обработкой и возник вопрос. У нас есть 2 сигнала s1 = @(t)...

Обработка ЧМ сигналов(спектры ЧМ сигналов)
Доброго времени суток! Ранее задавала вопрос: &quot;Алгоритм обработки ЧМ сигналов, основанный на...

0
25.09.2014, 11:34
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.09.2014, 11:34
Помогаю со студенческими работами здесь

Обработка сигналов
Здравствуйте, подскажите, пожалуйста, какие-нибудь статьи, источники посмотреть для такой задачи:...

Обработка сигналов
Привет всем! Написал следующий код: void func(int sig, siginfo_t* sinfo, void *_addinfo) {...

Обработка сигналов
Здравствуйте Уважаемые! Не могу сообразить правильно сделал или нет, но кроме Вас спросить не у...

Обработка сигналов
Хочу решить задачу с сигналами. Надо написать программу, которая порождает процес, этому процессу я...

обработка сигналов
Здравствуйте!! Помогите пожалуйста с заданием!!! Нужно написать программу. В которой: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru