circuitpython与micropython部分差别(劝退攻略)

circuitpython虽然说是基于micropython,但是实际上与micropython有很大的区别,在此记录一下蛋疼的点以及对应应对方案:
 

1)基础包不一样,没有machine,改用了microcontroller,其他的模块也是,造成micropython的代码在circuitpython里几乎无法运行。这叫什么基于micropython,完全已经改头换面了。。。

2)PIN接口不一样,无法根据参数指定PIN,我写了一段代码,根据名称将int值和PIN做了对应:

import sys
import gc

CIRCUIT: bool = (sys.implementation.name == 'circuitpython')   # 是否circuitpython

if CIRCUIT:
    # circuitpython的IO映射
    import microcontroller
    iomapper: dict[int, microcontroller.Pin] = {}

    for pin_str in dir(microcontroller.pin):
        pin = getattr(microcontroller.pin, pin_str)
        if isinstance(pin, microcontroller.Pin):
            iomapper[int(pin_str[4:])] = pin

然后iomapper[10]即获取到IO10
3)SPI、I2C使用不一样:

使用另外的接口了

4)键盘模块不一样,虽然做了简单的包装,但是完全把中断的接口屏蔽并封装了,重新包装一下,勉强还是可以用。之前的键盘模块整合circuitpython后的代码:
 

from lib.epui import *
import time

if CIRCUIT:
    from microcontroller import Pin
else:
    from machine import Pin

"""
micropython switch check module
By @Jim 2023-2025
"""

class BaseSwitchButton:
    """
    按钮接口
    支持防抖及持续按的按键检测模块
    """
    def check_continuous(self):
        """
        检测是否在持续按下
        :return:
        """
        pass

    def pull_state(self) -> tuple(bool, bool):
        """
        拉取状态
        :return: (期间是否被按下,是否被持续按下)
        """
        return (None, None)

if CIRCUIT:
    import lib.adafruit_ticks as adafruit_ticks
    import keypad

    class CSwitchButton(BaseSwitchButton):
        """Switch Button Class
        支持防抖及持续按的按键检测模块Circuitpython
        """

        continuous_period = 1000  # 连续按多少秒进入持续触发

        pins: list[Pin] = []
        buttons = []

        def __init__(self, pin_num: int):
            self.__pressed = False
            self.__continuous = False
            self.__press_tick = 0
            self.__stat_on = False  # 是否按下状态

            self.pin = iomapper[pin_num]
            if self.pin is None:
                raise ValueError(f'pin number {pin_num} not available')
            self.key_number = len(CSwitchButton.pins)
            CSwitchButton.pins.append(self.pin)
            CSwitchButton.buttons.append(self)

        @classmethod
        def init_keypad(cls):
            CSwitchButton.keys = keypad.Keys(tuple(CSwitchButton.pins), value_when_pressed=False, pull=True)

        @classmethod
        def sync_button(cls):
            while True:     # 拉取所有的状态
                event = CSwitchButton.keys.events.get()
                if event is None:
                    break
                button = CSwitchButton.buttons[event.key_number]
                if event.pressed:
                    button.__pressed = True  # 记录有按下
                    button.__press_tick = event.timestamp
                    button.__stat_on = True
                if event.released:
                    button.__stat_on = False

        def check_continuous(self):
            if self.__stat_on:     # 按下
                if adafruit_ticks.ticks_diff(adafruit_ticks.ticks_ms(), self.__press_tick) > CSwitchButton.continuous_period:
                    self.__continuous = True
                    self.__pressed = True

        def pull_state(self) -> tuple(bool, bool):
            result = (self.__pressed, self.__continuous)
            self.__pressed = False
            self.__continuous = False
            return result
else:   # micropython
    import machine
    class MSwitchButton(BaseSwitchButton):
        """Switch Button Class
        支持防抖及持续按的按键检测模块Micropython
        """

        continuous_period = 1000  # 连续按多少秒进入持续触发
        throttle_ms = 400    # 坑爹会触发多次,做一下节流

        def __init__(self, pin: Pin):
            """
            :param pin:
            """
            self.__pin = pin
            self.__pin.irq(handler=self.__switch_change, trigger=Pin.IRQ_FALLING)  # 下降沿触发

            self.__pressed = False
            self.__continuous = False
            self.__press_tick = 0

        def __switch_change(self, _):
            if time.ticks_diff(time.ticks_ms(), self.__press_tick) < MSwitchButton.throttle_ms:   # throttle
                return
            self.__pressed = True
            self.__press_tick = time.ticks_ms()
            self.__continuous = False

        def check_continuous(self):
            if self.__pin.value() == 0:     # 按下
                if time.ticks_diff(time.ticks_ms(), self.__press_tick) > MSwitchButton.continuous_period:
                    self.__continuous = True
                    self.__pressed = True

        def pull_state(self) -> tuple(bool, bool):
            result = (self.__pressed, self.__continuous)
            self.__pressed = False
            self.__continuous = False
            return result

        def sleep(self):    # 休眠irq
            self.__pin.irq(trigger=0)

        def awake(self):
            self.__pin.irq(handler=self.__switch_change, trigger=Pin.IRQ_FALLING)  # 下降沿触发

if __name__ == '__main__':
    my_switch = CSwitchButton(12) if CIRCUIT else MSwitchButton(Pin(2, Pin.IN, Pin.PULL_UP))
    if CIRCUIT:
        CSwitchButton.init_keypad()

    print('start')
    while True:
        if CIRCUIT:
            CSwitchButton.sync_button()
        my_switch.check_continuous()
        pressed = continuous = False
        if not CIRCUIT:
            irq_state = machine.disable_irq()
        [pressed, continuous] = my_switch.pull_state()
        if CIRCUIT:
            time.sleep(0.1)
        else:
            machine.enable_irq(irq_state)
            time.sleep_ms(100)

        if pressed:
            print(f'OK 被{"持续按下" if continuous else "按下"}')

4)没有协程模块。这个没有打包在固件里,但是单独有py代码提供,看了下,似乎勉强能用:

https://github.com/adafruit/Adafruit_CircuitPython_asyncio/tree/main

5)没有framebuffer。这个没有打包在固件里,也有单独的py代码

GitHub - adafruit/Adafruit_CircuitPython_framebuf: CircuitPython framebuf module, based on the Python framebuf module

但是……这个模块是用python重新实现的,居然没实现blit,这个最能提升性能的块拷贝居然没有。。。OMG

好吧,没有也没关系,大不了咱从micropython去搬,请看相关文章《编译带smartconfig、framebuffer的circuitpython》

你可能感兴趣的:(python,circuitpython,micropython)