Используя угловой кодер с AVR Микро контроллер

У меня была аналогичная ситуация при использовании обратного вызова «eventClick» библиотеки fullCalendar , чьи обратные вызовы возвращаются из-за пределов угловой зоны, в результате чего мое приложение имеет частичные и ненадежные эффекты. Мне удалось объединить зонный подход и ссылку на замыкание на компонент, как показано ниже, чтобы поднять выходное событие. Как только я начал выполнять событие внутри метода zone.run (), событие и его эффекты снова были предсказуемы и подхвачены обнаружением угловых изменений. Надеюсь, это поможет кому-то.

constructor(public zone: NgZone) { // code removed for clarity
}

ngOnInit() {
    this.configureCalendar();
}

private configureCalendar() {
    // FullCalendar settings
    this.uiConfig = {
        calendar: { // code removed for clarity

        }
    };

    this.uiConfig.calendar.eventClick = this.onEventClick();

}

private onEventClick() {
    const vm = this;

    return function (event, element, view) {
        vm.zone.run(() => {
            vm.onSequenceSelected.emit(event.sequenceSource);                    
        });

        return false;

    };
}

5
задан Marius 29 August 2008 в 17:47
поделиться

5 ответов

У меня есть веб-страница об угловых кодерах и как использовать их, которых Вы могли бы найти полезным.

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

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

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

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

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

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

10
ответ дан 18 December 2019 в 10:51
поделиться

Добавление аналогового фильтра низких частот значительно улучшает сигнал. С фильтром низких частот код 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;
}

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

5
ответ дан 18 December 2019 в 10:51
поделиться

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

1
ответ дан 18 December 2019 в 10:51
поделиться

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

0
ответ дан 18 December 2019 в 10:51
поделиться
/* 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
ответ дан 18 December 2019 в 10:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: