From 06d703fee65e2de8c854e2c92576a7ef78d982f5 Mon Sep 17 00:00:00 2001 From: wemos Date: Thu, 13 Oct 2022 13:38:15 +0800 Subject: [PATCH 1/4] micropython/drivers: Add "sht3x" sensor driver. --- micropython/drivers/sensor/sht3x/manifest.py | 1 + micropython/drivers/sensor/sht3x/sht3x.py | 26 ++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 micropython/drivers/sensor/sht3x/manifest.py create mode 100644 micropython/drivers/sensor/sht3x/sht3x.py diff --git a/micropython/drivers/sensor/sht3x/manifest.py b/micropython/drivers/sensor/sht3x/manifest.py new file mode 100644 index 000000000..9daa56622 --- /dev/null +++ b/micropython/drivers/sensor/sht3x/manifest.py @@ -0,0 +1 @@ +module("sht3x.py", opt=3) diff --git a/micropython/drivers/sensor/sht3x/sht3x.py b/micropython/drivers/sensor/sht3x/sht3x.py new file mode 100644 index 000000000..411c49571 --- /dev/null +++ b/micropython/drivers/sensor/sht3x/sht3x.py @@ -0,0 +1,26 @@ +# SHT3x driver for MicroPython on ESP8266/ESP32 +# MIT license; Copyright (c) 2022 WEMOS.CC + +import utime + + +class SHT3X: + def __init__(self, i2c, address=0x45): + self.bus = i2c + self.slv_addr = address + self.buf = bytearray(6) + + def measure(self): + self.bus.writeto(self.slv_addr, b"\x24\x00") + utime.sleep(1) + self.buf = self.bus.readfrom(self.slv_addr, 6) + + def humidity(self): + humidity_raw = self.buf[3] << 8 | self.buf[4] + humidity = 100.0 * float(humidity_raw) / 65535.0 + return humidity + + def temperature(self): + temperature_raw = self.buf[0] << 8 | self.buf[1] + temperature = (175.0 * float(temperature_raw) / 65535.0) - 45 + return temperature From fbc2f38428550cb6491c34f3219d0a6c47a61569 Mon Sep 17 00:00:00 2001 From: wemos Date: Fri, 14 Oct 2022 07:57:21 +0800 Subject: [PATCH 2/4] add sc7a20 driver. --- micropython/drivers/sensor/sc7a20/manifest.py | 1 + micropython/drivers/sensor/sc7a20/sc7a20.py | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 micropython/drivers/sensor/sc7a20/manifest.py create mode 100644 micropython/drivers/sensor/sc7a20/sc7a20.py diff --git a/micropython/drivers/sensor/sc7a20/manifest.py b/micropython/drivers/sensor/sc7a20/manifest.py new file mode 100644 index 000000000..72565c607 --- /dev/null +++ b/micropython/drivers/sensor/sc7a20/manifest.py @@ -0,0 +1 @@ +module("sc7a20.py", opt=3) diff --git a/micropython/drivers/sensor/sc7a20/sc7a20.py b/micropython/drivers/sensor/sc7a20/sc7a20.py new file mode 100644 index 000000000..b2e2d8af9 --- /dev/null +++ b/micropython/drivers/sensor/sc7a20/sc7a20.py @@ -0,0 +1,51 @@ +# SC7A20 driver for MicroPython on ESP8266/ESP32 +# MIT license; Copyright (c) 2022 WEMOS.CC + +from micropython import const + + +WHO_AM_I_REG = const(0x0F) +CTRL_REG1 = const(0x20) +CTRL_REG2 = const(0x21) +CTRL_REG3 = const(0x22) +ADDR_STATUS_REG = const(0x27) +OUT_X_L_REG = const(0x28) +OUT_X_H_REG = const(0x29) +OUT_Y_L_REG = const(0x2A) +OUT_Y_H_REG = const(0x2B) +OUT_Z_L_REG = const(0x2C) +OUT_Z_H_REG = const(0x2D) + +CHIP_ID = const(0x11) + + +class SC7A20: + def __init__(self, i2c, address=0x18): + self.bus = i2c + self.slv_addr = address + self.buf = bytearray(6) + self.bus.writeto_mem(self.slv_addr, CTRL_REG1, b"\x27") # 10hz + + def _12bitComplement(self, msb, lsb): + # temp=0x0000 + temp = msb << 8 | lsb + temp = temp >> 4 + # 只有高12位有效 + temp = temp & 0x0FFF + + if temp & 0x0800: # 负数 补码==>原码 + temp = temp & 0x07FF # 屏弊最高位 + temp = ~temp + temp = temp + 1 + temp = temp & 0x07FF + temp = -temp # 还原最高位 + + return temp + + def measure(self): + + self.buf = self.bus.readfrom_mem(self.slv_addr, OUT_X_L_REG, 6) + accel_X = self._12bitComplement(self.buf[1], self.buf[0]) + accel_Y = self._12bitComplement(self.buf[3], self.buf[2]) + accel_Z = self._12bitComplement(self.buf[5], self.buf[4]) + return accel_X, accel_Y, accel_Z From 771332670dfdf3efbe83c149e6275ea233ed50b7 Mon Sep 17 00:00:00 2001 From: wemos Date: Wed, 10 Jul 2024 14:47:34 +0800 Subject: [PATCH 3/4] Add QST QMI8658 IMU driver --- micropython/drivers/imu/qmi8658/manifest.py | 2 + micropython/drivers/imu/qmi8658/qmi8658.py | 232 ++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 micropython/drivers/imu/qmi8658/manifest.py create mode 100644 micropython/drivers/imu/qmi8658/qmi8658.py diff --git a/micropython/drivers/imu/qmi8658/manifest.py b/micropython/drivers/imu/qmi8658/manifest.py new file mode 100644 index 000000000..e6578af21 --- /dev/null +++ b/micropython/drivers/imu/qmi8658/manifest.py @@ -0,0 +1,2 @@ +metadata(description="QST QMI8658 IMU driver.", version="1.0.0") +module("qmi8658.py", opt=3) diff --git a/micropython/drivers/imu/qmi8658/qmi8658.py b/micropython/drivers/imu/qmi8658/qmi8658.py new file mode 100644 index 000000000..ea932be83 --- /dev/null +++ b/micropython/drivers/imu/qmi8658/qmi8658.py @@ -0,0 +1,232 @@ +# QMI8658 driver for MicroPython +# MIT license; Copyright (c) 2022-2024 WEMOS.CC + +import struct +from machine import I2C +import machine +import time +import array +import math + +WHO_AM_I = const(0x00) # Device identifier +REVISION_ID = const(0x01) +CTRL1 = const(0x02) # Serial Interface and Sensor Enable +CTRL2 = const(0x03) # Accelerometer Settings +CTRL3 = const(0x04) # Gyroscope Settings +CTRL4 = const(0x05) # Magnetometer Settings +CTRL5 = const(0x06) # Sensor Data Processing Settings +CTRL7 = const(0x08) # Enable Sensors and Configure Data Reads +CTRL8 = const(0x09) # Reserved – Special Settings + +# + +TEMP_L = const(0x33) + +AccX_L = const(0x35) +AccX_H = const(0x36) +AccY_L = const(0x37) +AccY_H = const(0x38) +AccZ_L = const(0x39) +AccZ_H = const(0x3A) + +GyrX_L = const(0x3B) +GyrX_H = const(0x3C) +GyrY_L = const(0x3D) +GyrY_H = const(0x3E) +GyrZ_L = const(0x3F) +GyrZ_H = const(0x40) + + +class QMI8658(): + def __init__(self, i2c, addr=0x6b, accel_scale=2, gyro_scale=2048,accel_odr=500,gyro_odr=500): + self.i2c = i2c + self.addr = addr + + self.accel_scale = accel_scale + self.gyro_scale = gyro_scale + + self.accel_odr=accel_odr + self.gyro_odr=gyro_odr + + self.accel_sensitivity=32768/self.accel_scale + self.gyro_sensitivity=32768/gyro_scale + + self.scratch_int = array.array("h", [0, 0, 0]) + + if self.i2c.readfrom_mem(self.addr, WHO_AM_I, 1) != b'\x05': + raise OSError( + "No QMI8658 device was found at address 0x%x" % (self.addr)) + + # Accelerometer Full-scale + SCALE_ACCEL = {2: 0, 4: 1, 8: 2, 16: 3} + + # Gyroscope Full-scale + SCALE_GYRO = {16: 0, 32: 1, 64: 2, 128: 3, + 256: 4, 512: 5, 1024: 6, 2048: 7} + + # Accelerometer Output Data Rate (ODR) + ODR_ACCEL = { + # Normal + 8000: 0, + 4000: 1, + 2000: 2, + 1000: 3, + 500: 4, + 250: 5, + 125: 6, + 62.5: 7, + 31.25: 8, + # Low Power + 128: 12, + 21: 13, # 58% Duty Cycle + 11: 14, # 31% Duty Cycle + 3: 15 # 8.5% Duty Cycle + } + + # Gyroscope Output Data Rate (ODR) + ODR_GYRO = { + # Normal + 8000: 0, + 4000: 1, + 2000: 2, + 1000: 3, + 500: 4, + 250: 5, + 125: 6, + 62.5: 7, + 31.25: 8, + } + + # Sanity checks + + if not self.accel_scale in SCALE_ACCEL: + raise ValueError("Invalid accelerometer scaling: %d" % + self.accel_scale) + + if not self.gyro_scale in SCALE_GYRO: + raise ValueError("invalid gyro scaling: %d" % self.gyro_scale) + + if not self.accel_odr in ODR_ACCEL: + raise ValueError("Invalid sampling rate: %d" % self.accel_odr) + + if not self.gyro_odr in ODR_GYRO: + raise ValueError("Invalid sampling rate: %d" % self.gyro_odr) + + # Serial Interface and Sensor Enable, address auto increment + self.i2c.writeto_mem(self.addr, CTRL1, b'\x40') + # Enable Sensors and Configure Data Reads + self.i2c.writeto_mem(self.addr, CTRL7, b'\x03') + + # Accelerometer Settings + parm=(ODR_ACCEL[self.accel_odr])|(SCALE_ACCEL[self.accel_scale]<<4) + self.i2c.writeto_mem(self.addr, CTRL2, bytes([parm])) + + # Gyroscope Settings< ±2048dps 500Hz> + parm=(ODR_GYRO[self.gyro_odr])|(SCALE_GYRO[self.gyro_scale]<<4) + self.i2c.writeto_mem(self.addr, CTRL3, bytes([parm])) + + # Sensor Data Processing Settings + self.i2c.writeto_mem(self.addr, CTRL5, b'\x11') + + def test(self): + return self.i2c.readfrom_mem(self.addr, AccX_L, 12) + + def read_gyro(self): + mv = memoryview(self.scratch_int) + self.i2c.readfrom_mem_into(self.addr,GyrX_L, mv) + return (mv[0] / self.gyro_sensitivity, mv[1] / self.gyro_sensitivity, mv[2] / self.gyro_sensitivity) + + def read_accel(self): + mv = memoryview(self.scratch_int) + self.i2c.readfrom_mem_into(self.addr,AccX_L, mv) + return (mv[0] / self.accel_sensitivity, mv[1] / self.accel_sensitivity, mv[2] / self.accel_sensitivity) + + def read_temp(self): + return struct.unpack("> 1) # arithmetic with magic number + packed_i = struct.pack('i', i) + y = struct.unpack('f', packed_i)[0] # treat int's bytes as float + + y = y * (threehalfs - (x2 * y * y)) # Newton's method + return y + + def get_euler_angles(self,gx,gy,gz,ax,ay,az): + + Ki=const(0.008) + Kp=const(10.0) + halfT=const(0.002127) + + q0 = 1.0 + q1 = 0.0 + q2 = 0.0 + q3 = 0.0 #/** quaternion of sensor frame relative to auxiliary frame */ + + exInt=0.0 + eyInt=0.0 + ezInt=0.0 + + q0q0 = q0*q0 + q0q1 = q0*q1 + q0q2 = q0*q2 + + q1q1 = q1*q1 + q1q3 = q1*q3 + + q2q2 = q2*q2 + q2q3 = q2*q3 + + q3q3 = q3*q3 + + + if( ax*ay*az==0): + return 0 + #/* 对加速度数据进行归一化处理 */ + recipNorm = self.invSqrt( ax* ax +ay*ay + az*az) + ax = ax *recipNorm + ay = ay *recipNorm + az = az *recipNorm + #/* DCM矩阵旋转 */ + vx = 2*(q1q3 - q0q2) + vy = 2*(q0q1 + q2q3) + vz = q0q0 - q1q1 - q2q2 + q3q3 + #/* 在机体坐标系下做向量叉积得到补偿数据 */ + ex = ay*vz - az*vy + ey = az*vx - ax*vz + ez = ax*vy - ay*vx + #/* 对误差进行PI计算,补偿角速度 */ + exInt = exInt + ex * Ki + eyInt = eyInt + ey * Ki + ezInt = ezInt + ez * Ki + + gx = gx + Kp*ex + exInt + gy = gy + Kp*ey + eyInt + gz = gz + Kp*ez + ezInt + #/* 按照四元素微分公式进行四元素更新 */ + q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT + q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT + q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT + q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT + + recipNorm = self.invSqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3) + + q0 = q0*recipNorm + q1 = q1*recipNorm + q2 = q2*recipNorm + q3 = q3*recipNorm + + roll = math.atan2(2*q2*q3 + 2*q0*q1, -2*q1*q1 - 2*q2*q2 + 1)*57.3 + pitch = math.asin(2*q1*q3 - 2*q0*q2)*57.3 + yaw = -math.atan2(2*q1*q2 + 2*q0*q3, -2*q2*q2 -2*q3*q3 + 1)*57.3 + + + + # print("pitch:{:>8.3f} roll:{:>8.3f} yaw:{:>8.3f}\r\n".format(pitch,roll,yaw)) + return pitch,roll,yaw From c8c668dd546bfe0489fac4949de04d8f2b3909ba Mon Sep 17 00:00:00 2001 From: wemos Date: Wed, 10 Jul 2024 15:35:04 +0800 Subject: [PATCH 4/4] add ESP32 RMT IR --- .../drivers/ir/esp32_rmt_ir/esp32_rmt_ir.py | 76 +++++++++++++++++++ .../drivers/ir/esp32_rmt_ir/manifest.py | 2 + 2 files changed, 78 insertions(+) create mode 100644 micropython/drivers/ir/esp32_rmt_ir/esp32_rmt_ir.py create mode 100644 micropython/drivers/ir/esp32_rmt_ir/manifest.py diff --git a/micropython/drivers/ir/esp32_rmt_ir/esp32_rmt_ir.py b/micropython/drivers/ir/esp32_rmt_ir/esp32_rmt_ir.py new file mode 100644 index 000000000..d4429d01a --- /dev/null +++ b/micropython/drivers/ir/esp32_rmt_ir/esp32_rmt_ir.py @@ -0,0 +1,76 @@ +# ESP32 RMT IR for MicroPython +# MIT license; Copyright (c) 2022-2024 WEMOS.CC + +import esp32 +from machine import Pin +import struct +import time +import gc + + +IR_TYPE=[{'tag':'NEC','start':(9000, 4500),'high':( 560, 1690 ),'low':( 560, 560 ),'end':( 560,0 ) }, + {'tag':'SAMSUNG','start':(4500, 4450),'high':( 560, 1600 ),'low':( 560, 560 ),'end':( 8950,0 )}, + {'tag':'LG32','start':(4500, 4500),'high':( 500, 1750 ),'low':( 500, 560 ),'end':( 8950,0 )}] + + + +class ESP32_RMT_IR: + + def __init__(self,pin): + try: + self.ir = esp32.RMT(0, pin=Pin(pin), clock_div=80, tx_carrier=(38000, 33, 1))#1us, 38khz + except: + print("Error") + self.available=0 + else: + self.available=1 + + def find_type(self,type): + for i, dic in enumerate(IR_TYPE): + if(dic['tag']==type): + return i + return -1 + + def build_data(self,cmd_data,type): + + i=self.find_type(type) + + if(i!=-1): + data_START=IR_TYPE[i]['start'] + data_HIGH=IR_TYPE[i]['high'] + data_LOW=IR_TYPE[i]['low'] + data_END=IR_TYPE[i]['end'] + + tmp=data_START + + for b in ('{:032b}'.format(cmd_data)): + if (b=='1'): + tmp+=data_HIGH + + else: + tmp+=data_LOW + + tmp+=data_END + + return tmp + + else: + return -1 + + def send_INT32(self,data,type): + if(self.available): + + tmp=self.build_data(data,type) + + if(tmp!=-1): + if(self.ir.wait_done()): + self.ir.write_pulses(tmp, 1) + + + def send_NEC(self,address,cmd): + + if(self.available): + tmp=struct.pack(">4b",address,~address,cmd,~cmd) + data=struct.unpack('>i',tmp)[0] + rmt_data=self.send_INT32(data,'NEC') + return rmt_data diff --git a/micropython/drivers/ir/esp32_rmt_ir/manifest.py b/micropython/drivers/ir/esp32_rmt_ir/manifest.py new file mode 100644 index 000000000..447d5221a --- /dev/null +++ b/micropython/drivers/ir/esp32_rmt_ir/manifest.py @@ -0,0 +1,2 @@ +metadata(description="ESP32 RMT IR.", version="1.0.0") +module("esp32_rmt_ir.py", opt=3)