Использование поворотного энкодера с микроконтроллером AVR - PullRequest
5 голосов
/ 29 августа 2008

У меня проблемы с настройкой поворотного энкодера для правильной работы с микроконтроллерами AVR. Кодировщик - это механический ALPS-кодировщик , и я использую Atmega168 .

Разъяснение

Я пытался использовать внешнее прерывание для прослушивания контактов, но кажется, что оно слишком медленное. Когда вывод A становится высоким, начинается процедура прерывания, а затем проверяется, является ли вывод B высоким. Идея состоит в том, что если вывод В высокий в момент подъема вывода А, то он вращается против часовой стрелки. Если контакт B низкий, то он вращается по часовой стрелке. Но кажется, что AVR слишком долго проверяет контакт B, поэтому он всегда читается как высокий.

Я также пытался создать программу, которая просто блокирует, пока не изменится контакт B или контакт A. Но может случиться так, что при вращении кодера слишком много шума, потому что это тоже не работает. Моя последняя попытка была иметь таймер, который хранит последние 8 значений в буфере и проверяет, идет ли он от низкого до высокого. Это тоже не сработало.

Я попытался определить область действия энкодера, и он, похоже, использует от 2 до 4 мс от первого изменения Пина до изменения другого Пина.

Ответы [ 5 ]

10 голосов
/ 29 августа 2008

У меня есть веб-страница о поворотных энкодерах и способах их использования , что может оказаться полезным.

К сожалению, без дополнительной информации я не могу решить вашу конкретную проблему.

Какие выводы микроконтроллера подключены к энкодеру и какой код вы сейчас используете для декодирования импульсов?

Хорошо, вы имеете дело с несколькими различными проблемами, первая проблема заключается в том, что это механический кодировщик, поэтому вам приходится иметь дело с шумом переключения (отскок, вибрация). В листе данных указано, что для прекращения подпрыгивания деталей и создания ложных выходных данных может потребоваться до 3 мсек.

Вам нужно создать процедуру отладки. Самым простым из которых является постоянная проверка, чтобы увидеть, идет ли А высоко. Если это так, запустите таймер и проверьте его снова через 3 мс. Если он все еще высокий, тогда вы можете проверить B - если он не высокий, тогда вы игнорируете паразитный импульс и продолжаете искать уровень A. Когда вы проверяете B, вы смотрите на него, запускаете таймер на 3 мс, а затем снова смотрите на B. Если оно было одинаковым оба раза, то вы можете использовать это значение - если оно изменится в течение 3 мс, вам придется сделать это снова (прочитайте B, подождите 3 мс, затем прочитайте его снова и посмотрите, соответствует ли оно).

Atmega достаточно быстр, чтобы вам не приходилось беспокоиться о медленной проверке, если только вы не используете низкую тактовую частоту.

Как только вы разберетесь с механическим шумом, вы захотите взглянуть на правильную подпрограмму серого кода - алгоритм, которому вы следуете, не будет работать, если вы также не уменьшите, если A высокий, а B низкий. Обычно люди сохраняют последнее значение двух входов, а затем сравнивают его с новым значением двух входов и используют небольшую функцию для увеличения или уменьшения на основе этого. (Проверьте заголовок «чтение с высоким разрешением» на веб-сайте, который я упомянул выше для таблицы). Я объединяю два чтения в четырехбитное число и использую простой массив, чтобы сообщить мне, увеличивать или уменьшать счетчик, но есть решения, которые являются даже более продвинутыми и оптимизируют размер кода, скорость или простоту обслуживания кода.

5 голосов
/ 23 ноября 2008

Добавление аналогового фильтра нижних частот значительно улучшает сигнал. С фильтром нижних частот код на AVR был действительно простым.

       _________
        |         |
        | Encoder |
        |_________|
          |  |  |
          |  |  |
     100n |  O  | 100n  
 GND O-||-+ GND +-||-O GND
          |     | 
          \     /
      3K3 /     \ 3K3
          \     /
          |     |    
VCC O-/\/-+     +-\/\-O VCC
     15K  |     |  15K
          |     |
          O     O
          A     B

Ах, чудеса искусства ASCII: p

Вот программа на AVR. Подключите A и B к входу PORTB на AVR:

#include <avr/io.h>

#define PIN_A (PINB&1)
#define PIN_B ((PINB>>1)&1)

int main(void){
    uint8_t st0 = 0;
    uint8_t st1 = 0;
    uint8_t dir = 0;
    uint8_t temp = 0;
    uint8_t counter = 0;
    DDRD = 0xFF;
    DDRB = 0;
    while(1){   
    if(dir == 0){
        if(PIN_A & (!PIN_B)){
            dir = 2;
        }else if(PIN_B & (!PIN_A)){
            dir = 4;
        }else{
            dir = 0;
        }
    }else if(dir == 2){
        if(PIN_A & (!PIN_B)){
            dir = 2;
        }else if((!PIN_A) & (!PIN_B)){
            counter--;
            dir = 0;
        }else{
            dir = 0;
        }
    }else if(dir == 4){
        if(PIN_B & (!PIN_A)){
            dir = 4;
        }else if((!PIN_A) & (!PIN_B)){
            counter++;
            dir = 0;
        }else{
            dir = 0;
        }
    }else if(PIN_B & PIN_A){
        dir = 0;
    }
        PORTD = ~counter;
    }
    return 0;
}

Этот код работает, если вы не очень быстро поворачиваете кодировщик. Тогда он может пропустить шаг или два, но это не важно, так как человек, использующий кодировщик, не будет знать, на сколько шагов он его включил.

1 голос
/ 22 октября 2008

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

0 голосов
/ 03 ноября 2008
/* into 0 service rutine */
if(CHB)
{
  if(flagB)
   Count++;
  FlagB=0;
}
else
{
  if(FlagB)
   count--:
  FlagB=0:
}

/* into 1 service rutine */
FlagB=1;

/* make this give to you a windows time of 1/4 of T of the encoder resolution
   that is in angle term: 360/ (4*resolution)
 */
0 голосов
/ 29 августа 2008

С чем именно у вас проблемы? Я предполагаю, что вы смогли подключить контакты кодера к вашей PIC в соответствии с техническими характеристиками, приведенными на странице Фарнелла, которую вы дали, так что проблема в чтении данных? Вы не получаете никаких данных от кодировщика? Разве вы не знаете, как интерпретировать возвращаемые данные?

...