Using a rotary encoder with AVR Micro controller

后端 未结 5 1221
小鲜肉
小鲜肉 2021-02-10 06:48

I\'m having trouble getting a rotary encoder to work properly with AVR micro controllers. The encoder is a mechanical ALPS encoder, and I\'m using Atmega168.

Cla

5条回答
  •  南方客
    南方客 (楼主)
    2021-02-10 07:15

    Adding an analog lowpass filter greatly improves the signal. With the lowpass filter, the code on the AVR was really simple.

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

    Ah, the wonders of ASCII art :p

    Here is the program on the AVR. Connect A and B to input PORTB on the avr:

    #include 
    
    #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;
    }
    

    This code works unless you rotate the encoder really fast. Then it might miss a step or two, but that is not important, as the person using the encoder won't know how many steps they have turned it.

提交回复
热议问题