raspberry-pi-pico学习笔记 LCD+MX30102

上一篇之后鸽了大概一年多(虽然好像也没人看),但是最近无聊,发现微雪出了个给RP2040的LCD小屏幕,大概是智能手表的大小,实在是心动,但是微雪的整套板子又太贵(且没必要),于是万能的某宝搞定一块35块钱,同样是GC9A01A驱动芯片的屏幕,但是吃水不忘挖井人,还是把微雪的资料发出来,淘宝那个自己搜就好,多得很

RP2040-LCD-1.28 - Waveshare Wiki

等了两天,屏幕到货了,由于之前没拍,只能这会儿拍一个连好线的了(请忽略杂乱的桌子和已经点亮的屏幕)

raspberry-pi-pico学习笔记 LCD+MX30102_第1张图片

之后就是下载代码了,微雪已经提供好了现成的亮屏固件,点亮其实没啥复杂的,烧写就对了

raspberry-pi-pico学习笔记 LCD+MX30102_第2张图片

之后觉得挺没意思的,然后翻出来一块凑单用的心率血氧传感器MX30102,想着干脆搞到一起试一下,然后就开始了两个小时的折腾之路 

MX30102的代码也是百度直接搜的,某家开发板的,老规矩,直接上连接

GitHub - TPYBoard/TPYBoard-v102: TPYBoard v102开发板的典型实例资料

毕竟我也是第一次在实际项目中写python,上一次看python语法好像还是2019还是2018年来着,然后看了RP2040的电路图就直接连线搞了,因为屏幕已经用了一个3V3引脚,所以就理所当然的把3V3_EN拿出来用了,结果一连线一上电,板子怎么都连不上电脑了,整个人完全傻了

后面拿出一块没焊引脚的板子发现是好的,理所当然的怀疑USB口坏了(毕竟这个板子买完焊接点了一次LED就吃灰了一年之久),于是开始了,找焊台,修焊台,焊引脚,然后重新连线的过程

结果重新连接后,新板子也不能用,我就怀疑,这个3V3_EN的引脚是不是有猫腻,果然,拔下来就好了

这就有问题了,板子只有一个3V3,但是还好,搞嵌入式的永远不会缺一个东西,就是USB转TTL,果断拿了一个出来,用它来供电

然后开始移植代码,因为我还没研究明白python的import是怎么回事(到最后其实理解了一点,不多),就全放到一个main.py里面了

然后,因为python对格式的硬要求,各种报错

接着就开始提示I2C错误,我才搞明白,弄了半天各家的micropython的硬件库是不一样的啊(原谅我,真的第一次写python)

然后就开始看两套I2C代码的对比

那个疑似ESP32板子的I2C是这样的

class MAX30102():
    #默认使用引脚X1作为中断引脚,连接模块的INT引脚
    #默认使用TPYBoard v102的i2c(2)接口 SCL=>Y9 SDA=>Y10
    def __init__(self,i2c_id=2,address=0x57, pin='X1'):
        print("intpin: {0}, address: {1}".format(pin, address))
        self.i2c = I2C(i2c_id,I2C.MASTER, baudrate=400000)
        self.address = address
        self.interrupt =Pin(pin,Pin.IN)                                  #设置中断引脚为输入模式
        self.reset()                                                     #软复位
        pyb.delay(1000)
        #reg_data = self.i2c.mem_read(1, self.address, REG_INTR_STATUS_1)
        addr = self.i2c.scan()
        if address not in addr:
            print('max30102 device not found')
        elif not self.i2c.is_ready(address):
            print('max30102 device not response')
        else:
            self.setup()

    def shutdown(self):
        """
        关闭模块
        """
        self.i2c.mem_write(b'\x80', self.address, REG_MODE_CONFIG)

    def reset(self):
        """
        Reset the device, this will clear all settings,
        so after running this, run setup() again.
        """
        self.i2c.mem_write(b'\x40', self.address, REG_MODE_CONFIG)

    def setup(self, led_mode=b'\x03'):
        """
        模块的初始化设置
        """

        self.i2c.mem_write(b'\xc0', self.address, REG_INTR_ENABLE_1)
        self.i2c.mem_write(b'\x00', self.address, REG_INTR_ENABLE_2)
        self.i2c.mem_write(b'\x00', self.address, REG_FIFO_WR_PTR)
        self.i2c.mem_write(b'\x00', self.address, REG_OVF_COUNTER)
        self.i2c.mem_write(b'\x00', self.address, REG_FIFO_RD_PTR)
        self.i2c.mem_write(b'\x4f', self.address, REG_FIFO_CONFIG)
        self.i2c.mem_write(led_mode, self.address, REG_MODE_CONFIG)
        self.i2c.mem_write(b'\x27', self.address, REG_SPO2_CONFIG)
        self.i2c.mem_write(b'\x24', self.address, REG_LED1_PA)
        self.i2c.mem_write(b'\x24', self.address, REG_LED2_PA)
        self.i2c.mem_write(b'\x7f', self.address, REG_PILOT_PA)


    def set_config(self, reg, value):
        self.i2c.mem_write(value, self.address, reg)

    def read_fifo(self):
        """
        读取寄存器的数据
        """
        red_led = None
        ir_led = None

        #从寄存器中读取1个字节的数据
        reg_INTR1 = self.i2c.mem_read(1, self.address, REG_INTR_STATUS_1)
        reg_INTR2 = self.i2c.mem_read(1, self.address, REG_INTR_STATUS_2)

        d = self.i2c.mem_read(6, self.address, REG_FIFO_DATA)

        # mask MSB [23:18]
        red_led = (d[0] << 16 | d[1] << 8 | d[2]) & 0x03FFFF
        ir_led = (d[3] << 16 | d[4] << 8 | d[5]) & 0x03FFFF

        return red_led, ir_led
    def read_sequential(self, amount=100):
        """
        读取模块上红色LED和红外光LED测量的数据
        """
        red_buf = []
        ir_buf = []
        for i in range(amount):
            while(self.interrupt.value() == 1):
                #等待中断信号
                pass

            red, ir = self.read_fifo()

            red_buf.append(red)
            ir_buf.append(ir)

        return red_buf, ir_buf

 而RP2040的I2C库是这样的

raspberry-pi-pico学习笔记 LCD+MX30102_第3张图片

raspberry-pi-pico学习笔记 LCD+MX30102_第4张图片

之后就试着改了一下,想着I2C反正就是IC地址,寄存器地址这点东西

改了之后的结果是

class MAX30102():
    #默认使用引脚X1作为中断引脚,连接模块的INT引脚
    #默认使用TPYBoard v102的i2c(2)接口 SCL=>Y9 SDA=>Y10
    def __init__(self,i2c_id=1,address=0x57, pin='X1'):
        #print("intpin: {0}, address: {1}".format(pin, address))
        self.i2c = I2C(i2c_id,scl=Pin(7),sda=Pin(6),freq=400_000)
        self.address = address
        #self.interrupt =Pin(pin,Pin.IN)                                  #设置中断引脚为输入模式
        self.reset()
        time.sleep(1)#软复位
        #delay(1000)
        #reg_data = self.i2c.readfrom_mem(1, self.address, REG_INTR_STATUS_1)
        addr = self.i2c.scan()
        if address not in addr:
            print('max30102 device not found')
#         elif not self.i2c.is_ready(address):
#             print('max30102 device not response')
        else:
            self.setup()

    def shutdown(self):
        """
        关闭模块
        """
        self.i2c.writeto_mem(b'\x80', self.address, REG_MODE_CONFIG)

    def reset(self):
        """
        Reset the device, this will clear all settings,
        so after running this, run setup() again.
        """
        self.i2c.writeto_mem(self.address,REG_MODE_CONFIG,'0x40',addrsize=8)

    def setup(self, led_mode=b'\x03'):
        """
        模块的初始化设置
        """

        self.i2c.writeto_mem(self.address, REG_INTR_ENABLE_1,b'\xc0',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_INTR_ENABLE_2,'0x00',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_FIFO_WR_PTR,'0x00',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_OVF_COUNTER,'0x00',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_FIFO_RD_PTR,'0x00',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_FIFO_CONFIG,'0x4f',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_MODE_CONFIG,led_mode,addrsize=8)
        self.i2c.writeto_mem(self.address, REG_SPO2_CONFIG,'0x27',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_LED1_PA,'0x24',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_LED2_PA,'0x24',addrsize=8)
        self.i2c.writeto_mem(self.address, REG_PILOT_PA,'0x7f',addrsize=8)


    def set_config(self, reg, value):
        self.i2c.writeto_mem(value, self.address, reg)

    def read_fifo(self):
        """
        读取寄存器的数据
        """
        red_led = None
        ir_led = None

        #从寄存器中读取1个字节的数据
        reg_INTR1 = self.i2c.readfrom_mem(self.address, REG_INTR_STATUS_1,1,addrsize=8)
        reg_INTR2 = self.i2c.readfrom_mem(self.address, REG_INTR_STATUS_2,1,addrsize=8)

        d = self.i2c.readfrom_mem(self.address, REG_FIFO_DATA,6,addrsize=8)

        # mask MSB [23:18]
        red_led = (d[0] << 16 | d[1] << 8 | d[2]) & 0x03FFFF
        ir_led = (d[3] << 16 | d[4] << 8 | d[5]) & 0x03FFFF

        return red_led, ir_led
    def read_sequential(self, amount=100):
        """
        读取模块上红色LED和红外光LED测量的数据
        """
        red_buf = []
        ir_buf = []
        for i in range(amount):
#             while(self.interrupt.value() == 1):
#                 #等待中断信号
#                 pass

            red, ir = self.read_fifo()

            red_buf.append(red)
            ir_buf.append(ir)

        return red_buf, ir_buf

中间试了很多次,到这块终于算成功了

然后最后就是main函数了

if __name__=='__main__':
  
    LCD = LCD_1inch28()
    LCD.set_bl_pwm(65535)
#     qmi8658=QMI8658()
    Vbat= ADC(Pin(Vbat_Pin))   
    m = MAX30102()
    while(True):
        #read QMI8658
#         xyz=qmi8658.Read_XYZ()
        red, ir = m.read_sequential(1000)
        #进行分析
        ir_avg = []
        red_avg = []
        for i in range(37):
            d = calc_hr_and_spo2(ir[25*i:25*i+100], red[25*i:25*i+100])
            #print(d)
            if d[1]:
                ir_avg.append(d[0])
            if d[3]:
                red_avg.append(d[2])
            ir_D = (sum(ir_avg) - max(ir_avg) - min(ir_avg)) // len(ir_avg)
            #red_D = (sum(red_avg) - max(red_avg) - min(red_avg)) // len(red_avg)
        LCD.fill(LCD.white)
        
        LCD.fill_rect(0,0,240,40,LCD.red)
        LCD.text("RP2040-LCD-1.28",60,25,LCD.white)
        
        LCD.fill_rect(0,40,240,40,LCD.blue)
        LCD.text("micropython",80,57,LCD.white)
        
        LCD.fill_rect(0,80,120,120,0x1805)
        LCD.text("heart is:%d"%(ir_D/2),20,100-3,LCD.white)
        LCD.text("times/min",20,140-3,LCD.white)
#         LCD.text("ACC_Z={:+.2f}".format(xyz[2]),20,180-3,LCD.white)

        LCD.fill_rect(120,80,120,120,0xF073)
#         LCD.text("GYR_X={:+3.2f}".format(xyz[3]),125,100-3,LCD.white)
#         LCD.text("GYR_Y={:+3.2f}".format(xyz[4]),125,140-3,LCD.white)
#         LCD.text("GYR_Z={:+3.2f}".format(xyz[5]),125,180-3,LCD.white)
        
        LCD.fill_rect(0,200,240,40,0x180f)
        reading = Vbat.read_u16()*3.3/65535*2
        LCD.text("Vbat={:.2f}".format(reading),80,215,LCD.white)
        
        LCD.show()
        time.sleep(0.1)

 成功可以输出心率数据了,就是觉得挺不对的,应该是传感器的具体配置还是哪没弄好,改天继续弄弄吧

完整代码先不传了,改天整好了再说

LCD+MX30102

你可能感兴趣的:(学习)