查看: 773|回复: 0

BPI-PicoW-S3 使用增量型旋转编码器[CircuitPython]

[复制链接]

该用户从未签到

发表于 2022-11-30 08:48:30 | 显示全部楼层 |阅读模式
分享到:
BPI-Pico-S3 与 Raspberry Pi Pico 板尺寸相同,搭载ESP32S3芯片,8M flash,4层PCB,电镀半孔工艺,陶瓷天线,支持 2.4 GHz Wi-Fi 和 Bluetooth® LE 双模无线通信,是一款专为物联网开发和Maker DIY设计的开发板。
出厂内置 tinyUF2 + CircuitPython,推荐使用Mu编辑器上手CircuitPython开发。
硬件接口示意图
使用增量型旋转编码器
接线参考
增量型旋转编码器
BPI-PicoW-S3
GNDGND
+VBUS
SW
DTGP0
CLKGP1
  • 增量型旋转编码器外观粗看与一些常见的旋转电位器相似,其关键的不同之处大致分为三点。

    • 微控制器使用ADC外设来读取旋转电位器输出的模拟信号(电压值),确定转轴当前角位;微控制器通过GPIO接收增量型旋转编码器输出的数字信号,可通过软件程序判断信号所对应的转轴动作。
    • 微控制器可在一定精度下,确定旋转电位器转轴当前角位,但因为模拟信号的持续性与抗干扰能力差的原因,无法准确判断它是否有动作;增量型旋转编码器仅在转轴运动到一个触点时,向微控制器发出一段动作数字信号,如果一个增量型旋转编码器一周有20个触点,它旋转一周就触发20次动作信号,微控制器可以精确的判断它是否动作,向哪个方向转动,信号触发了多少次。
    • 旋转电位器通常不可向任意转向进行无限旋转,会停止在最大或最小限位点;增量型旋转编码器可向任意转向进行无限旋转。


  • 增量型旋转编码器采用正交编码器生成其A和B的输出信号。从A和B输出发射的脉冲是正交编码的,这意味着当增量编码器以恒定速度运动时,A和B波形是方波,A和B之间存在90度的相位差。最终A和B信号将从两个管脚传输给微控制器。



  • 理论上,在任何特定时间,对于旋转编码器,A和B信号之间,顺时针旋转的相位差为+90°,逆时针旋转的相位差为−90°,具体则取决于设备内部的正交编码器设计。

  • A或B输出上的脉冲频率与转轴的速度(位置变化率)成正比。较高的频率表示较快的速度,而较低的频率表示较慢的速度。当转轴静止时,静态、不变的信号输出在A和B上,所以有很多测速方案使用增量型旋转编码器。

  • 用CircuitPython设计一个程序读取在GP0与GP1引脚上的信号,当其中一个发生变化时同时输出两个引脚当前的值,连接开发板与增量型旋转编码器后运行程序。



    import board
    import digitalio

    dt = digitalio.DigitalInOut(board.GP0)
    clk = digitalio.DigitalInOut(board.GP1)
    dt.switch_to_input()
    clk.switch_to_input()
    dt_last_value = 0
    clk_last_value = 0

    while True:
        if dt.value != dt_last_value or clk.value != clk_last_value:
            dt_last_value = int(dt.value)
            clk_last_value = int(clk.value)
            print((dt_last_value,clk_last_value))
  • 逐级转动转轴,观察输出信号,如果有逻辑分析仪或示波器也可接入观察。

  • 转轴逆时针旋转时,REPL的输出。

    (1, 1)
    (1, 0)
    (0, 0)
    (0, 1)
    (1, 1)
    (1, 0)
    (0, 0)
    (0, 1)
    (1, 1)
  • 转轴逆时针旋转时,逻辑分析仪所观察到的波形。



  • 转轴顺时针旋转时,REPL的输出。



      (1, 1)
      (0, 1)
      (0, 0)
      (1, 0)
      (1, 1)
      (0, 1)
      (0, 0)
      (1, 0)
      (1, 1)
  • 转轴逆时针旋转时,逻辑分析仪所观察到的波形。




  • 首先可以观察到的现象是,转轴完成一级动作后,两个引脚上的信号都为1,可以设计程序,当值都变为1时输出一次计数值,计数值可作为判断编码器完成一次动作的依据。



    import board
    import digitalio

    dt = digitalio.DigitalInOut(board.GP0)
    clk = digitalio.DigitalInOut(board.GP1)
    dt.switch_to_input()
    clk.switch_to_input()
    dt_last_value = 0
    clk_last_value = 0
    count = 0

    while True:
        if dt.value != dt_last_value or clk.value != clk_last_value:
            dt_last_value = int(dt.value)
            clk_last_value = int(clk.value)
            print((dt_last_value,clk_last_value))
            if (dt_last_value,clk_last_value) == (1,1):
                print('--',count_1,'--')
                count += 1
  • 再确定编码器顺时针旋转与逆时针旋转的动作,在两个引脚上输出的信号变化的规律与差异。

  • 逆时针旋转的规律为(1, 1)>(1, 0)>(0, 0)>(0, 1)>(1, 1)。

  • 顺时针旋转的规律为(1, 1)>(0, 1)>(0, 0)>(1, 0)>(1, 1)。



    由此可设计一个顺时针旋转使计数+1,逆时针旋转使计数-1的程序,并加入消抖除错的功能。
    import board
    import digitalio
    import time
    dt = digitalio.DigitalInOut(board.GP0)
    clk = digitalio.DigitalInOut(board.GP1)
    dt.switch_to_input()
    clk.switch_to_input()
    dt_last_value = 0
    clk_last_value = 0
    count = 0
    start_sign = 0
    clockwise_sign = 0
    while True:
        if dt.value != dt_last_value or clk.value != clk_last_value:
            dt_last_value = int(dt.value)
            clk_last_value = int(clk.value)
            print((dt_last_value,clk_last_value))
            if start_sign == 0 and (dt_last_value,clk_last_value) == (0,0):
                start_sign = 1
            elif start_sign == 1:
                if (dt_last_value,clk_last_value) == (1, 0):
                    clockwise_sign = 1
                elif (dt_last_value,clk_last_value) == (0, 1):
                    clockwise_sign = -1
                elif (dt_last_value,clk_last_value) == (1, 1):
                    count = count + clockwise_sign
                    clockwise_sign = 0
                    start_sign = 0
                    print('--',count,'--')
  • 此程序中的消抖除错功能的实现,并不是逐步判断验证是否符合信号规律,或许还有更多办法可以实现消抖除错,欢迎讨论。

  • 另外 CircuitPython 的rotaryio模块可直接实现正反转计数功能。(内部程序有所差异,但最终实现功能基本一致)。

import rotaryio
import board

encoder = rotaryio.IncrementalEncoder(board.GP0,board.GP1)
last_position = 0

while True:
    position = encoder.position
    if position != last_position:
        print(position)
    last_position = position
购买BPI-PicoW-S3

回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /5 下一条



手机版|小黑屋|与非网

GMT+8, 2024-12-19 12:38 , Processed in 0.106918 second(s), 15 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.