找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2102|回复: 18
打印 上一主题 下一主题
收起左侧

单个旋转编码器旋转时没有问题,但是多个接到单片机上时旋转会有错误?

  [复制链接]
跳转到指定楼层
楼主
ID:985033 发表于 2022-6-7 11:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
单个旋转编码器旋转时没有问题,但是多个接到单片机上时旋转会有错误,有时会自己旋转改变,有大神知道是怎么回事吗?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:883242 发表于 2022-6-7 21:31 | 只看该作者
单片机跟不上旋转编码器运动,丢脉冲了吧。绝对值编码器不会出这种问题,AB相的一定是软件写的不好或者单片机太慢。
回复

使用道具 举报

板凳
ID:390416 发表于 2022-6-7 22:27 | 只看该作者
代码没优化好,
回复

使用道具 举报

地板
ID:161164 发表于 2022-6-8 00:08 | 只看该作者
代码呢?接线图呢?
你猜我猜不猜得到你的问题在哪?
回复

使用道具 举报

5#
ID:985033 发表于 2022-6-8 09:16 | 只看该作者
void Encoder_EC11_Init(void)
{
/***避免上电时EC11旋钮位置不确定导致一次动作误判***/               
                EC11_A1_Now=1;
                EC11_B1_Now=1;       
}

/***********************************************************************
功能描述:编码器旋转方向分析
入口参数:无
返回值:无
***********************************************************************/
void Encoder_EC11_Scan1(void)
{
        if(EC11_A1_Now != EC11_A_Last)   //以A为时钟,B为数据。正转时AB反相,反转时AB同相
        {
                        if(EC11_A1_Now == 0)
                        {
                                if(EC11_B1_Now == 1)      //只需要采集A的上升沿或下降沿的任意一个状态,若A下降沿时B为1,正转
                                        {
                                                printf("\r\n ECll_KEY1_CW \r\n");
                                        }                                                                       
                                        else                    //反转
                                        {
                                                printf("\r\n ECll_KEY1_CCW \r\n");
                                        }
                        }
                       
                        EC11_A_Last = EC11_A1_Now;   //更新编码器上一个状态暂存变量
                        EC11_B_Last = EC11_B1_Now;   //更新编码器上一个状态暂存变量
        }
}

就是单个编码器程序是这样的,旋转没问题,然后多个也是类似这样写,旋转后就会发生误判正转反转,有时也会自己串口显示
回复

使用道具 举报

6#
ID:1033120 发表于 2022-6-8 09:56 | 只看该作者
   这种情况一般是由于安装时固定螺母或锁紧电位器的锁紧螺母过分拧紧,这里给到的建议是在螺母锁紧后,转轴要比螺母表面高出大约lmm以上。
回复

使用道具 举报

7#
ID:985033 发表于 2022-6-8 10:03 | 只看该作者

那应该怎么优化呢
回复

使用道具 举报

8#
ID:985033 发表于 2022-6-8 10:06 | 只看该作者
Hephaestus 发表于 2022-6-7 21:31
单片机跟不上旋转编码器运动,丢脉冲了吧。绝对值编码器不会出这种问题,AB相的一定是软件写的不好或者单片 ...

那软件部分应该怎么优化呢,单个是没问题的,但是单个以上就会这样了
回复

使用道具 举报

9#
ID:161164 发表于 2022-6-8 10:29 | 只看该作者
xyz_city 发表于 2022-6-8 09:16
void Encoder_EC11_Init(void)
{
/***避免上电时EC11旋钮位置不确定导致一次动作误判***/               

EC11_A_Last/EC11_B_Last 不会是共用的吧?

保险一点把EC11_A_Last/EC11_B_Last改为静态变量
  1. void Encoder_EC11_Scan1(void)
  2. {
  3.         static bit EC11_A_Last = EC11_A1_Now, EC11_B_Last = EC11_B1_Now;//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  4.         if(EC11_A1_Now != EC11_A_Last)   //以A为时钟,B为数据。正转时AB反相,反转时AB同相
  5.         {
  6.                         if(EC11_A1_Now == 0)
  7.                         {
  8.                                 if(EC11_B1_Now == 1)      //只需要采集A的上升沿或下降沿的任意一个状态,若A下降沿时B为1,正转
  9.                                         {
  10.                                                 printf("\r\n ECll_KEY1_CW \r\n");
  11.                                         }                                                                       
  12.                                         else                    //反转
  13.                                         {
  14.                                                 printf("\r\n ECll_KEY1_CCW \r\n");
  15.                                         }
  16.                         }
  17.                        
  18.                         EC11_A_Last = EC11_A1_Now;   //更新编码器上一个状态暂存变量
  19.                         EC11_B_Last = EC11_B1_Now;   //更新编码器上一个状态暂存变量
  20.         }
  21. }
复制代码


回复

使用道具 举报

10#
ID:329625 发表于 2022-6-8 10:29 | 只看该作者
建议调整一下代码的逻辑与优先级问题
回复

使用道具 举报

11#
ID:213173 发表于 2022-6-8 10:55 | 只看该作者
xyz_city 发表于 2022-6-8 09:16
void Encoder_EC11_Init(void)
{
/***避免上电时EC11旋钮位置不确定导致一次动作误判***/               

这段代码用于STC15W系列单片机,在快慢手速操作下未见误码。你扩展成多个编码器试试。
  1. void EC11(void)
  2. {
  3.         static unsigned char traitA=0,traitB=0;
  4.         //开关部分代码略
  5.         //......
  6.         //顺时针旋转,每圈进阶20
  7.         if(EC11_B && !EC11_A && traitA==0)          //第一特征码
  8.         {
  9.                 traitA=1;
  10.         }
  11.         else if(!EC11_B && !EC11_A && traitA==1)//第二特征码
  12.         {
  13.                 traitA=2;
  14.         }
  15.         else if(!EC11_B && EC11_A && traitA==2)//第三特征码
  16.         {
  17.                 if(count>0)count--;
  18.                 traitA=3;
  19.         }
  20.         else if(EC11_B && EC11_A && traitA==3)//第四特征码
  21.         {
  22.                 traitA=0;//清0
  23.         }
  24.         //逆时针旋转
  25.         if(!EC11_B && EC11_A && traitB==0)          //第一特征码
  26.         {
  27.                 traitB=1;
  28.         }
  29.         else if(!EC11_B && !EC11_A && traitB==1)//第二特征码
  30.         {
  31.                 traitB=2;
  32.         }
  33.         else if(EC11_B && !EC11_A && traitB==2)//第三特征码
  34.         {
  35.                 if(count<250)count++;
  36.                 traitB=3;
  37.         }
  38.         else if(EC11_B && EC11_A && traitB==3)//第四特征码
  39.         {
  40.                 traitB=0;//清0
  41.         }
  42. }
复制代码

回复

使用道具 举报

12#
ID:887371 发表于 2022-6-11 15:30 | 只看该作者
怎么没有一个采用外中断或端口变化中断做的。
这种方法占用mcu时间极少,适用面广(0~MHz级),极其可靠。
回复

使用道具 举报

13#
ID:161164 发表于 2022-6-11 15:56 来自手机 | 只看该作者
datouyuan 发表于 2022-6-11 15:30
怎么没有一个采用外中断或端口变化中断做的。
这种方法占用mcu时间极少,适用面广(0~MHz级),极其可靠。

愿闻其详
回复

使用道具 举报

14#
ID:451718 发表于 2022-6-11 16:44 | 只看该作者
datouyuan 发表于 2022-6-11 15:30
怎么没有一个采用外中断或端口变化中断做的。
这种方法占用mcu时间极少,适用面广(0~MHz级),极其可靠。

EC11的判断,最好还是丢到 1ms 的定时器中断中去比较稳妥, 哪怕中断级别低点都不是问题。 但是,如果放到外中断 里面去执行,还真没试过。  你不担心按键坏了,程序一直停在中断出不来么?   
回复

使用道具 举报

15#
ID:1018334 发表于 2022-6-11 19:21 | 只看该作者

代码没优化好
回复

使用道具 举报

16#
ID:887371 发表于 2022-6-13 10:13 | 只看该作者

ec11和电机编码器时序是一样的。
假设电机旋转1圈有100个编码器脉冲,电机最大转速3000rpm,每秒编码器脉冲可达6000Hz。用定时扫描中断太频繁了。

  1. //只开启一个引脚变化中断
  2. void p1_change_int(void) interrupt 8
  3. {//
  4.         bit bZZ=0;
  5.         if(PIN_A)
  6.         {
  7.                 if(!PIN_B)
  8.                         bZZ=1;
  9.         }
  10.         else
  11.         {
  12.                 if(PIN_B)
  13.                         bZZ=1;
  14.         }
  15.         if(bZZ)
  16.                 gPosition++;//正传
  17.         else
  18.                 gPosition--;//反转
  19.         INTFLG=0;//清除变化中断
  20. }
  21. /*
  22. 定时分析gPosition变化,可得到EC11的状态
  23. */
复制代码
回复

使用道具 举报

17#
ID:887371 发表于 2022-6-13 10:17 | 只看该作者
robinsonlin 发表于 2022-6-11 16:44
EC11的判断,最好还是丢到 1ms 的定时器中断中去比较稳妥, 哪怕中断级别低点都不是问题。 但是,如果放 ...

不担心。
我的代码,中断中不允许有长耗时操作。
回复

使用道具 举报

18#
ID:514317 发表于 2022-6-15 09:42 | 只看该作者
datouyuan 发表于 2022-6-13 10:13
ec11和电机编码器时序是一样的。
假设电机旋转1圈有100个编码器脉冲,电机最大转速3000rpm,每秒编码器 ...

那是你没试过中断法,你试过就知道了干扰有多严重了,另外EC11和电机编码器不一样的地方是EC11更多干扰。
最好的方法是加电容硬件防抖加定时查询状态机
回复

使用道具 举报

19#
ID:887371 发表于 2022-6-15 13:55 | 只看该作者
lzzasd 发表于 2022-6-15 09:42
那是你没试过中断法,你试过就知道了干扰有多严重了,另外EC11和电机编码器不一样的地方是EC11更多干扰。 ...

我的代码就是中断法,并且是实际使用过的。
该算法天然具备消抖功能。
加电容硬件防抖仅仅是为了减少进入中断的次数,节约mcu开销。主频极低的mcu也能胜任。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表