这是编写适用于不同构建的 MicroPython 模块的正确方法吗?
Is this the correct way to write a MicroPython module that works across different builds?
我正在为 I2C 温度传感器 (TMP117) 编写一个模块,优先考虑交叉兼容性。
BBC Micro:bit 和 Raspberry Pi Pico 上的 MicroPython 实现不同 - 一个重要的区别是 I2C 驱动程序的实现方式:
- Pico 使用 machine class 驱动 i2c:
i2c.writeto
- Micro:bit 已经定义了
i2c.write
(与 from microbit import *
绑定)docs
这个简单的命名差异确实会影响兼容性!
到目前为止,我已经找到了一个可行的解决方案,因此我的模块 tmp117.py
可以在两个平台上使用。
在 tmp117.py
中,当传感器 class 初始化时,它会检查 sysname
并声明函数指针 self.i2cWrite
和 self.i2cRead
,它们被分配了适合硬件的定义。
但是,我对 Python 还很陌生,我想我可能犯下了很多暴行,例如。命名空间处理不当或使用不适当的导入占用内存。有人可以评论这种方法是否合适吗?在可伸缩性、不必要的导入、名称空间等方面
main.py
# TMP117 minimal example code
from tmp117 import *
from time import sleep
mySensor = tmp117()
while True:
# Read and print the temperature in various units
tempC = mySensor.readTempC() # Celsius
tempStringC = str(tempC) # convert temperature number to string
print("it's " + tempStringC)
sleep(1)
tmp117.py
# A simple class to read temperature from the TMP117 i2c temperature sensor
# Currently only supports reading temperature in C, F, K. Does not support
# alarms.
# This module has been tested with the following development boards:
# • BBC Micro:bit
# • Raspberry Pi Pico (RP2040)
import os
if os.uname().sysname == 'microbit':
from microbit import *
else: # for Raspberry Pi Pico
from machine import I2C
i2c = I2C(0)
print("Running on " + os.uname().sysname)
# Register definitions
REG_TEMPC = b'\x00'
class tmp117(object):
def __init__(self, addr_=0x48, i2c_=i2c):
if os.uname().sysname == 'microbit':
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.write
self.i2cRead = self.i2c.read
else:
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.writeto
self.i2cRead = self.i2c.readfrom
def readTempC(self):
self.i2cWrite(self.addr, REG_TEMPC)
data = self.i2cRead(self.addr, 2) # returns a bytes object
tempDataRaw = int.from_bytes(data, 'big')
# handle negatives (MicroPython int.from_bytes does not support signed conversion (yet)
if tempDataRaw >= 0x8000:
return -256.0 + (tempDataRaw - 0x8000) * 7.8125e-3 # One LSB equals 7.812 mdegC
else:
return tempDataRaw * 7.8125e-3 # One LSB equals 7.812 mdegC
我选择做同样的事情是定义 _PLATFORM
变量,相应地设置它并在以后使用它:
import os
if os.uname().sysname == 'microbit':
_PLATFORM = 'microbit'
elif os.uname().sysname == 'rpico': # not sure about real value
_PLATFORM = 'pico'
else:
raise Exception('Unsupported platform')
if _PLATFORM == 'microbit':
from microbit import *
elif _PLATFORM == 'pico': # for Raspberry Pi Pico
from machine import I2C
i2c = I2C(0)
print("Running on {}".format(_PLATFORM)) # <<--- use format() function to save RAM
# Register definitions
REG_TEMPC = b'\x00'
class tmp117(object):
def __init__(self, addr_=0x48, i2c_=i2c):
if _PLATFORM == 'microbit':
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.write
self.i2cRead = self.i2c.read
elif _PLATFORM == 'pico':
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.writeto
self.i2cRead = self.i2c.readfrom
def readTempC(self):
self.i2cWrite(self.addr, REG_TEMPC)
data = self.i2cRead(self.addr, 2) # returns a bytes object
tempDataRaw = int.from_bytes(data, 'big')
# handle negatives (MicroPython int.from_bytes does not support signed conversion (yet)
if tempDataRaw >= 0x8000:
return -256.0 + (tempDataRaw - 0x8000) * 7.8125e-3 # One LSB equals 7.812 mdegC
else:
return tempDataRaw * 7.8125e-3 # One LSB equals 7.812 mdegC
我正在为 I2C 温度传感器 (TMP117) 编写一个模块,优先考虑交叉兼容性。
BBC Micro:bit 和 Raspberry Pi Pico 上的 MicroPython 实现不同 - 一个重要的区别是 I2C 驱动程序的实现方式:
- Pico 使用 machine class 驱动 i2c:
i2c.writeto
- Micro:bit 已经定义了
i2c.write
(与from microbit import *
绑定)docs
这个简单的命名差异确实会影响兼容性!
到目前为止,我已经找到了一个可行的解决方案,因此我的模块 tmp117.py
可以在两个平台上使用。
在 tmp117.py
中,当传感器 class 初始化时,它会检查 sysname
并声明函数指针 self.i2cWrite
和 self.i2cRead
,它们被分配了适合硬件的定义。
但是,我对 Python 还很陌生,我想我可能犯下了很多暴行,例如。命名空间处理不当或使用不适当的导入占用内存。有人可以评论这种方法是否合适吗?在可伸缩性、不必要的导入、名称空间等方面
main.py
# TMP117 minimal example code
from tmp117 import *
from time import sleep
mySensor = tmp117()
while True:
# Read and print the temperature in various units
tempC = mySensor.readTempC() # Celsius
tempStringC = str(tempC) # convert temperature number to string
print("it's " + tempStringC)
sleep(1)
tmp117.py
# A simple class to read temperature from the TMP117 i2c temperature sensor
# Currently only supports reading temperature in C, F, K. Does not support
# alarms.
# This module has been tested with the following development boards:
# • BBC Micro:bit
# • Raspberry Pi Pico (RP2040)
import os
if os.uname().sysname == 'microbit':
from microbit import *
else: # for Raspberry Pi Pico
from machine import I2C
i2c = I2C(0)
print("Running on " + os.uname().sysname)
# Register definitions
REG_TEMPC = b'\x00'
class tmp117(object):
def __init__(self, addr_=0x48, i2c_=i2c):
if os.uname().sysname == 'microbit':
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.write
self.i2cRead = self.i2c.read
else:
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.writeto
self.i2cRead = self.i2c.readfrom
def readTempC(self):
self.i2cWrite(self.addr, REG_TEMPC)
data = self.i2cRead(self.addr, 2) # returns a bytes object
tempDataRaw = int.from_bytes(data, 'big')
# handle negatives (MicroPython int.from_bytes does not support signed conversion (yet)
if tempDataRaw >= 0x8000:
return -256.0 + (tempDataRaw - 0x8000) * 7.8125e-3 # One LSB equals 7.812 mdegC
else:
return tempDataRaw * 7.8125e-3 # One LSB equals 7.812 mdegC
我选择做同样的事情是定义 _PLATFORM
变量,相应地设置它并在以后使用它:
import os
if os.uname().sysname == 'microbit':
_PLATFORM = 'microbit'
elif os.uname().sysname == 'rpico': # not sure about real value
_PLATFORM = 'pico'
else:
raise Exception('Unsupported platform')
if _PLATFORM == 'microbit':
from microbit import *
elif _PLATFORM == 'pico': # for Raspberry Pi Pico
from machine import I2C
i2c = I2C(0)
print("Running on {}".format(_PLATFORM)) # <<--- use format() function to save RAM
# Register definitions
REG_TEMPC = b'\x00'
class tmp117(object):
def __init__(self, addr_=0x48, i2c_=i2c):
if _PLATFORM == 'microbit':
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.write
self.i2cRead = self.i2c.read
elif _PLATFORM == 'pico':
self.i2c = i2c_
self.addr = addr_
self.i2cWrite = self.i2c.writeto
self.i2cRead = self.i2c.readfrom
def readTempC(self):
self.i2cWrite(self.addr, REG_TEMPC)
data = self.i2cRead(self.addr, 2) # returns a bytes object
tempDataRaw = int.from_bytes(data, 'big')
# handle negatives (MicroPython int.from_bytes does not support signed conversion (yet)
if tempDataRaw >= 0x8000:
return -256.0 + (tempDataRaw - 0x8000) * 7.8125e-3 # One LSB equals 7.812 mdegC
else:
return tempDataRaw * 7.8125e-3 # One LSB equals 7.812 mdegC