build(boards): xpython板卡执行 npm run build:prod

This commit is contained in:
王立帮
2026-01-13 15:16:17 +08:00
parent a5fa5034f9
commit 8f4f023ab3
50 changed files with 2166 additions and 744 deletions

View File

@@ -0,0 +1,87 @@
"""
Iamge
MicroPython library for the Iamge(jpeg C module)
=======================================================
@dahanzimin From the Mixly Team
"""
import gc
import urequests
from base64 import b64encode
from jpeg import Encoder, Decoder
class IMG:
def __init__(self, image, width, height):
self.image = image
self.width = width
self.height = height
self.format = "RGB565"
class Image:
def save(self, img, path="mixly.jpg", **kwargs):
'''quality(1-100), rotation (0, 90, 180, 270)'''
_encoder = Encoder(pixel_format="RGB565_BE", width=img.width, height=img.height, **kwargs)
_jpeg = _encoder.encode(img.image)
del _encoder
gc.collect()
if isinstance(path, str):
with open(path, 'wb') as f:
f.write(_jpeg)
else:
return _jpeg
def open(self, path="mixly.jpg", scale_width=None, scale_height=None, tft_width=240, tft_height=240, **kwargs):
'''rotation (0, 90, 180, 270), clipper_width, clipper_height'''
with open(path, "rb") as f:
_jpeg = f.read()
return self._jpg_decoder(_jpeg, scale_width, scale_height, tft_width, tft_height, **kwargs)
def convert(self, img, formats=0, **kwargs):
if formats == 0:
return self.save(img, None, **kwargs)
elif formats == 1:
return b'data:image/jpg;base64,' + b64encode(self.save(img, None, **kwargs))
def download(self, url, path=None, scale_width=None, scale_height=None, tft_width=240, tft_height=240, block=1024, **kwargs):
'''rotation (0, 90, 180, 270), clipper_width, clipper_height'''
response = urequests.get(url, stream=True)
if path is None:
_image = self._jpg_decoder(response.raw.read(), scale_width, scale_height, tft_width, tft_height, **kwargs)
response.close()
return _image
else:
with open(path, 'wb') as f:
while True:
_data = response.raw.read(block)
if not _data:
break
else:
f.write(_data)
response.close()
def _jpg_decoder(self, jpg, scale_width, scale_height, tft_width, tft_height, **kwargs):
'''Automatically zoom based on the screen'''
if scale_width is None or scale_height is None:
_width = tft_width
_height = tft_height
for i in range(min(len(jpg), 1024)):
if jpg[i] == 0xFF and (jpg[i + 1] & 0xF0) == 0xC0:
if jpg[i + 1] not in [0xC4, 0xC8, 0xCC]:
_width = jpg[i + 7] << 8 | jpg[i + 8]
_height = jpg[i + 5] << 8| jpg[i + 6]
break
if _width > tft_width or _height > tft_height:
_scale = max(_width / tft_width, _height / tft_height) * 8
_decoder = Decoder(pixel_format="RGB565_BE", scale_width=round(_width / _scale) * 8, scale_height=round(_height / _scale) * 8, **kwargs)
else:
_decoder = Decoder(pixel_format="RGB565_BE", **kwargs)
else:
_decoder = Decoder(pixel_format="RGB565_BE", scale_width=scale_width // 8 * 8, scale_height=scale_height // 8 * 8, **kwargs)
_info = _decoder.get_img_info(jpg)
_image = IMG(_decoder.decode(jpg), _info[0], _info[1])
del _decoder, jpg
gc.collect()
return _image
#图像处理
Image = Image()

View File

@@ -392,6 +392,17 @@
"__size__": 3049,
"__name__": "icm42670.py"
},
"image": {
"__require__": [
"gc",
"urequests",
"base64",
"jpeg"
],
"__file__": true,
"__size__": 3626,
"__name__": "image.py"
},
"informatio_picture": {
"__require__": [],
"__file__": true,
@@ -689,7 +700,7 @@
"micropython"
],
"__file__": true,
"__size__": 3574,
"__size__": 4305,
"__name__": "pe_g1.py"
},
"pm2_5": {

View File

@@ -1,30 +1,31 @@
"""
PE_G1
Micropython library for the PE_G1(Motor*5*2 & Servo*4)
=======================================================
#Preliminary composition 20230120
Micropython library for
PE_G1 (Motor*5*2 & Servo*4)
MDB (Motor*4*2 & Servo*6)
===============================
@dahanzimin From the Mixly Team
"""
from time import sleep_ms
from micropython import const
_PE_G1_ADDRESS = const(0x25)
_PE_G1_ID = const(0x00)
_PE_G1_VBAT = const(0x01)
_PE_G1_MOTOR = const(0x03)
_PE_G1_SERVO = const(0x0D)
_PE_G1_OFF = const(0x16)
_PE_GX_ADDRESS = const(0x25)
_PE_GX_ID = const(0x00)
_PE_GX_VBAT = const(0x01)
_PE_GX_MOTOR = const(0x03)
class PE_G1:
def __init__(self, i2c_bus, addr=_PE_G1_ADDRESS):
self._i2c=i2c_bus
def __init__(self, i2c_bus, addr=_PE_GX_ADDRESS):
self._i2c = i2c_bus
self._addr = addr
sleep_ms(500)
if self._rreg(_PE_G1_ID)!= 0x25:
raise AttributeError("Cannot find a PE_G1")
if self._rreg(_PE_GX_ID) == 0x25:
self._PE_GX_SERVO = 0x0D
self._type = 1 #PE_G1
elif self._rreg(_PE_GX_ID) == 0x26:
self._PE_GX_SERVO = 0x0B
self._type = 2 #MDB
else:
raise AttributeError("Cannot find a PE_G1 or MDB")
self.reset()
def _wreg(self, reg, val):
@@ -38,75 +39,88 @@ class PE_G1:
'''Read memory address'''
try:
self._i2c.writeto(self._addr, reg.to_bytes(1, 'little'))
return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes<=1 else self._i2c.readfrom(self._addr, nbytes)[0:nbytes]
return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes <= 1 else self._i2c.readfrom(self._addr, nbytes)
except:
return 0
def reset(self):
"""Reset all registers to default state"""
for reg in range(_PE_G1_MOTOR,_PE_G1_MOTOR+18):
self._wreg(reg,0x00)
if self._type == 1:
self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(18))
if self._type == 2:
self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(20))
def read_bat(self,ratio=0.0097):
def read_bat(self, ratio=1):
'''Read battery power'''
vbat= self._rreg(_PE_G1_VBAT)<<2 | self._rreg(_PE_G1_VBAT+1)>>6
return round(vbat*ratio,2)
def m_pwm(self,index,duty=None):
"""Motor*5*2 PWM duty cycle data register"""
if not 0 <= index <= 9:
raise ValueError("Motor port must be a number in the range: 0~9")
vbat = self._rreg(_PE_GX_VBAT) << 2 | self._rreg(_PE_GX_VBAT+1) >> 6
if self._type == 1:
return round(vbat * ratio * 0.00968, 2)
if self._type == 2:
return round(vbat * ratio * 0.01398, 2)
def m_pwm(self, index, duty=None):
"""Motor PWM duty cycle data register"""
if self._type == 1: # Motor*5*2
if not 0 <= index <= 9:
raise ValueError("Motor port must be a number in the range: 0~4")
if self._type == 2: # Motor*4*2
if not 0 <= index <= 7:
raise ValueError("Motor port must be a number in the range: 0~3")
if duty is None:
return self._rreg(_PE_G1_MOTOR+index)
return self._rreg(_PE_GX_MOTOR + index)
else:
if not 0 <= duty <= 255:
raise ValueError("Duty must be a number in the range: 0~255")
self._wreg(_PE_G1_MOTOR+index,duty)
self._wreg(_PE_GX_MOTOR + index, duty)
def s_pwm(self,index,duty=None):
"""Servo*4 PWM duty cycle data register"""
if not 0 <= index <= 3:
raise ValueError("Servo port must be a number in the range: 0~3")
def s_pwm(self, index, duty=None):
"""Servo PWM duty cycle data register"""
if self._type == 1: # Servo*4
if not 0 <= index <= 3:
raise ValueError("Servo port must be a number in the range: 0~3")
if self._type == 2: # Servo*6
if not 0 <= index <= 5:
raise ValueError("Servo port must be a number in the range: 0~5")
if duty is None:
return self._rreg(_PE_G1_SERVO+index*2)<<8 | self._rreg(_PE_G1_SERVO+index*2+1)
return self._rreg(self._PE_GX_SERVO + index * 2) << 8 | self._rreg(self._PE_GX_SERVO + index * 2 + 1)
else:
if not 0 <= duty <= 4095:
raise ValueError("Duty must be a number in the range: 0~4095")
self._wreg(_PE_G1_SERVO+index*2,duty>>8)
self._wreg(_PE_G1_SERVO+index*2+1,duty&0xff)
self._wreg(self._PE_GX_SERVO + index * 2,duty >> 8)
self._wreg(self._PE_GX_SERVO + index * 2 + 1,duty & 0xff)
def motor(self,index,action,speed=0):
def motor(self, index, action="NC", speed=0):
if not 0 <= speed <= 100:
raise ValueError("Speed parameters must be a number in the range: 0~100")
if action=="N":
self.m_pwm(index*2,0)
self.m_pwm(index*2+1,0)
elif action=="P":
self.m_pwm(index*2,255)
self.m_pwm(index*2+1,255)
elif action=="CW":
self.m_pwm(index*2,0)
self.m_pwm(index*2+1,speed*255//100)
elif action=="CCW":
self.m_pwm(index*2,speed*255//100)
self.m_pwm(index*2+1,0)
elif action=="NC":
return round(self.m_pwm(index*2)*100/255),round(self.m_pwm(index*2+1)*100/255)
if action == "N":
self.m_pwm(index * 2, 0)
self.m_pwm(index * 2 + 1, 0)
elif action == "P":
self.m_pwm(index * 2, 255)
self.m_pwm(index * 2 + 1, 255)
elif action == "CW":
self.m_pwm(index * 2, 0)
self.m_pwm(index * 2 + 1, speed * 255 // 100)
elif action == "CCW":
self.m_pwm(index * 2, speed * 255 // 100)
self.m_pwm(index * 2 + 1, 0)
elif action == "NC":
return round(self.m_pwm(index * 2) * 100 / 255), round(self.m_pwm(index * 2 + 1) * 100 / 255)
else:
raise ValueError('Invalid input, valid are "N","P","CW","CCW"')
def servo180(self,index,angle=None):
def servo180(self, index, angle=None):
if angle is None:
return round((self.s_pwm(index)-102.375)*180/409.5)
return round((self.s_pwm(index) - 102.375) * 180 / 409.5)
else:
if not 0 <= angle <= 180:
raise ValueError("Servo(180) angle must be a number in the range: 0~180")
self.s_pwm(index,round(102.375 + 409.5/180 * angle))
self.s_pwm(index,round(102.375 + 409.5 / 180 * angle))
def servo360(self,index,speed=None):
def servo360(self, index, speed=None):
if speed is None:
return round((self.s_pwm(index)-102.375)*200/409.5-100)
return round((self.s_pwm(index) - 102.375) * 200 / 409.5 - 100)
else:
if not -100<= speed <= 100:
if not -100 <= speed <= 100:
raise ValueError("Servo(360) speed must be a number in the range: -100~100")
self.s_pwm(index,round(102.375 + 409.5/200 * (speed+100)))
self.s_pwm(index,round(102.375 + 409.5 / 200 * (speed + 100)))