Micropython学习交流群 学习QQ群:786510434 提供多种固件下载和学习交流。
Micropython-扇贝物联 QQ群:31324057 扇贝物联是一个让你与智能设备沟通更方便的物联网云平台
Micropython学习交流群 学习QQ群:468985481 学习交流ESP8266、ESP32、ESP8285、wifi模块开发交流、物联网。
Micropython老哥俩的IT农场分享QQ群:929132891 为喜欢科创制作的小白们分享一些自制的计算机软硬件免费公益课程,由两位多年从事IT研发的中年大叔发起。
旋转编码器
库1:
import machine import utime as time from machine import Pin import micropython class Rotary: ROT_CW = 1 ROT_CCW = 2 SW_PRESS = 4 SW_RELEASE = 8 def __init__(self,dt,clk,sw): self.dt_pin = Pin(dt, Pin.IN) self.clk_pin = Pin(clk, Pin.IN) self.sw_pin = Pin(sw, Pin.IN) self.last_status = (self.dt_pin.value() << 1) | self.clk_pin.value() self.dt_pin.irq(handler=self.rotary_change, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING ) self.clk_pin.irq(handler=self.rotary_change, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING ) self.sw_pin.irq(handler=self.switch_detect, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING ) self.handlers = [] self.last_button_status = self.sw_pin.value() def rotary_change(self, pin): new_status = (self.dt_pin.value() << 1) | self.clk_pin.value() if new_status == self.last_status: return transition = (self.last_status << 2) | new_status try: if transition == 0b1110: micropython.schedule(self.call_handlers, Rotary.ROT_CW) elif transition == 0b1101: micropython.schedule(self.call_handlers, Rotary.ROT_CCW) except: pass self.last_status = new_status def switch_detect(self,pin): if self.last_button_status == self.sw_pin.value(): return self.last_button_status = self.sw_pin.value() if self.sw_pin.value(): micropython.schedule(self.call_handlers, Rotary.SW_RELEASE) else: micropython.schedule(self.call_handlers, Rotary.SW_PRESS) def add_handler(self, handler): self.handlers.append(handler) def call_handlers(self, type): for handler in self.handlers: handler(type)
main.py
from rotary import Rotary import utime as time rotary = Rotary(2,1,0) val = 0 def rotary_changed(change): global val if change == Rotary.ROT_CW: val = val + 1 print(val) elif change == Rotary.ROT_CCW: val = val - 1 print(val) elif change == Rotary.SW_PRESS: print('PRESS') elif change == Rotary.SW_RELEASE: print('RELEASE') rotary.add_handler(rotary_changed) while True: time.sleep(999)
库2:
# encoder.py Asynchronous driver for incremental quadrature encoder. # Copyright (c) 2021-2022 Peter Hinch # Released under the MIT License (MIT) - see LICENSE file # Thanks are due to @ilium007 for identifying the issue of tracking detents, # https://github.com/peterhinch/micropython-async/issues/82. # Also to Mike Teachman (@miketeachman) for design discussions and testing # against a state table design # https://github.com/miketeachman/micropython-rotary/blob/master/rotary.py import uasyncio as asyncio from machine import Pin class Encoder: def __init__(self, pin_x, pin_y, v=0, div=1, vmin=None, vmax=None, mod=None, callback=lambda a, b : None, args=(), delay=20): self._pin_x = pin_x self._pin_y = pin_y self._x = pin_x() self._y = pin_y() self._v = v * div # Initialise hardware value self._cv = v # Current (divided) value self.delay = delay # Pause (ms) for motion to stop/limit callback frequency if ((vmin is not None) and v < vmin) or ((vmax is not None) and v > vmax): raise ValueError('Incompatible args: must have vmin <= v <= vmax') self._tsf = asyncio.ThreadSafeFlag() trig = Pin.IRQ_RISING | Pin.IRQ_FALLING try: xirq = pin_x.irq(trigger=trig, handler=self._x_cb, hard=True) yirq = pin_y.irq(trigger=trig, handler=self._y_cb, hard=True) except TypeError: # hard arg is unsupported on some hosts xirq = pin_x.irq(trigger=trig, handler=self._x_cb) yirq = pin_y.irq(trigger=trig, handler=self._y_cb) asyncio.create_task(self._run(vmin, vmax, div, mod, callback, args)) # Hardware IRQ's. Duration 36μs on Pyboard 1 ~50μs on ESP32. # IRQ latency: 2nd edge may have occured by the time ISR runs, in # which case there is no movement. def _x_cb(self, pin_x): if (x := pin_x()) != self._x: self._x = x self._v += 1 if x ^ self._pin_y() else -1 self._tsf.set() def _y_cb(self, pin_y): if (y := pin_y()) != self._y: self._y = y self._v -= 1 if y ^ self._pin_x() else -1 self._tsf.set() async def _run(self, vmin, vmax, div, mod, cb, args): pv = self._v # Prior hardware value pcv = self._cv # Prior divided value passed to callback lcv = pcv # Current value after limits applied plcv = pcv # Previous value after limits applied delay = self.delay while True: await self._tsf.wait() await asyncio.sleep_ms(delay) # Wait for motion to stop. hv = self._v # Sample hardware (atomic read). if hv == pv: # A change happened but was negated before continue # this got scheduled. Nothing to do. pv = hv cv = round(hv / div) # cv is divided value. if not (dv := cv - pcv): # dv is change in divided value. continue # No change lcv += dv # lcv: divided value with limits/mod applied lcv = lcv if vmax is None else min(vmax, lcv) lcv = lcv if vmin is None else max(vmin, lcv) lcv = lcv if mod is None else lcv % mod self._cv = lcv # update ._cv for .value() before CB. if lcv != plcv: cb(lcv, lcv - plcv, *args) # Run user CB in uasyncio context pcv = cv plcv = lcv def value(self): return self._cv
main.py
# encoder_test.py Test for asynchronous driver for incremental quadrature encoder. # Copyright (c) 2021-2022 Peter Hinch # Released under the MIT License (MIT) - see LICENSE file from machine import Pin import uasyncio as asyncio import encoder px = Pin(1, Pin.IN, Pin.PULL_UP) py = Pin(2, Pin.IN, Pin.PULL_UP) def cb(pos, delta): print(pos, delta) async def main(): while True: await asyncio.sleep(1) def test(): print('Running encoder test. Press ctrl-c to teminate.') enc = encoder.Encoder(px, py, v=5, vmin=0, vmax=100, callback=cb) try: asyncio.run(main()) except KeyboardInterrupt: print('Interrupted') finally: asyncio.new_event_loop() test()
来源:https://jd3096.blog.csdn.net/article/details/128311589?spm=1001.2014.3001.5502
Copyright © 2014 ESP56.com All Rights Reserved
执行时间: 0.0084099769592285 seconds