Micropython下采用非中断(循环扫描)模式驱动EC11旋钮

0.前言

EC11是一种常用的旋转编码器,在小型设备中用的很多。

网上有很多该旋转编码器的micropython版本驱动,但大多采用中断方式。在程序比较小时,中断方式还是可用的,但是如果程序逻辑比较复杂,采用中断方式就会带来程序时序逻辑控制困难等问题。

本文提供了一种采用周期扫描,而不是中断的驱动方式。

1.编码器简单介绍

EC11的样子如图,共有5个脚,一侧3脚,一侧2脚。 2脚的一侧是可以按下的按钮,3脚的一侧是旋转编码脚。

使用时,把3脚侧的中间脚接地,两个边上的引脚一个取名为CLK,另一个取名为DATA,均用10k电阻上拉,并且并联一个104的电容对地消抖。2脚侧的其中1个脚接地,另一个取名叫KEY,同样加上拉和电容。电路如下:

旋转时,其CLK和DAT脚输出时序如下:

2.驱动程序

驱动程序封装为一个单独文件,定义2个类:EC11Var和EC11Process。

EC11Var用于子线程与主程序间传递键值信息,EC11Process是扫描程序。

'''
EC11旋转编码器处理程序
By:fat0x 2023/3/17

旋转读取原理:
不断扫描CLK引脚状态,在CLK引脚下降沿读取DATA状态,从而判断旋转。
CLK和DATA并不严格区分,如果发现左右转反了,把线换一下或者调换本程序中EC11Value返回的2和3的位置即可


本程序采用扫描的方式来读取EC11的动作,并没有采取中断方式。原因是读取EC11的动作时耗时比较长(因为要做按键消抖)
几十毫秒的中断处理时间极有可能导致CPU因为WDT超时重启。
如果采取只在中断处理函数中置中断标志位,动作判断交给主程序的话,也会导致主程序运行不流畅,用户图形界面卡顿问题。
因此,本程序采用了多线程的方式,单独启动一个EC11动作扫描的进程,独立于主程序运行,并向主程序传递动作信息EC11Var.EC11Value。
主程序中不断判断EC11Var.EC11Value的值,并采取相应动作即可。


使用本类时注意:
1.要先定义一个EC11Var类实例,在定义EC11Process实例时
将其传递给EC11Process实例,用于EC11Process里向主程序传递按键和旋转信息;

2.按键定义:EC11Var.EC11Value=0时无动作,=1为按钮按下,=2为右旋转,=3为左旋转。
主程序处理按键的事务后,要将EC11Var.EC11Value重新赋值为0,否则将会重复进入按键处理。
见最后示例程序。
'''
from machine import Pin
import time,machine
import _thread

class EC11Var:
    def __init__(self):
        self.EC11Value=0x00


class EC11Process:
    def __init__(self,pinNumClk,pinNumData,pinNumKey,insEC11Var):
        self.ECPin_Clk  = Pin(pinNumClk,Pin.IN,Pin.PULL_UP)
        self.ECPin_Data = Pin(pinNumData, Pin.IN, Pin.PULL_UP)
        self.ECPin_Key  = Pin(pinNumKey,  Pin.IN, Pin.PULL_UP)
        self.insEC11Var=insEC11Var
        

    def EC_ReadValue(self):
        while True:
            if self.ECPin_Key.value() == 0x00:
                #先判断是否是按钮按下。如果是按下状态并有旋转动作,则只会处理按下动作,不会处理旋转动作
                #一般人也不会采取这种非常规的动作....
                #print("key pressed!")
                time.sleep_ms(50)#延时消抖
                if self.ECPin_Key.value() != 0x00:
                    print("EC11按键-抖动")
                    return
                i=1000000
                while(self.ECPin_Key.value()==0 and i>0):
                    #等待引脚返回高电平(按钮释放)
                    #同时防止旋转按钮卡住或不到位导致程序卡死
                    i-=1
                if i==0:
                    print("EC11按键-卡涩超时")
                    self.insEC11Var.EC11Value=0x00
                self.insEC11Var.EC11Value=0x01
                #print(self.clsEC11Value.EC11Value)
                return
            elif self.ECPin_Clk.value() == 0x00:
                if self.ECPin_Clk.value() != 0x00:#重复检测一次防抖
                    print("EC11旋转-抖动")
                    return
                if self.ECPin_Data.value()==0:
                    #print("EC11右转!")
                    self.insEC11Var.EC11Value=0x03
                elif self.ECPin_Data.value()==1:
                    #print("EC11左转")
                    self.insEC11Var.EC11Value=0x02
                else:
                    print("EC11旋转-检测错误!")
                
                i=1000000
                while((self.ECPin_Data.value()==0 and i>0) or (self.ECPin_Clk.value()==0 and i>0)):
                    #等待CLK和DATA引脚都返回高电平,才是旋转一格结束
                    #同时防止旋转按钮卡住或不到位导致程序卡死
                    i-=1
                if i==0:
                    print("EC11旋转-卡涩超时")
                    self.insEC11Var.EC11Value=0x00
      





'''
以下是示例程序
'''

#示例程序先在主程序前定义EC11扫描的线程程序
def thread_EC_ReadValue(insEC11Process):
    while True:
        insEC11Process.EC_ReadValue()




if __name__ == "__main__":
    insEC11Var         =EC11Var()
    insEC11Process     =EC11Process(18,19,23,insEC11Var)#Pin18=clk,19=data,23=key

    print("EC11示例程序启动...")

    PerPwrPin=Pin(25,Pin.OUT)#开启EC11电源,你的板子如果没有电源控制,删掉即可
    PerPwrPin(1)
    
    _thread.start_new_thread(thread_EC_ReadValue,(insEC11Process,))#启动EC11扫描程序
    while True:
        if insEC11Var.EC11Value!=0x00:
            print("insEC11Var.EC11Value=",insEC11Var.EC11Value)
            insEC11Var.EC11Value=0
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值