2008-08-29 16 views
5

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

Разъяснение

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

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

Я попытался просмотреть кодировщик, и он, кажется, использует от 2 до 4 мс от первого изменения Pin до изменения другого Pin.

ответ

10

У меня есть веб-страница о rotary encoders and how to use them, которая может вам пригодиться.

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

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

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

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

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

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

0

С чем именно вы столкнулись? Я предполагаю, что вы смогли подключить контакты кодера к вашему ПОС в соответствии с техническими спецификациями, связанными с страницей Farnell, которую вы дали, так же как и проблема с чтением данных? Вы не получаете никаких данных от кодировщика? Вы не знаете, как интерпретировать данные, которые вы возвращаете?

1

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

0
/* 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) 
*/ 
5

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

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

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

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

#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

Это нормально, как «хобби». Однако дополнительное оборудование (резисторы/конденсаторы) не следует недооценивать. Именно поэтому программное debouncing является «лучшим» решением (IMHO). – 2009-02-02 22:45:23