From bbaa6587c5e90509d2cfdb57d4b245d48e3969e1 Mon Sep 17 00:00:00 2001 From: dahanzimin <353767514@qq.com> Date: Wed, 13 Nov 2024 15:29:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0MPY=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=BA=93=E4=BC=98=E5=8C=96=EF=BC=8C=E5=8F=8A=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=BE=AE=E6=B3=A2=E9=9B=B7=E8=BE=BE=EF=BC=8C=E8=AF=AD=E9=9F=B3?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../micropython/origin/build/lib/cbr817.py | 112 +++++++++++++++++ .../micropython/origin/build/lib/gnss.py | 32 +++-- .../micropython/origin/build/lib/ns9300.py | 117 ++++++++++++++++++ .../origin/build/lib/oled128x64.py | 9 +- .../micropython/origin/build/lib/rtctime.py | 90 +++++++------- .../micropython/origin/build/lib/sonar.py | 56 ++++++--- .../micropython/origin/build/lib/ssd1106.py | 21 ++-- 7 files changed, 343 insertions(+), 94 deletions(-) create mode 100644 boards/default_src/micropython/origin/build/lib/cbr817.py create mode 100644 boards/default_src/micropython/origin/build/lib/ns9300.py diff --git a/boards/default_src/micropython/origin/build/lib/cbr817.py b/boards/default_src/micropython/origin/build/lib/cbr817.py new file mode 100644 index 00000000..f711bcfd --- /dev/null +++ b/boards/default_src/micropython/origin/build/lib/cbr817.py @@ -0,0 +1,112 @@ +""" +CBR817 + +MicroPython library for the CBR817 (Microwave radar sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from machine import Pin +from micropython import const + +CBR_ADDRESS = const(0x71) +CBR_OP_SET = const(0x02) +CBR_TX_RF = const(0x03) +CBR_POWER = const(0x04) +CBR_LIGHT = const(0x0B) +CBR_REG_CTR1 = const(0X13) +CBR_SENSOR_THR = const(0X18) +CBR_NOISE_THR = const(0X1A) +CBR_TRIGER = const(0x1C) +CBR_DELAY_TIM = const(0X1D) +CBR_LOCK_TIM = const(0X20) +CBR_SEL_REG = const(0x23) +CBR_REG_CTR2 = const(0X24) +CBR_FILTER = const(0x2A) +CBR_RESULT = const(0x81) + +class CBR817: + def __init__(self, i2c_bus, addr=CBR_ADDRESS, tx_power=3, threshold=5000, noise=256, delay=500, lock=500): + self._device = i2c_bus + self._address = addr + _str_i2c = str(self._device) + self._scl = Pin(int(_str_i2c[_str_i2c.find('=') + 1 : _str_i2c.find(",")]), Pin.OUT, Pin.OPEN_DRAIN) + + self._wake() + self._configure() + self.tx_power(tx_power) + self.threshold(threshold) + self.noise(noise) + self.delay_ms(delay) + self.lock_ms(lock) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address, reg, val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes <= 1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _wake(self): + '''Wake up from low power consumption''' + self._scl.value(0) + time.sleep_us(10) + + def threshold(self, value=None): + if value is None: + return self._rreg(CBR_SENSOR_THR) | self._rreg(CBR_SENSOR_THR + 1) << 8 + else: + self._wreg(CBR_SENSOR_THR, value & 0xFF) + self._wreg(CBR_SENSOR_THR + 1, (value >> 8) & 0xFF) + + def noise(self, value=None): + if value is None: + return self._rreg(CBR_NOISE_THR) | self._rreg(CBR_NOISE_THR + 1) << 8 + else: + self._wreg(CBR_NOISE_THR, value & 0xFF) + self._wreg(CBR_NOISE_THR + 1, (value >> 8) & 0xFF) + + def delay_ms(self, value=None): + if value is None: + return round((self._rreg(CBR_DELAY_TIM) | self._rreg(CBR_DELAY_TIM + 1) << 8 | self._rreg(CBR_DELAY_TIM + 2) << 16) / 32) + else: + value = value * 32 + self._wreg(CBR_DELAY_TIM, value & 0xFF) + self._wreg(CBR_DELAY_TIM + 1, (value >> 8) & 0xFF) + self._wreg(CBR_DELAY_TIM + 2, (value >> 16) & 0xFF) + + def lock_ms(self, value=None): + if value is None: + return round((self._rreg(CBR_LOCK_TIM) | self._rreg(CBR_LOCK_TIM + 1) << 8 | self._rreg(CBR_LOCK_TIM + 2) << 16) // 32) + else: + value = value * 32 + self._wreg(CBR_LOCK_TIM, value & 0xFF) + self._wreg(CBR_LOCK_TIM + 1, (value >> 8) & 0xFF) + self._wreg(CBR_LOCK_TIM + 2, (value >> 16) & 0xFF) + + def tx_power(self, value=None): + if value is None: + return self._rreg(CBR_TX_RF) & 0x07 + else: + self._wreg(CBR_TX_RF, (value & 0x07) | 0x30) + + def _configure(self): + self._wreg(CBR_SEL_REG, 0xC0) #唤醒射频芯片 + _star = time.ticks_ms() + while self._rreg(CBR_SEL_REG) != 0xC0: + self._wreg(CBR_SEL_REG, 0xC0) + time.sleep_us(10) + if time.ticks_diff(time.ticks_ms(), _star) >= 200: + raise AttributeError("Cannot find a CBR817") + self._wreg(CBR_TRIGER, 0x55) #连续检测 + self._wreg(CBR_LIGHT, 0x12) #关闭光敏 + self._wreg(CBR_POWER, 0xA0) #功耗全供电 + self._wreg(CBR_FILTER, 0x0F) #打开滤波器 + self._wreg(CBR_OP_SET, 0x5C) #单运放,0.5uA电流 + self._wreg(CBR_REG_CTR1, 0X61) #感应门限和噪声门限改寄存器控制 + self._wreg(CBR_REG_CTR2, 0X60) #延时时间和闭锁时间改寄存器控制 + + def result(self): + self._wake() + return bool(self._rreg(CBR_RESULT) & 0x20) diff --git a/boards/default_src/micropython/origin/build/lib/gnss.py b/boards/default_src/micropython/origin/build/lib/gnss.py index 20751cdf..dd4786c3 100644 --- a/boards/default_src/micropython/origin/build/lib/gnss.py +++ b/boards/default_src/micropython/origin/build/lib/gnss.py @@ -3,20 +3,20 @@ GNSS Micropython library for the GNSS(NMEA0183/GPS,DBS) ======================================================= - -#Preliminary composition 20230314 - @dahanzimin From the Mixly Team """ +from time import sleep_ms from ubinascii import unhexlify class NMEA0183: def __init__(self, uart, baudrate=9600, timeout=200): self._uart=uart self._uart.init(baudrate=baudrate, timeout=timeout, rxbuf=1024) - self.time=[None, None, None, None, None, None, None, 0] - self.locate=['', None, '', None, None, None, None] #0'1经度,2'3纬度,4海拔m,5速度m/s,6航向° - self.status=[False, ' ', 0] #有效标注,定位模式,卫星量 + self.time=[None, None, None, None, None, None] + self.locate=['', None, '', None, None, None, None] #0'1经度,2'3纬度,4海拔m,5速度m/s,6航向° + self.status=[False, ' ', 0] #有效标注,定位模式,卫星量 + if not self._chip_id(): + raise AttributeError("Cannot find a GNSS device") def _crc8(self, buffer): '''对数据进行CRC校验''' @@ -25,6 +25,14 @@ class NMEA0183: crc ^= byte return crc & 0xff + def _chip_id(self): + for _ in range(10): + sleep_ms(300) + if self.any(): + self._uart.write(("$PCAS02,1000*2E\r\n").encode()) #更新频率1HZ + self._uart.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n".encode()) #只加载GNGGA和GNRMC + return True + def _judge(self, buffer, dlen): try: data=buffer.strip().decode().split(',') @@ -43,9 +51,9 @@ class NMEA0183: flag_gga,data=self._judge(_data, 15) #print("GGA----",flag_gga) if flag_gga: - self.time[4]= int(data[1][0:2]) if data[1] else None - self.time[5]= int(data[1][2:4]) if data[1] else None - self.time[6]= int(data[1][4:6]) if data[1] else None + self.time[3]= int(data[1][0:2]) if data[1] else None + self.time[4]= int(data[1][2:4]) if data[1] else None + self.time[5]= int(data[1][4:6]) if data[1] else None self.locate[0]= data[5] self.locate[1]= int(data[4][:3])+int(data[4][3:].replace('.',''))/6000000 if data[4] else None self.locate[2]= data[3] @@ -60,9 +68,9 @@ class NMEA0183: self.time[0]= int(data[9][4:6])+2000 if data[9] else None self.time[1]= int(data[9][2:4]) if data[9] else None self.time[2]= int(data[9][0:2]) if data[9] else None - self.time[4]= int(data[1][0:2])+8 if data[1] else None - self.time[5]= int(data[1][2:4]) if data[1] else None - self.time[6]= int(data[1][4:6]) if data[1] else None + self.time[3]= int(data[1][0:2])+8 if data[1] else None + self.time[4]= int(data[1][2:4]) if data[1] else None + self.time[5]= int(data[1][4:6]) if data[1] else None self.locate[0]= data[6] self.locate[1]= int(data[5][:3])+int(data[5][3:].replace('.',''))/6000000 if data[5] else None self.locate[2]= data[4] diff --git a/boards/default_src/micropython/origin/build/lib/ns9300.py b/boards/default_src/micropython/origin/build/lib/ns9300.py new file mode 100644 index 00000000..3bd5a6e3 --- /dev/null +++ b/boards/default_src/micropython/origin/build/lib/ns9300.py @@ -0,0 +1,117 @@ +""" +NS9300 + +Micropython library for the NS9300(Music Player) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_PLAY_CTRL = const(0x04) +_PLAY_VOL = const(0x06) +_PLAY_INS = const(0x09) +_PLAY_MODE = const(0x0B) + +class NS9300: + def __init__(self, uart, delay=250): + self._uart = uart + self._delay = delay + self._uart.init(baudrate=9600, timeout_char=5) + if not self._chip_id(): + raise AttributeError("Cannot find a NS930x") + + def _wreg(self, cmd, data=b'\x00'): + '''Write memory address''' + _buf = bytearray([cmd, 255 - cmd, len(data)]) + data + eec = 0 + for i in range(len(_buf)): + eec += _buf[i] + _buf.append(eec & 0xFF) + #print("TX:", bytes(_buf), len(_buf)) + self._uart.write(_buf) + + def _rreg(self, cmd): + '''read memory address''' + time.sleep_ms(self._delay) + if self._uart.any(): + _buf = self._uart.read() + #print("RX:", _buf, len(_buf)) + if _buf[0] == 0xAA and _buf[1] == 0x55: + raise OSError("Play Error", _buf[4]) + elif _buf[0] == cmd and _buf[0] == (255 - _buf[1]): + #eec = 0 + #for i in range(len(_buf) - 1): + #eec += _buf[i] + #if (eec & 0xFF) == _buf[-1]: + return _buf[3:3 + _buf[2]] + + def _chip_id(self): + '''复位指令有问题,暂停止播放态处理''' + for _ in range(10): + self._wreg(_PLAY_CTRL, b'\x03') + if self._rreg(_PLAY_CTRL): + return True + + def _ascll(self, data): + '''获取ASCLL字节,剔除中文''' + _strs='' + for char in data: + _strs += char if ord(char) <= 0xFF else "*" + return _strs.encode() + + def status(self, value=1): + """0已停止? 1播放中? 2已暂停?""" + return self.control(0) == value + + def control(self, value=0): + """0查询(0停止 1播放 2暂停) 1播放 2暂停 3停止 4上一曲 5下一曲 6总曲数 7当前曲""" + self._wreg(_PLAY_CTRL, (value if value <= 5 else value + 7).to_bytes(1, 'little')) + _dat = self._rreg(_PLAY_CTRL) + if _dat: + return _dat[1] if value <= 3 else _dat[1] << 8 | _dat[2] + + def play(self, value='m*.mp3'): + """int播放曲目 str播放文件(*省略,GBK编码MPY不支持)""" + if isinstance(value, int): + self._wreg(_PLAY_CTRL, b'\x06' + value.to_bytes(2, 'big')) + elif isinstance(value, str): + self._wreg(_PLAY_CTRL, b'\x07' + self._ascll(value)) + else: + raise ValueError("Input format error") + _dat = self._rreg(_PLAY_CTRL) + if _dat: + return _dat[1] << 8 | _dat[2] + + def insert(self, value='m*.mp3'): + """int播放曲目 str播放文件(*省略,GBK编码MPY不支持)""" + if isinstance(value, int): + self._wreg(_PLAY_INS, b'\x00\x02' + value.to_bytes(2, 'big')) + elif isinstance(value, str): + self._wreg(_PLAY_INS, b'\x01\x02' + self._ascll(value)) + else: + raise ValueError("Input format error") + time.sleep_ms(self._delay) + + def volume(self, value=None): + """None返回音量 int设置音量(0~30)""" + if value is None: + self._wreg(_PLAY_VOL, b'\x00') + _dat = self._rreg(_PLAY_VOL) + if _dat: + return _dat[1] + else: + value = min(30, max(0, value)) + self._wreg(_PLAY_VOL, b'\x01' + value.to_bytes(1, 'little')) + time.sleep_ms(self._delay) + + def mode(self, value=None): + """0全部循环 1单曲循环 2目录循环 3随机播放 4单曲停止 5顺序播放""" + if value is None: + self._wreg(_PLAY_MODE, b'\x00') + _dat = self._rreg(_PLAY_MODE) + if _dat: + return _dat[1] + else: + self._wreg(_PLAY_MODE, b'\x01' + value.to_bytes(1, 'little')) + time.sleep_ms(self._delay) diff --git a/boards/default_src/micropython/origin/build/lib/oled128x64.py b/boards/default_src/micropython/origin/build/lib/oled128x64.py index d88ab3ad..d47f3673 100644 --- a/boards/default_src/micropython/origin/build/lib/oled128x64.py +++ b/boards/default_src/micropython/origin/build/lib/oled128x64.py @@ -3,15 +3,12 @@ OLED Displays Micropython library for the SSD1106_I2C OLED Displays ======================================================= - -#Preliminary composition 20230412 - -dahanzimin From the Mixly Team +@dahanzimin From the Mixly Team """ from ssd1106 import SSD1106_I2C class OLED(SSD1106_I2C): """A single matrix.""" - def __init__(self, i2c, width=128, height=64, address=0x3c, font_address=0x700000): - super().__init__(width, height, i2c, address) + def __init__(self, i2c, width=128, height=64, address=0x3c, font_address=0x700000, types=0): + super().__init__(width, height, i2c, address, l_offset=0 if types == 0 else -2) self.font(font_address) diff --git a/boards/default_src/micropython/origin/build/lib/rtctime.py b/boards/default_src/micropython/origin/build/lib/rtctime.py index 4c4aa60a..3d44d4bc 100644 --- a/boards/default_src/micropython/origin/build/lib/rtctime.py +++ b/boards/default_src/micropython/origin/build/lib/rtctime.py @@ -1,45 +1,45 @@ -"""RTC Time""" -import gc -from time import * -from machine import RTC -import usocket as socket -import ustruct as struct - -# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 -NTP_DELTA = 3155673600 - -def ntptime(host="pool.ntp.org", utc=28800): - NTP_QUERY = bytearray(48) - NTP_QUERY[0] = 0x1B - addr = socket.getaddrinfo(host, 123)[0][-1] - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - s.settimeout(1) - res = s.sendto(NTP_QUERY, addr) - msg = s.recv(48) - finally: - del addr - s.close() - gc.collect() - val = struct.unpack("!I", msg[40:44])[0] - return gmtime(val - NTP_DELTA + utc) - -# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. -def settime(times): - if isinstance(times, str): - try: - val = eval(times) - if len(val) >= 6: - times=(val[0], val[1], val[2], 0, val[3], val[4], val[5], 0) - else: - raise ValueError("Clock information format error") - except: - raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") - if isinstance(times, tuple): - if 6 <= len(times) <= 8: - RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0)) - else: - raise ValueError("Settime needs a tuple of length 6~8") - -def strtime(): - return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(*localtime()) +"""RTC Time""" +import gc +from time import * +from machine import RTC +import usocket as socket +import ustruct as struct + +# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 +NTP_DELTA = 3155673600 + +def ntptime(host="pool.ntp.org", utc=28800): + NTP_QUERY = bytearray(48) + NTP_QUERY[0] = 0x1B + addr = socket.getaddrinfo(host, 123)[0][-1] + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.settimeout(1) + res = s.sendto(NTP_QUERY, addr) + msg = s.recv(48) + finally: + del addr + s.close() + gc.collect() + val = struct.unpack("!I", msg[40:44])[0] + return gmtime(val - NTP_DELTA + utc) + +# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. +def settime(times): + if isinstance(times, str): + try: + val = eval(times) + if len(val) >= 6: + times=(val[0], val[1], val[2], 0, val[3], val[4], val[5], 0) + else: + raise ValueError("Clock information format error") + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0)) + else: + raise ValueError("Settime needs a tuple of length 6~8") + +def strtime(): + return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(*localtime()) diff --git a/boards/default_src/micropython/origin/build/lib/sonar.py b/boards/default_src/micropython/origin/build/lib/sonar.py index 28fd4106..6b8e6ba4 100644 --- a/boards/default_src/micropython/origin/build/lib/sonar.py +++ b/boards/default_src/micropython/origin/build/lib/sonar.py @@ -1,23 +1,39 @@ -from machine import Pin -import time +""" +CS100/HC-SR04 + +Micropython library for the CS100/HC-SR04(Ultrasonic ranging) +======================================================= +@dahanzimin From the Mixly Team +""" +from time import sleep_us +from machine import Pin, time_pulse_us -# Sonar class Sonar: - def __init__(self, trig, echo): - self.trig=Pin(trig, Pin.OUT) - self.echo=Pin(echo, Pin.IN) + __species = {} + __first_init = True - def checkdist(self): - #trig, echo = Pin(trig, Pin.OUT), Pin(echo, Pin.IN) - self.trig.value(0) - self.echo.value(0) - self.trig.value(1) - time.sleep_us(10) - self.trig.value(0) - while(self.echo.value()==0): - pass - t1 = time.ticks_us() - while(self.echo.value()==1): - pass - t2 = time.ticks_us() - return round(time.ticks_diff(t2, t1) / 10000 * 340 / 2, 2) \ No newline at end of file + def __new__(cls, trig, echo, *args, **kwargs): + if (trig, echo) not in cls.__species.keys(): + cls.__first_init = True + cls.__species[(trig, echo) ] = object.__new__(cls) + return cls.__species[(trig, echo)] + + def __init__(self, trig, echo, max_rang=400): + if self.__first_init: + self.__first_init = False + self.trig = Pin(trig, Pin.OUT, value=0) + self.echo = Pin(echo, Pin.IN) + self.timeout_us = int(max_rang * 2 * 29.1) + + def checkdist(self): + self.trig.value(0) + sleep_us(5) + self.trig.value(1) + sleep_us(10) + self.trig.value(0) + try: + pulse_time = time_pulse_us(self.echo, 1, self.timeout_us) + pulse_time = pulse_time if pulse_time >= 0 else self.timeout_us + return round(pulse_time / 2 / 29.1, 2) # 1cm each 29.1us + except: + return None diff --git a/boards/default_src/micropython/origin/build/lib/ssd1106.py b/boards/default_src/micropython/origin/build/lib/ssd1106.py index ab53625a..a4d2e810 100644 --- a/boards/default_src/micropython/origin/build/lib/ssd1106.py +++ b/boards/default_src/micropython/origin/build/lib/ssd1106.py @@ -3,9 +3,6 @@ SSD1106 library for the SSD1x06 OLED128x64 ======================================================= - -#Preliminary composition 20230412 - @dahanzimin From the Mixly Team """ import uframebuf @@ -34,8 +31,10 @@ SET_PAGE_ADDR1 = const(0xb0) SET_CONTRACT_CTRL = const(0x81) class SSD1106(uframebuf.FrameBuffer_Uincode): - def __init__(self, width, height, external_vcc): + def __init__(self, width, height, external_vcc, l_offset=0, h_offset=0): self._external = external_vcc + self._l_offset = l_offset + self._h_offset = h_offset self._buffer = bytearray((width + 7) // 8 * height) super().__init__(self._buffer, width, height, uframebuf.MONO_VLSB) self.init_display() @@ -78,16 +77,16 @@ class SSD1106(uframebuf.FrameBuffer_Uincode): def show(self): for i in range(0, 8): self.write_cmd(SET_PAGE_ADDR1 + i) - self.write_cmd(SET_COL_ADDR_L + 0) # offset 2 pixels for 128x64 panel - self.write_cmd(SET_COL_ADDR_H + 0) - self.write_data(self._buffer[i*128:(i+1)*128]) # send one page display data + self.write_cmd(SET_COL_ADDR_L + self._l_offset) + self.write_cmd(SET_COL_ADDR_H + self._h_offset) + self.write_data(self._buffer[i * 128:(i + 1) * 128]) #send one page display data class SSD1106_I2C(SSD1106): - def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): + def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False, l_offset=0, h_offset=0): self.i2c = i2c self.addr = addr self.temp = bytearray(2) - super().__init__(width, height, external_vcc) + super().__init__(width, height, external_vcc, l_offset, h_offset) def write_cmd(self, cmd): self.temp[0] = 0x80 @@ -99,14 +98,14 @@ class SSD1106_I2C(SSD1106): self.i2c.writeto(self.addr, tmp+buf) class SSD1106_SPI(SSD1106): - def __init__(self, width, height, spi, dc, cs, external_vcc=False): + def __init__(self, width, height, spi, dc, cs, external_vcc=False, l_offset=0, h_offset=0): self.rate = 10 * 1024 * 1024 dc.init(dc.OUT, value=0) cs.init(cs.OUT, value=1) self.spi = spi self.dc = dc self.cs = cs - super().__init__(width, height, external_vcc) + super().__init__(width, height, external_vcc, l_offset, h_offset) def write_cmd(self, cmd): self.spi.init(baudrate=self.rate, polarity=0, phase=0)