문제

AVR 마이크로 컨트롤러에서 로터리 인코더가 제대로 작동하도록 하는 데 문제가 있습니다.인코더는 기계식입니다. ALPS 인코더, 그리고 나는 사용하고 있습니다 Atmega168.

설명

핀 소리를 듣기 위해 외부 인터럽트를 사용해 보았지만 너무 느린 것 같습니다.핀 A가 하이가 되면 인터럽트 절차가 시작된 다음 핀 B가 하이인지 확인합니다.아이디어는 핀 B가 하이인 경우 핀 A가 하이가 된 순간 시계 반대 방향으로 회전한다는 것입니다.핀 B가 로우이면 시계 방향으로 회전합니다.그런데 AVR이 Pin B를 확인하는 데 시간이 너무 오래 걸리는 것 같아서 항상 high로 읽혀집니다.

또한 핀 B나 핀 A가 변경될 때까지 단순히 차단하는 프로그램을 만들어 보았습니다.하지만 인코더가 회전할 때 너무 많은 소음이 발생할 수 있습니다. 이 역시 작동하지 않기 때문입니다.나의 마지막 시도는 마지막 8개 값을 버퍼에 저장하고 값이 낮은 값에서 높은 값으로 이동하는지 확인하는 타이머를 갖는 것이었습니다.이것도 작동하지 않았습니다.

인코더 범위 지정을 시도했는데 첫 번째 핀 변경부터 다른 핀 변경까지 2~4ms를 사용하는 것 같습니다.

도움이 되었습니까?

해결책

다음과 관련된 웹페이지가 있습니다. 로터리 엔코더 및 사용 방법, 유용할 수도 있습니다.

안타깝게도 추가 정보가 없으면 귀하의 특정 문제를 해결할 수 없습니다.

인코더에 어떤 마이크로컨트롤러 핀이 연결되어 있으며 현재 펄스를 디코딩하는 데 사용하고 있는 코드는 무엇입니까?

좋아, 당신은 몇 가지 다른 문제를 다루고 있습니다. 첫 번째 문제는 이것이 기계식 인코더이므로 스위치 소음(바운스, 채터링)을 처리해야 한다는 것입니다.그만큼 데이터 시트 부품이 튀는 것을 멈추고 잘못된 출력을 생성하는 데 최대 3mS가 걸릴 수 있음을 나타냅니다.

디바운스 루틴을 생성해야 합니다.가장 간단한 방법은 A가 높아지는지 지속적으로 확인하는 것입니다.그렇다면 타이머를 시작하고 3ms 후에 다시 확인하세요.여전히 높으면 B를 확인할 수 있습니다. 높지 않으면 스퓨리어스 펄스를 무시하고 계속해서 A 하이를 찾습니다.B를 확인하면 보고, 3ms 동안 타이머를 시작한 다음 다시 B를 봅니다.두 번 모두 동일했다면 해당 값을 사용할 수 있습니다. 3ms 내에 변경되면 다시 수행해야 합니다(B를 읽고 3ms를 기다린 다음 다시 읽고 일치하는지 확인).

atmega는 느린 클럭 속도를 실행하지 않는 한 이러한 검사가 느리게 진행되는 것에 대해 걱정할 필요가 없을 만큼 충분히 빠릅니다.

기계적 소음을 처리한 후에는 적절한 그레이 코드 루틴을 살펴보고 싶을 것입니다. B가 낮아질 때 A가 높아지면 이를 감소시키지 않으면 따르는 알고리즘이 작동하지 않습니다.일반적으로 사람들은 두 입력의 마지막 값을 저장한 다음 이를 두 입력의 새 값과 비교하고 이를 기반으로 작은 함수를 사용하여 늘리거나 줄입니다.(위에서 표에 대해 언급한 웹사이트에서 "고해상도 판독"이라는 제목을 확인하세요.)두 판독값을 4비트 숫자로 결합하고 간단한 배열을 사용하여 카운터를 늘리거나 줄일지 알려주지만 훨씬 더 발전된 솔루션이 있으며 코드 크기, 속도 또는 코드 유지 관리 용이성에 맞게 최적화됩니다.

다른 팁

아날로그 저역 통과 필터를 추가하면 신호가 크게 향상됩니다.저역 통과 필터를 사용하면 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의 프로그램입니다.AVR의 입력 PORTB에 A와 B를 연결합니다.

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

이 코드는 인코더를 매우 빠르게 회전시키지 않는 한 작동합니다.그런 다음 한두 단계를 놓칠 수 있지만 인코더를 사용하는 사람은 인코더를 몇 단계 돌렸는지 알 수 없기 때문에 중요하지 않습니다.

속도는 문제가 되지 않습니다.대부분의 모든 기계식 스위치에는 디바운스 루틴이 필요합니다.인터럽트로 이 작업을 수행하려면 인터럽트가 트리거될 때 인터럽트를 끄고 몇 ms 후에 다시 켜는 타이머를 시작하십시오.프로그램을 폴링 없이 유지합니다 >:)

정확히 어떤 문제가 있나요?귀하가 제공한 Farnell 페이지에 링크된 기술 사양에 따라 인코더의 핀을 PIC에 연결할 수 있다고 가정합니다. 그러면 데이터를 읽는 데 문제가 있습니까?인코더에서 데이터를 얻지 못합니까?반환되는 데이터를 해석하는 방법을 모르시나요?

/* 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)
 */
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top