当前位置:  开发笔记 > 人工智能 > 正文

使用带AVR Micro控制器的旋转编码器

如何解决《使用带AVRMicro控制器的旋转编码器》经验,为你挑选了2个好方法。

我无法让旋转编码器与AVR微控制器一起正常工作.编码器是机械ALPS编码器,我使用的是Atmega168.

澄清

我曾尝试使用外部中断来收听引脚,但看起来它太慢了.当引脚A变为高电平时,中断程序开始,然后检查引脚B是否为高电平.我们的想法是,如果引脚B变高,引脚A变高,那么它就会逆时针旋转.如果引脚B为低电平,则它按顺时针方向旋转.但似乎AVR检查引脚B需要太长时间,所以它总是读得很高.

我还尝试创建一个程序,只需阻塞直到引脚B或引脚A发生变化.但可能是旋转编码器时噪音太大,因为这也不起作用.我的最后一次尝试是有一个计时器,它将最后8个值存储在缓冲区中,并检查它是否从低到高.这也不起作用.

我已经尝试过对编码器进行范围设计,它似乎在第一个Pin的2到4ms之间使用,直到另一个Pin发生变化.



1> Adam Davis..:

我有一个关于旋转编码器的网页以及如何使用它们,你可能会发现它们很有用.

很遗憾没有更多信息我无法解决您的特定问题.

哪些微控制器引脚连接到编码器,您目前用于解码脉冲的代码是什么?

好吧,你正在处理一些不同的问题,第一个问题是这是一个机械编码器,所以你必须处理开关噪声(反弹,颤振).该数据表指示它可能需要最多3毫秒的零件停止跳动和创建虚假输出.

你需要创建一个去抖动例程.最简单的是不断检查A是否变高.如果是,请启动计时器并在3 ms内再次检查.如果它仍然很高,那么你可以检查B - 如果它不高,那么你忽略了假脉冲并继续寻找A高.当你检查B时,你看它,启动一个3毫秒的计时器,然后再看看B. 如果两次都相同,则可以使用该值 - 如果它在3 ms内发生变化,则必须再次执行此操作(读取B,等待3 ms,然后再次读取它,看它是否匹配).

atmega足够快,你不必担心这些检查会慢慢进行,除非你的时钟速度很慢.

一旦你处理了机械噪声,那么你想看一个正确的灰色代码例程 - 你所遵循的算法将无法工作,除非你在A变低时A减小时减少.通常人们存储两个输入的最后一个值,然后将它与两个输入的新值进行比较,并使用一个小函数根据该值递增或递减.(请查看我在上面提到的表格中的"高分辨率阅读"标题).我将两个读数组合成一个四位数,并使用一个简单的数组告诉我是否增加或减少计数器,但有更高级的解决方案,并优化代码大小,速度或代码维护的简易性.



2> Marius..:

添加模拟低通滤波器可大大改善信号.使用低通滤波器,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连接到avr上的输入PORTB:

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

除非您快速旋转编码器,否则此代码有效.然后它可能会错过一两步,但这并不重要,因为使用编码器的人不会知道他们转了多少步.


但是,硬件解决方案的优点在于它为用户提供了额外的ESD保护.当然,并没有针对这一点进行优化,而是一点奖励.
推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有