《深入浅出:树莓派 RP2040 硬件接口功能与传感器模块使用大全》

树莓派-RP2040

  • 实物图
  • 引脚图
  • IDE工具(thonny)
  • GPIO 输出
  • GPIO 输入
  • GPIO 中断
  • ADC(模数转换)
  • PWM(脉宽调制)
  • WDT看门狗
  • RTC实时时钟
  • I2C总线接口
  • UART串口通信
  • Timer定时器
  • _thread多线程
  • File文件操作
  • 超声波测距模块
  • 舵机控制
  • WS2812 RGB灯
  • SSD1306 OLED屏
  • AHT10温湿度传感器
  • BH1750光照度传感器
  • BMP280 气压强传感器
  • GNSS导航模块
  • 无线串口模块
  • 旋转编码器
  • 实物图

    https://pico.org.cn/

    引脚图

    IDE工具(thonny)

    https://thonny.org

    GPIO 输出

    GPIO输出模式:machine.Pin.OUT
    GPIO输入模式:machine.Pin.IN

    import machine
    import utime
    
    led = machine.Pin(25, machine.Pin.OUT)
    print('gpio output demo...')
    while True:
        led.value(0)
        utime.sleep(1)
        led.value(1)
        utime.sleep(0.5)
        
    	# 其它GPIO相关操作接口
    	#led.low()
        #led.high()
        #led.toggle()
        #led.on()
        #led.off()
        #led.value(0)
        #led.value(1)
        #state=led.value()
        #print(state)
    

    GPIO 输入

    上拉:machine.Pin.PULL_UP
    下拉:machine.Pin.PULL_DOWN

    import machine
    import utime
    
    key = machine.Pin(23, machine.Pin.IN, machine.Pin.PULL_UP)
    led = machine.Pin(25, machine.Pin.OUT)
    
    print('gpio input demo...')
    while True:
        if key.value() == 1:
            led.value(1)
        else:
            led.value(0)
        utime.sleep_ms(100)
            
    

    GPIO 中断

    irq(trigger, handler), trigger中断触发方式,handler中断处理函数
    下降沿:trigger=machine.Pin.IRQ_FALLING
    上升沿:trigger=machine.Pin.IRQ_RISING

    import machine
    import utime
    
    key = machine.Pin(23, machine.Pin.IN, machine.Pin.PULL_DOWN)
    led = machine.Pin(25, machine.Pin.OUT)
    
    print('gpio irq demo...')
    def irq_handler(pin):
        print(pin)
        led.toggle()
    
    key.irq(trigger=machine.Pin.IRQ_FALLING, handler=irq_handler)
    
    while True:
        utime.sleep(1)
        print("main loop...")
    

    ADC(模数转换)

    外部ADC模拟电压表

    import machine
    import utime
    import math
    
    adc0 = machine.ADC(26)
    adc1 = machine.ADC(27)
    adc2 = machine.ADC(28)
    
    adcvalue0 = 0
    adcvalue1 = 0
    adcvalue2 = 0
    factor = 3.3/(65536)
    
    while True:
        adcvalue0 = adc0.read_u16()*factor
        adcvalue1 = adc1.read_u16()*factor
        adcvalue2 = adc2.read_u16()*factor
        print(adcvalue0, adcvalue1, adcvalue2)
        utime.sleep_ms(500)    
    

    内部ADC测量温度

    import machine
    import utime
    
    sensor_temp = machine.ADC(4)
    #sensor_temp = machine.ADC(machine.ADC.CORE_TEMP)
    conversion_factor = 3.3/(65535)
    while True:
        reading = sensor_temp.read_u16()*conversion_factor
        temperature = 27 - (reading - 0.706)/0.001721
        print(temperature,"C")
        utime.sleep(1)
    

    PWM(脉宽调制)

    PWM相关接口:
    pwm0 = machine.PWM(machine.Pin(0))
    pwm0.freq() # 返回当前PWM设置频率
    pwm0.freq(2000) # 设置PWM频率
    pwm0.duty_u16(15000) # 设置占空比(0~65535)
    pwm0.duty_ns(10) # 设置占空比时间ns

    import machine
    import utime
    import urandom
    
    led_r = machine.PWM(machine.Pin(4))
    led_g = machine.PWM(machine.Pin(3))
    led_b = machine.PWM(machine.Pin(2))
    
    led_r.freq(1000)
    led_g.freq(1000)
    led_b.freq(1000)
    
    print(led_r.freq())
    print(led_g.freq())
    print(led_b.freq())
    
    while True:
        led_r.duty_u16(urandom.randrange(1, 65535, 10))
        led_g.duty_u16(urandom.randrange(1, 65535, 20))
        led_b.duty_u16(urandom.randrange(1, 65535, 30))    
        utime.sleep_ms(100)
    

    WDT看门狗

    import machine
    import utime
    
    # enable the WDT with a timeout of 5s (1s is the minimum)
    wdt = machine.WDT(timeout=5000)
    
    print("WDT Demo...")
    while True:
        wdt.feed()
        utime.sleep(3)
    

    RTC实时时钟

    rtc = machine.RTC()
    rtc.datetime()返回一个元组数据:
    (年,月,日,星期,时,分,秒,0)
    (2022, 10, 14, 4, 14, 41, 57, 0)

    import machine
    import utime
    
    rtc = machine.RTC()
    
    # 设置RTC日期时间等参数
    # rtc.datetime((2020, 1, 21, 2, 10, 32, 36, 0))
    
    while True:
        print(rtc.datetime())
        utime.sleep(1)
    

    I2C总线接口

    import machine
    import utime
    
    sda = machine.Pin(16)
    scl = machine.Pin(17)
    i2c = machine.I2C(0, sda=sda, scl=scl, freq=200000)
      
    print(i2c.scan())
    
    i2c.writeto(35, '0x01') # power on
    i2c.writeto(35, '0x10') # H-resolution mode
    i2c.writeto(35, '0x20')
    utime.sleep(0.2)
    
    while True:
        i2c.writeto(35, '\x01')
        val = i2c.readfrom(35, 2, True)
        print(val)
        utime.sleep(1)
    

    UART串口通信

    串口通信相关接口:
    rxbuf=bytes()
    rxData=bytes()
    txData=bytes()
    tx = machine.Pin(16)
    rx = machine.Pin(17)
    uart = machine.UART(0, baudrate=9600, bits=8, parity=None, stop=1, tx=tx, rx=rx)
    uart.any() # True:有可以读取的数据,False:没有可读取的数据
    rxData += uart.read(1) # 读取一个字节数据
    rxData = uart.readline() # 读取一行数据
    uart.readinto(rxbuf, 10) # 读取10个字节数据到rxbuf
    uart.sendbreak() # 中断串口数据发送

    txData = b’hello world!’
    uart.write(txData) # 串口写入数据
    uart.txdone() # 串口数据 True:发送完成, False:还有数据未发送成功
    uart.flush() # 串口刷新数据
    uart.deinit() # 串口反初始化

    uart.CTS
    uart.RTS
    uart.INV_RX
    uart.INV_TX

    from machine import Pin,UART
    import utime
    
    uart0 = UART(0, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17), )
    #uart0.deinit()
    
    txData = b'hello world\n\r'
    rxData = bytes()
    uart0.write(txData)
    #buf=bytes()
    #uart0.readinto(buf, 10)
    #uart0.sendbreak()
    
    print(type(txData))
    print(type(rxData))
    while True:
        while uart0.any() > 0:
            #rxData += uart0.read(1)
            rxData = uart0.readline()
            print(rxData.decode('utf-8'))
            if not uart0.txdone():
                uart0.flush()
            uart0.write(rxData)
        utime.sleep(0.2)
    

    Timer定时器

    初始化并启动定时器:

  • Timer.init(*, mode=Timer.PERIODIC, period=- 1, callback=None)
    mode: 定时器模式(Timer.ONE_SHOT , Timer.PERIODIC)
    period:定时器周期
    callback:定时器回调函数
  • Timer.deinit()
  • 启动一个定时器:

    from machine import Pin, Timer
    
    led = Pin(25, Pin.OUT)
    tim = Timer()
    
    def tick(timer):
       global led
       led.toggle()
    
    tim.init(freq=2.5, mode=Timer.PERIODIC, callback=tick)
    

    启动多个定时器:

    import utime
    from machine import Timer
    
    def tim_callback1(timer):
        """
        Timer Callback Function.
        """
        print("Timer 1...")
        pass
    
    def tim_callback2(timer):
        print("Timer 2...")
        pass
    
    tim1 = Timer()
    tim1.init(mode=Timer.PERIODIC, period=1000, callback=tim_callback1)
    #tim.init(mode=Timer.ONE_SHOT, period=100, callback=tim_callback)
    
    tim2 = Timer()
    tim2.init(mode=Timer.PERIODIC, period=2000, callback=tim_callback2)
    
    print("timer demo ...")
    
    #tim1.deinit()
    #tim2.deinit()
    while True:
        utime.sleep(1)
    

    _thread多线程

    RP2040 CPU是双核默认代码运行在core0通过
    _thread.start_new_thread启动的线程代码运行在core1上,注:start_new_thread只能调用一次,多次调用会提示core 1已使用;

    import time, _thread
    
    def th1_task(n, delay):
        while True:
            print("thread 1 running...",n)
            time.sleep(delay)
        pass
    
    _thread.start_new_thread(th1_task,(10, 1))
    
    print("thread demo...")
    while True:
        print("main loop...")
        time.sleep(10)
    

    使用线程互斥锁:

    import utime
    import _thread
    
    # 线程互斥锁
    lock = _thread.allocate_lock()
    
    # 内核1 运行任务
    def core1_task():
        """
        Core1 task
        """
        while True:
            #lock.acquire()
            print("core1 task")
            utime.sleep(0.5)
            #lock.release()
        pass
    
    _thread.start_new_thread(core1_task, ())
    
    while True:
        #lock.acquire()
        print("core0 task")
        utime.sleep(0.5)
        #lock.release()
            
    

    File文件操作

    file = open("test.txt", "w")
    file.write("Hello, File!")
    file.write(str('13245')+"\n")
    file.flush()
    file.close()
    
    file = open("test.txt")
    print(file.read())
    file.close()
    

    超声波测距模块

    import machine
    import utime
    
    trig = machine.Pin(16, machine.Pin.OUT)
    echo = machine.Pin(17, machine.Pin.IN)
    
    def get_distance(trig, echo):
        # 10us high
        trig.low()
        utime.sleep_us(2)
        trig.high()
        utime.sleep_us(10)
        trig.low()
        
        while (echo.value() == 0):
            start = utime.ticks_us()
        while echo.value() == 1:
            end = utime.ticks_us()
            d = (end - start) * 0.034 / 2
        return d
    
    trig.low()
    
    while True:
        distance = get_distance(trig, echo)
        print("距离:{:.2f} cm".format(distance))
        utime.sleep(0.1)
        
    

    舵机控制

    棕色:GND(电源负极)
    红色:VCC(电源正极)
    橙色:PWM(控制信号)


    控制时序0~180角度

    控制时序-90 ~ 0 ~ 90角度

    from machine import Pin, PWM
    import utime
    
    pwm0 = PWM(Pin(0))
    pwm0.freq(50)
    updown = True
    
    # 舵机控制信号周期T=20ms, f=1/T = 1/20ms = 50Hz
    # 脉冲宽度:0.5ms ---> 0度    PWM_DUTY=65535*(0.5ms/20ms)=1638
    # 脉冲宽度:1.5ms ---> 90度   PWM_DUTY=65535*(1.5ms/20ms)=4915
    # 脉冲宽度:2.5ms ---> 180度  PWM_DUTY=65535*(2.5ms/20ms)=8192
    
    vmin, vmax = (65535*(0.5/20)), (65535*(2.5/20))
    def get_angle(angle):   
        duty = int(vmin + (((vmax-vmin)/180) *angle) )
        return duty
    
    angle = 0
    pwm0.duty_u16(get_angle(angle))
    utime.sleep(2)
    
    while True:
        angle = 0
        pwm0.duty_u16(get_angle(angle))
        utime.sleep(1)
        angle = 45
        pwm0.duty_u16(get_angle(angle))
        utime.sleep(1)
        angle = 90
        pwm0.duty_u16(get_angle(angle))
        utime.sleep(1)
        angle = 135
        pwm0.duty_u16(get_angle(angle))
        utime.sleep(1)
        angle = 180
        pwm0.duty_u16(get_angle(angle))
        utime.sleep(1)
    
    

    WS2812 RGB灯

    将该文件通过Thonny保存到Raspberry PI Pico 的:“/lib/ws2812b.py”目录下


    文件已保存到Raspberry Pi Pico内,然后就可以在代码使用import ws2812b

  • ws2812b(num, sm, pin)
    num代表ws2812的数量
    sm是内核,目前需要设置为0
    pin是使用的引脚
  • set_pixel(n, r, g, b)
    n是第几个ws2812
    r, b, b是红绿蓝颜色
  • show(),刷新显示
  • fill((r, g, b)),填充所有ws2812
  • set_pixel_line(n1,n2,r,g,b),设置从n1到n2颜色
  • set_pixel_line_gradient(n1,n2,r1,g1,b1,r2,g2,b2),设置从n1到n2渐变色
    ws2812b.py
  • import array, time
    from machine import Pin
    import rp2
    
    @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
    def ws2812():
        T1 = 2
        T2 = 5
        T3 = 3
        wrap_target()
        label("bitloop")
        out(x, 1)               .side(0)    [T3 - 1]
        jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
        jmp("bitloop")          .side(1)    [T2 - 1]
        label("do_zero")
        nop()                   .side(0)    [T2 - 1]
        wrap()
        
    #delay here is the reset time. You need a pause to reset the LED strip back to the initial LED
    #however, if you have quite a bit of processing to do before the next time you update the strip
    #you could put in delay=0 (or a lower delay)
    class ws2812b:
        def __init__(self, num_leds, state_machine, pin, delay=0.001):
            self.pixels = array.array("I", [0 for _ in range(num_leds)])
            self.sm = rp2.StateMachine(state_machine, ws2812, freq=8000000, sideset_base=Pin(pin))
            self.sm.active(1)
            self.num_leds = num_leds
            self.delay = delay
            self.brightnessvalue = 255
    
        # Set the overal value to adjust brightness when updating leds
        def brightness(self, brightness = None):
            if brightness == None:
                return self.brightnessvalue
            else:
                if (brightness < 1):
                    brightness = 1
            if (brightness > 255):
                brightness = 255
            self.brightnessvalue = brightness
    
          # Create a gradient with two RGB colors between "pixel1" and "pixel2" (inclusive)
        def set_pixel_line_gradient(self, pixel1, pixel2, left_red, left_green, left_blue, right_red, right_green, right_blue):
            if pixel2 - pixel1 == 0: return
        
            right_pixel = max(pixel1, pixel2)
            left_pixel = min(pixel1, pixel2)
            
            for i in range(right_pixel - left_pixel + 1):
                fraction = i / (right_pixel - left_pixel)
                red = round((right_red - left_red) * fraction + left_red)
                green = round((right_green - left_green) * fraction + left_green)
                blue = round((right_blue - left_blue) * fraction + left_blue)
                
                self.set_pixel(left_pixel + i, red, green, blue)
        
          # Set an array of pixels starting from "pixel1" to "pixel2" to the desired color.
        def set_pixel_line(self, pixel1, pixel2, red, green, blue):
            for i in range(pixel1, pixel2+1):
                self.set_pixel(i, red, green, blue)
    
        def set_pixel(self, pixel_num, red, green, blue):
            # Adjust color values with brightnesslevel
            blue = round(blue * (self.brightness() / 255))
            red = round(red * (self.brightness() / 255))
            green = round(green * (self.brightness() / 255))
    
            self.pixels[pixel_num] = blue | red << 8 | green << 16
        
        # rotate x pixels to the left
        def rotate_left(self, num_of_pixels):
            if num_of_pixels == None:
                num_of_pixels = 1
            self.pixels = self.pixels[num_of_pixels:] + self.pixels[:num_of_pixels]
    
        # rotate x pixels to the right
        def rotate_right(self, num_of_pixels):
            if num_of_pixels == None:
                num_of_pixels = 1
            num_of_pixels = -1 * num_of_pixels
            self.pixels = self.pixels[num_of_pixels:] + self.pixels[:num_of_pixels]
    
        def show(self):
            for i in range(self.num_leds):
                self.sm.put(self.pixels[i],8)
            time.sleep(self.delay)
                
        def fill(self, red, green, blue):
            for i in range(self.num_leds):
                self.set_pixel(i, red, green, blue)
            time.sleep(self.delay)
    
    

    Demo演示代码

    from machine  import Pin
    import utime
    import ws2812b
    
    print(str(ws2812b))
    
    led = ws2812b.ws2812b(9, 0, 6)	# 参数1:LED灯个数, 参数2:固定填0,参数3:Pin端口号
    
    led.fill(255, 0, 0)
    led.set_pixel(0, 255, 0, 0) # 设置第一个像素,为红色
    #led.set_pixel_line(1, 3, 255, 255, 0)
    led.set_pixel_line_gradient(0, 8, 255, 0, 0, 0, 255, 0)# 设置渐变
    led.show()
    
    while True:
        #led.rotate_left(1)
        led.rotate_right(1)
        led.show()
        utime.sleep(1)
    

    SSD1306 OLED屏

    ssd1306.py保存到pico的/lib目录

    # MicroPython SSD1306 OLED driver, I2C and SPI interfaces
    
    from micropython import const
    import framebuf
    
    
    # register definitions
    SET_CONTRAST = const(0x81)
    SET_ENTIRE_ON = const(0xA4)
    SET_NORM_INV = const(0xA6)
    SET_DISP = const(0xAE)
    SET_MEM_ADDR = const(0x20)
    SET_COL_ADDR = const(0x21)
    SET_PAGE_ADDR = const(0x22)
    SET_DISP_START_LINE = const(0x40)
    SET_SEG_REMAP = const(0xA0)
    SET_MUX_RATIO = const(0xA8)
    SET_COM_OUT_DIR = const(0xC0)
    SET_DISP_OFFSET = const(0xD3)
    SET_COM_PIN_CFG = const(0xDA)
    SET_DISP_CLK_DIV = const(0xD5)
    SET_PRECHARGE = const(0xD9)
    SET_VCOM_DESEL = const(0xDB)
    SET_CHARGE_PUMP = const(0x8D)
    
    # Subclassing FrameBuffer provides support for graphics primitives
    # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
    class SSD1306(framebuf.FrameBuffer):
        def __init__(self, width, height, external_vcc):
            self.width = width
            self.height = height
            self.external_vcc = external_vcc
            self.pages = self.height // 8
            self.buffer = bytearray(self.pages * self.width)
            super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
            self.init_display()
    
        def init_display(self):
            for cmd in (
                SET_DISP | 0x00,  # off
                # address setting
                SET_MEM_ADDR,
                0x00,  # horizontal
                # resolution and layout
                SET_DISP_START_LINE | 0x00,
                SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
                SET_MUX_RATIO,
                self.height - 1,
                SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
                SET_DISP_OFFSET,
                0x00,
                SET_COM_PIN_CFG,
                0x02 if self.width > 2 * self.height else 0x12,
                # timing and driving scheme
                SET_DISP_CLK_DIV,
                0x80,
                SET_PRECHARGE,
                0x22 if self.external_vcc else 0xF1,
                SET_VCOM_DESEL,
                0x30,  # 0.83*Vcc
                # display
                SET_CONTRAST,
                0xFF,  # maximum
                SET_ENTIRE_ON,  # output follows RAM contents
                SET_NORM_INV,  # not inverted
                # charge pump
                SET_CHARGE_PUMP,
                0x10 if self.external_vcc else 0x14,
                SET_DISP | 0x01,
            ):  # on
                self.write_cmd(cmd)
            self.fill(0)
            self.show()
    
        def poweroff(self):
            self.write_cmd(SET_DISP | 0x00)
    
        def poweron(self):
            self.write_cmd(SET_DISP | 0x01)
    
        def contrast(self, contrast):
            self.write_cmd(SET_CONTRAST)
            self.write_cmd(contrast)
    
        def invert(self, invert):
            self.write_cmd(SET_NORM_INV | (invert & 1))
    
        def show(self):
            x0 = 0
            x1 = self.width - 1
            if self.width == 64:
                # displays with width of 64 pixels are shifted by 32
                x0 += 32
                x1 += 32
            self.write_cmd(SET_COL_ADDR)
            self.write_cmd(x0)
            self.write_cmd(x1)
            self.write_cmd(SET_PAGE_ADDR)
            self.write_cmd(0)
            self.write_cmd(self.pages - 1)
            self.write_data(self.buffer)
    
    
    class SSD1306_I2C(SSD1306):
        def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
            self.i2c = i2c
            self.addr = addr
            self.temp = bytearray(2)
            self.write_list = [b"\x40", None]  # Co=0, D/C#=1
            super().__init__(width, height, external_vcc)
    
        def write_cmd(self, cmd):
            self.temp[0] = 0x80  # Co=1, D/C#=0
            self.temp[1] = cmd
            self.i2c.writeto(self.addr, self.temp)
    
        def write_data(self, buf):
            self.write_list[1] = buf
            self.i2c.writevto(self.addr, self.write_list)
    
    
    class SSD1306_SPI(SSD1306):
        def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
            self.rate = 10 * 1024 * 1024
            dc.init(dc.OUT, value=0)
            res.init(res.OUT, value=0)
            cs.init(cs.OUT, value=1)
            self.spi = spi
            self.dc = dc
            self.res = res
            self.cs = cs
            import time
    
            self.res(1)
            time.sleep_ms(1)
            self.res(0)
            time.sleep_ms(10)
            self.res(1)
            super().__init__(width, height, external_vcc)
    
        def write_cmd(self, cmd):
            self.spi.init(baudrate=self.rate, polarity=0, phase=0)
            self.cs(1)
            self.dc(0)
            self.cs(0)
            self.spi.write(bytearray([cmd]))
            self.cs(1)
    
        def write_data(self, buf):
            self.spi.init(baudrate=self.rate, polarity=0, phase=0)
            self.cs(1)
            self.dc(1)
            self.cs(0)
            self.spi.write(buf)
            self.cs(1)
    
    from machine import Pin,I2C
    from ssd1306 import SSD1306_I2C
    import framebuf
    import utime
    import array
    
    i2c = I2C(0, scl=Pin(9), sda=Pin(8))
    print("I2C Address:", hex(i2c.scan()[0]).upper())
    
    WIDTH  = 128
    HEIGHT = 64
    oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)
    
    # Raspberry Pi logo as 32x32 bytearray
    buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
    
    # Load the raspberry pi logo into the framebuffer (the image is 32x32)
    fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
    
    
    oled.fill(0)
    oled.blit(fb, (128-32)//2, (64-32)//2)
    oled.text('RaspberryPi Pico', 0, 48)
    oled.show()
    utime.sleep(1)
    
    #oled.invert(True)	# 反色
    #oled.invert(False) # 正常
    #oled.poweroff()
    #oled.poweron()
    oled.contrast(250) # 0x0~0xFF
    
    oled.fill(0)
    oled.text("Hello", 15, 30)
    oled.text("RP2040", 15, 40)
    oled.hline(0,0,60, 1)
    oled.hline(0,20,60, 1)  # 水平线, X,Y, W, 颜色
    oled.vline(0,0,20, 1)
    oled.vline(60,0,20, 1)  # 垂直线, X,Y, W, 颜色
    oled.rect(80, 0, 40, 10, 1, True) # X,Y, 宽度,高度,颜色,True:实心矩形,False:空心矩形
    oled.ellipse(40, 20, 30, 10, 1, True, 0b0010) # 中心X,中心Y,宽度,高度,颜色,实心/空心  象限Q4|Q3|Q2|Q1
    oled.pixel(64, 32, 1)   # 画一个像素,X,Y, 颜色
    
    coords = array.array('h', [0,0,  15,12, 2,8,  16,26]) # 路径坐标, [x0,y0, x1,y1,...xn,yn]
    oled.poly(60, 20, coords, 1, False) #多边形  x, y, 路径,颜色,实心/空心
    oled.show()
    
    
    while True:
    #     oled.scroll(0,1)
        oled.show()
        utime.sleep_ms(200)
    

    AHT10温湿度传感器

    aht10.py另存到pico的/lib/aht10.py

    import time
    from math import log
    
    # AHT10 Library for MicroPython on ESP32
    # Author: Sean Yong
    # Date: 23rd December, 2019
    # Version 1.0
    
    #CONSTANTS
    AHT10_ADDRESS = 0x38 # 0111000 (7bit address)
    AHT10_READ_DELAY_MS = 75 # Time it takes for AHT to collect data
    AHT_TEMPERATURE_CONST = 200
    AHT_TEMPERATURE_OFFSET = 50
    KILOBYTE_CONST = 1048576
    CMD_INITIALIZE = bytearray([0xE1, 0x08, 0x00])
    CMD_MEASURE = bytearray([0xAC, 0x33, 0x00])
    FARENHEIT_MULTIPLIER = 9/5
    FARENHEIT_OFFSET = 32
    
    class AHT10:
        def __init__(self, i2c, mode=0, address=AHT10_ADDRESS):
            if i2c is None:
                raise ValueError('I2C object required.')
            if mode is not (0 and 1):
                raise ValueError('Mode must be either 0 for Celsius or 1 Farenheit')
            self.i2c = i2c
            self.address = address
            self.i2c.writeto(address, CMD_INITIALIZE)
            self.readings_raw = bytearray(8)
            self.results_parsed = [0, 0]
            self.mode = mode # 0 for Celsius, 1 for Farenheit
    
        def read_raw(self):
            self.i2c.writeto(self.address, CMD_MEASURE)
            time.sleep_ms(AHT10_READ_DELAY_MS)
            self.readings_raw = self.i2c.readfrom(AHT10_ADDRESS, 6)
            self.results_parsed[0] = self.readings_raw[1] << 12 | self.readings_raw[2] << 4 | self.readings_raw[3] >> 4
            self.results_parsed[1] = (self.readings_raw[3] & 0x0F) << 16 | self.readings_raw[4] << 8 | self.readings_raw[5]
    
        def humidity(self):
            self.read_raw()
            return (self.results_parsed[0] / KILOBYTE_CONST) * 100 
    
        def temperature(self):
            self.read_raw()
            if self.mode is 0:
                return (self.results_parsed[1] / KILOBYTE_CONST) * AHT_TEMPERATURE_CONST - AHT_TEMPERATURE_OFFSET
            else:
                return ((self.results_parsed[1] / KILOBYTE_CONST) * AHT_TEMPERATURE_CONST - AHT_TEMPERATURE_OFFSET) * FARENHEIT_MULTIPLIER + FARENHEIT_OFFSET
    
        def set_mode(self, mode):
            if mode is not (0 or 1):
                raise ValueError('Mode must be either 0 for Celsius or 1 Farenheit')
            self.mode = mode
    
        def print(self):
            print("Temperature: " + str(self.temperature()) + ("C","F")[self.mode] + ", Humidity: " + str(self.humidity()))
    
        def dew_point(self):
            h = self.humidity()
            t = self.temperature()
            prev_mode = self.mode
            self.mode = 0
            h = (log(h, 10) - 2) / 0.4343 + (17.62 * t) / (243.12 + t)
            return 243.12 * h / (17.62 - h)
    
    
    from machine import Pin,I2C
    import utime
    import aht10
    
    i2c = I2C(0, sda=Pin(8), scl=Pin(9),freq=400000)
    devlist = i2c.scan()
    print("Address List:",devlist)
    for dev in devlist:
        print(hex(dev))
    
    aht10 = aht10.AHT10(i2c, mode=0, address=0x38)
    
    while True:
        humi = aht10.humidity()     # 湿度
        temp = aht10.temperature()  # 温度
        dewp = aht10.dew_point()    # 露点
        aht10.print()
        utime.sleep(1)    
    

    OLED显示AHT10读取值

    from machine import Pin,I2C
    from ssd1306 import SSD1306_I2C,SSD1306_SPI
    import framebuf
    import array
    import utime
    import aht10
    
    
    i2c = I2C(0, sda=Pin(8), scl=Pin(9),freq=400000)
    devlist = i2c.scan()
    print("Address List:",devlist)
    for dev in devlist:
        print(hex(dev))
    
    
    
    # Raspberry Pi logo as 32x32 bytearray
    buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
    
    # Load the raspberry pi logo into the framebuffer (the image is 32x32)
    fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
    
    WIDTH = 128
    HEIGHT = 64
    oled = SSD1306_I2C(WIDTH,HEIGHT,i2c)
    oled.fill(0)
    # oled.blit(fb, (128-32)//2, (64-32)//2)
    oled.text('RaspberryPi Pico', 0, 0)
    oled.hline(0,12, 128, 1)
    oled.blit(fb, (128-32), 15)
    oled.show()
    
    aht10 = aht10.AHT10(i2c, mode=0, address=0x38)
    utime.sleep(1)
    
    while True:
        humi = aht10.humidity()
        temp = aht10.temperature()
        dewp = aht10.dew_point()
        #aht10.print()
        utime.sleep(0.2)
        #oled.fill(0)
        oled.rect(0,15,128-32,45, 0, True)
        oled.text("Temp:{:.2f}C".format(temp), 0, 15)
        oled.text("Humi:{:.2f}%".format(humi), 0, 25)
        oled.text("Dewp:{:.2f}C".format(dewp), 0, 35)
        oled.show()
        
        utime.sleep(1)    
      
    

    BH1750光照度传感器

    bh1750.py

    import utime
    
    # BH1750 Library for MicroPython on RP2040
    # Author: Song YuLong
    # Date: 2022-10-25
    # Version 1.0
    
    #CONSTANTS
    BH1750_ADDRESS = const (0x23) # 00100011 I2C Slave Address
    BH1750_READ_DELAY_MS = 180    # measurement time ms.
    
    BH1750_POWERDOWN =  bytearray([0x00])		# Power Down
    BH1750_POWERON   =  bytearray([0x01])		# Power On
    BH1750_RESET     =  bytearray([0x07])		# Reset Data Register Value.
    
    # Countinue :
    # One Time  : it is automatically set to power down mode after measurement.
    BH1750_CONTINUE_H_MODE  = bytearray([0x10]) # Countinue H-Resolution Mode 1lx 120ms
    BH1750_CONTINUE_H_MODE2 = bytearray([0x11]) # Countinue H-Resolution Mode 0.5lx 120ms
    BH1750_CONTINUE_L_MODE  = bytearray([0x13])	# Countinue L-Resolution Mode 4lx 16ms
    BH1750_ONE_TIME_H_MODE  = bytearray([0x20]) # One Time H-Resolution Mode 1lx 120ms
    BH1750_ONE_TIME_H_MODE2 = bytearray([0x21]) # One Time H-Resolution Mode 0.5lx 120ms
    BH1750_ONE_TIME_L_MODE  = bytearray([0x23]) # One Time L-Resolution Mode 4lx 16ms
    
    class BH1750:
        def __init__(self, i2c, mode=0, address=BH1750_ADDRESS):
            if i2c is None:
                raise ValueError('I2C object required.')
            
            if mode == 0:
                self.mode = BH1750_CONTINUE_H_MODE
            elif mode == 1:
                self.mode = BH1750_CONTINUE_H_MODE2
            elif mode == 2:
                self.mode = BH1750_CONTINUE_L_MODE
            elif mode == 3:
                self.mode = BH1750_ONE_TIME_H_MODE
            elif mode == 4:
                self.mode = BH1750_ONE_TIME_H_MODE2
            elif mode == 5:
                self.mode = BH1750_ONE_TIME_L_MODE
            
            if self.mode == BH1750_CONTINUE_H_MODE2 or self.mode == BH1750_ONE_TIME_H_MODE2:
                self.resolurtion = 0.5
            elif self.mode == BH1750_CONTINUE_H_MODE or self.mode == BH1750_ONE_TIME_H_MODE:
                self.resolurtion = 1
            elif self.mode == BH1750_CONTINUE_L_MODE or self.mode == BH1750_ONE_TIME_L_MODE:
                self.resolurtion = 4
            else:
                raise ValueError('Mode must be 0 ~ 5')
            
            self.i2c = i2c
            self.address = address
            self.i2c.writeto(address, BH1750_POWERDOWN)
            self.i2c.writeto(address, BH1750_POWERON)
            self.i2c.writeto(address, self.mode)
            self.rawdata = bytearray(8)
            self.value = 0.0
            
        def read_raw(self):
            self.i2c.writeto(self.address, self.mode)
            utime.sleep_ms(BH1750_READ_DELAY_MS) # max 160ms
            self.rawdata = self.i2c.readfrom(self.address, 2) 
        
        def illuminance(self):
            # illumination =(reg[15:0] * resolurtion) / 1.2 (unit:lx)
            self.read_raw()
            self.value = ((self.rawdata[0]<<8 | self.rawdata[1]) * self.resolurtion)/1.2
            return self.value
        
        def output(self):
            print("illuminance -->{:.2f}".format(self.value), "LX")
        
        def set_mode(self, mode):
            if mode == 0:
                self.mode = BH1750_CONTINUE_H_MODE
            elif mode == 1:
                self.mode = BH1750_CONTINUE_H_MODE2
            elif mode == 2:
                self.mode = BH1750_CONTINUE_L_MODE
            elif mode == 3:
                self.mode = BH1750_ONE_TIME_H_MODE
            elif mode == 4:
                self.mode = BH1750_ONE_TIME_H_MODE2
            elif mode == 5:
                self.mode = BH1750_ONE_TIME_L_MODE
                
            if self.mode == BH1750_CONTINUE_H_MODE2 or self.mode == BH1750_ONE_TIME_H_MODE2:
                self.resolurtion = 0.5
            elif self.mode == BH1750_CONTINUE_H_MODE or self.mode == BH1750_ONE_TIME_H_MODE:
                self.resolurtion = 1
            elif self.mode == BH1750_CONTINUE_L_MODE or self.mode == BH1750_ONE_TIME_L_MODE:
                self.resolurtion = 4
            else:
                raise ValueError('Mode must be 0 ~ 5')
    

    bh1750_demo.py

    from machine import Pin,I2C
    import utime
    import bh1750
    
    i2c = I2C(0, sda=Pin(8), scl=Pin(9), freq=200000)
    devlist = i2c.scan()
    print(devlist)
    for dev in devlist:
        print(hex(dev))
    
    bh1750 = bh1750.BH1750(i2c, mode=1, address=0x23)
    
    print("BH1750 Demo...")
    value = 0.0
    
    while True:
        value = bh1750.illuminance()
        print("illuminance:{:.2f} lx".format(value))
        #bh1750.output()
        utime.sleep(0.1)
    

    BMP280 气压强传感器

    bmp280.py

    from micropython import const
    from ustruct import unpack as unp
    
    # Author David Stenwall Wahlund (david at dafnet.se)
    
    # Power Modes
    BMP280_POWER_SLEEP = const(0)
    BMP280_POWER_FORCED = const(1)
    BMP280_POWER_NORMAL = const(3)
    
    BMP280_SPI3W_ON = const(1)
    BMP280_SPI3W_OFF = const(0)
    
    BMP280_TEMP_OS_SKIP = const(0)
    BMP280_TEMP_OS_1 = const(1)
    BMP280_TEMP_OS_2 = const(2)
    BMP280_TEMP_OS_4 = const(3)
    BMP280_TEMP_OS_8 = const(4)
    BMP280_TEMP_OS_16 = const(5)
    
    BMP280_PRES_OS_SKIP = const(0)
    BMP280_PRES_OS_1 = const(1)
    BMP280_PRES_OS_2 = const(2)
    BMP280_PRES_OS_4 = const(3)
    BMP280_PRES_OS_8 = const(4)
    BMP280_PRES_OS_16 = const(5)
    
    # Standby settings in ms
    BMP280_STANDBY_0_5 = const(0)
    BMP280_STANDBY_62_5 = const(1)
    BMP280_STANDBY_125 = const(2)
    BMP280_STANDBY_250 = const(3)
    BMP280_STANDBY_500 = const(4)
    BMP280_STANDBY_1000 = const(5)
    BMP280_STANDBY_2000 = const(6)
    BMP280_STANDBY_4000 = const(7)
    
    # IIR Filter setting
    BMP280_IIR_FILTER_OFF = const(0)
    BMP280_IIR_FILTER_2 = const(1)
    BMP280_IIR_FILTER_4 = const(2)
    BMP280_IIR_FILTER_8 = const(3)
    BMP280_IIR_FILTER_16 = const(4)
    
    # Oversampling setting
    BMP280_OS_ULTRALOW = const(0)
    BMP280_OS_LOW = const(1)
    BMP280_OS_STANDARD = const(2)
    BMP280_OS_HIGH = const(3)
    BMP280_OS_ULTRAHIGH = const(4)
    
    # Oversampling matrix
    # (PRESS_OS, TEMP_OS, sample time in ms)
    _BMP280_OS_MATRIX = [
        [BMP280_PRES_OS_1, BMP280_TEMP_OS_1, 7],
        [BMP280_PRES_OS_2, BMP280_TEMP_OS_1, 9],
        [BMP280_PRES_OS_4, BMP280_TEMP_OS_1, 14],
        [BMP280_PRES_OS_8, BMP280_TEMP_OS_1, 23],
        [BMP280_PRES_OS_16, BMP280_TEMP_OS_2, 44]
    ]
    
    # Use cases
    BMP280_CASE_HANDHELD_LOW = const(0)
    BMP280_CASE_HANDHELD_DYN = const(1)
    BMP280_CASE_WEATHER = const(2)
    BMP280_CASE_FLOOR = const(3)
    BMP280_CASE_DROP = const(4)
    BMP280_CASE_INDOOR = const(5)
    
    _BMP280_CASE_MATRIX = [
        [BMP280_POWER_NORMAL, BMP280_OS_ULTRAHIGH, BMP280_IIR_FILTER_4, BMP280_STANDBY_62_5],
        [BMP280_POWER_NORMAL, BMP280_OS_STANDARD, BMP280_IIR_FILTER_16, BMP280_STANDBY_0_5],
        [BMP280_POWER_FORCED, BMP280_OS_ULTRALOW, BMP280_IIR_FILTER_OFF, BMP280_STANDBY_0_5],
        [BMP280_POWER_NORMAL, BMP280_OS_STANDARD, BMP280_IIR_FILTER_4, BMP280_STANDBY_125],
        [BMP280_POWER_NORMAL, BMP280_OS_LOW, BMP280_IIR_FILTER_OFF, BMP280_STANDBY_0_5],
        [BMP280_POWER_NORMAL, BMP280_OS_ULTRAHIGH, BMP280_IIR_FILTER_16, BMP280_STANDBY_0_5]
    ]
    
    _BMP280_REGISTER_ID = const(0xD0)
    _BMP280_REGISTER_RESET = const(0xE0)
    _BMP280_REGISTER_STATUS = const(0xF3)
    _BMP280_REGISTER_CONTROL = const(0xF4)
    _BMP280_REGISTER_CONFIG = const(0xF5)  # IIR filter config
    
    _BMP280_REGISTER_DATA = const(0xF7)
    
    
    class BMP280:
        def __init__(self, i2c_bus, addr=0x76, use_case=BMP280_CASE_HANDHELD_DYN):
            self._bmp_i2c = i2c_bus
            self._i2c_addr = addr
    
            # read calibration data
            # < little-endian
            # H unsigned short
            # h signed short
            self._T1 = unp('<H', self._read(0x88, 2))[0]
            self._T2 = unp('<h', self._read(0x8A, 2))[0]
            self._T3 = unp('<h', self._read(0x8C, 2))[0]
            self._P1 = unp('<H', self._read(0x8E, 2))[0]
            self._P2 = unp('<h', self._read(0x90, 2))[0]
            self._P3 = unp('<h', self._read(0x92, 2))[0]
            self._P4 = unp('<h', self._read(0x94, 2))[0]
            self._P5 = unp('<h', self._read(0x96, 2))[0]
            self._P6 = unp('<h', self._read(0x98, 2))[0]
            self._P7 = unp('<h', self._read(0x9A, 2))[0]
            self._P8 = unp('<h', self._read(0x9C, 2))[0]
            self._P9 = unp('<h', self._read(0x9E, 2))[0]
    
            # output raw
            self._t_raw = 0
            self._t_fine = 0
            self._t = 0
    
            self._p_raw = 0
            self._p = 0
            
            self._h = 0
    
            self.read_wait_ms = 0  # interval between forced measure and readout
            self._new_read_ms = 200  # interval between
            self._last_read_ts = 0
    
            if use_case is not None:
                self.use_case(use_case)
    
        def _read(self, addr, size=1):
            return self._bmp_i2c.readfrom_mem(self._i2c_addr, addr, size)
    
        def _write(self, addr, b_arr):
            if not type(b_arr) is bytearray:
                b_arr = bytearray([b_arr])
            return self._bmp_i2c.writeto_mem(self._i2c_addr, addr, b_arr)
    
        def _gauge(self):
            # TODO limit new reads
            # read all data at once (as by spec)
            d = self._read(_BMP280_REGISTER_DATA, 6)
    
            self._p_raw = (d[0] << 12) + (d[1] << 4) + (d[2] >> 4)
            self._t_raw = (d[3] << 12) + (d[4] << 4) + (d[5] >> 4)
    
            self._t_fine = 0
            self._t = 0
            self._p = 0
            self._h = 0
    
        def reset(self):
            self._write(_BMP280_REGISTER_RESET, 0xB6)
    
        def load_test_calibration(self):
            self._T1 = 27504
            self._T2 = 26435
            self._T3 = -1000
            self._P1 = 36477
            self._P2 = -10685
            self._P3 = 3024
            self._P4 = 2855
            self._P5 = 140
            self._P6 = -7
            self._P7 = 15500
            self._P8 = -14600
            self._P9 = 6000
    
        def load_test_data(self):
            self._t_raw = 519888
            self._p_raw = 415148
    
        def print_calibration(self):
            print("T1: {} {}".format(self._T1, type(self._T1)))
            print("T2: {} {}".format(self._T2, type(self._T2)))
            print("T3: {} {}".format(self._T3, type(self._T3)))
            print("P1: {} {}".format(self._P1, type(self._P1)))
            print("P2: {} {}".format(self._P2, type(self._P2)))
            print("P3: {} {}".format(self._P3, type(self._P3)))
            print("P4: {} {}".format(self._P4, type(self._P4)))
            print("P5: {} {}".format(self._P5, type(self._P5)))
            print("P6: {} {}".format(self._P6, type(self._P6)))
            print("P7: {} {}".format(self._P7, type(self._P7)))
            print("P8: {} {}".format(self._P8, type(self._P8)))
            print("P9: {} {}".format(self._P9, type(self._P9)))
    
        def _calc_t_fine(self):
            # From datasheet page 22
            self._gauge()
            if self._t_fine == 0:
                var1 = (((self._t_raw >> 3) - (self._T1 << 1)) * self._T2) >> 11
                var2 = (((((self._t_raw >> 4) - self._T1)
                          * ((self._t_raw >> 4)
                             - self._T1)) >> 12)
                        * self._T3) >> 14
                self._t_fine = var1 + var2
    
        @property
        def temperature(self):
            self._calc_t_fine()
            if self._t == 0:
                self._t = ((self._t_fine * 5 + 128) >> 8) / 100.
            return self._t
    
        @property
        def pressure(self):
            # From datasheet page 22
            self._calc_t_fine()
            if self._p == 0:
                var1 = self._t_fine - 128000
                var2 = var1 * var1 * self._P6
                var2 = var2 + ((var1 * self._P5) << 17)
                var2 = var2 + (self._P4 << 35)
                var1 = ((var1 * var1 * self._P3) >> 8) + ((var1 * self._P2) << 12)
                var1 = (((1 << 47) + var1) * self._P1) >> 33
    
                if var1 == 0:
                    return 0
    
                p = 1048576 - self._p_raw
                p = int((((p << 31) - var2) * 3125) / var1)
                var1 = (self._P9 * (p >> 13) * (p >> 13)) >> 25
                var2 = (self._P8 * p) >> 19
    
                p = ((p + var1 + var2) >> 8) + (self._P7 << 4)
                self._p = p / 256.0
            return self._p
        
        @property
        def altitude_p_t(self):
            '''
            Calculate altitude from current temperature and pressure.
            h = ( (((P0/P)^(1/5.257))-1) * (T + 237.15) ) / 0.0065
            h:altitude (m)
            P0:101.325(kPa)
            P:current pressure in kPa
            T:current temperature in Celsius
            '''
            self._h = ( (((101.325/(self._p/1000))**(1/5.257))-1) * (self._t + 273.15) ) / 0.0065
            return self._h
        
        @property
        def altitude_p(self):
            self._h = 44330 * (1 - (((self._p/1000)/101.325)**(1/5.255)))
            return self._h
        
        def _write_bits(self, address, value, length, shift=0):
            d = self._read(address)[0]
            m = int('1' * length, 2) << shift
            d &= ~m
            d |= m & value << shift
            self._write(address, d)
    
        def _read_bits(self, address, length, shift=0):
            d = self._read(address)[0]
            return d >> shift & int('1' * length, 2)
    
        @property
        def standby(self):
            return self._read_bits(_BMP280_REGISTER_CONFIG, 3, 5)
    
        @standby.setter
        def standby(self, v):
            assert 0 <= v <= 7
            self._write_bits(_BMP280_REGISTER_CONFIG, v, 3, 5)
    
        @property
        def iir(self):
            return self._read_bits(_BMP280_REGISTER_CONFIG, 3, 2)
    
        @iir.setter
        def iir(self, v):
            assert 0 <= v <= 4
            self._write_bits(_BMP280_REGISTER_CONFIG, v, 3, 2)
    
        @property
        def spi3w(self):
            return self._read_bits(_BMP280_REGISTER_CONFIG, 1)
    
        @spi3w.setter
        def spi3w(self, v):
            assert v in (0, 1)
            self._write_bits(_BMP280_REGISTER_CONFIG, v, 1)
    
        @property
        def temp_os(self):
            return self._read_bits(_BMP280_REGISTER_CONTROL, 3, 5)
    
        @temp_os.setter
        def temp_os(self, v):
            assert 0 <= v <= 5
            self._write_bits(_BMP280_REGISTER_CONTROL, v, 3, 5)
    
        @property
        def press_os(self):
            return self._read_bits(_BMP280_REGISTER_CONTROL, 3, 2)
    
        @press_os.setter
        def press_os(self, v):
            assert 0 <= v <= 5
            self._write_bits(_BMP280_REGISTER_CONTROL, v, 3, 2)
    
        @property
        def power_mode(self):
            return self._read_bits(_BMP280_REGISTER_CONTROL, 2)
    
        @power_mode.setter
        def power_mode(self, v):
            assert 0 <= v <= 3
            self._write_bits(_BMP280_REGISTER_CONTROL, v, 2)
    
        @property
        def is_measuring(self):
            return bool(self._read_bits(_BMP280_REGISTER_STATUS, 1, 3))
    
        @property
        def is_updating(self):
            return bool(self._read_bits(_BMP280_REGISTER_STATUS, 1))
    
        @property
        def chip_id(self):
            return self._read(_BMP280_REGISTER_ID, 2)
    
        @property
        def in_normal_mode(self):
            return self.power_mode == BMP280_POWER_NORMAL
    
        def force_measure(self):
            self.power_mode = BMP280_POWER_FORCED
    
        def normal_measure(self):
            self.power_mode = BMP280_POWER_NORMAL
    
        def sleep(self):
            self.power_mode = BMP280_POWER_SLEEP
    
        def use_case(self, uc):
            assert 0 <= uc <= 5
            pm, oss, iir, sb = _BMP280_CASE_MATRIX[uc]
            p_os, t_os, self.read_wait_ms = _BMP280_OS_MATRIX[oss]
            self._write(_BMP280_REGISTER_CONFIG, (iir << 2) + (sb << 5))
            self._write(_BMP280_REGISTER_CONTROL, pm + (p_os << 2) + (t_os << 5))
    
        def oversample(self, oss):
            assert 0 <= oss <= 4
            p_os, t_os, self.read_wait_ms = _BMP280_OS_MATRIX[oss]
            self._write_bits(_BMP280_REGISTER_CONTROL, p_os + (t_os << 3), 2)
    
    

    bmp280_demo.py

    from machine import Pin, I2C
    import utime
    import bmp280
    import math
    from ustruct import unpack as unp
    
    i2c = I2C(0, sda=Pin(8), scl=Pin(9), freq=200000)
    devlist = i2c.scan()
    print(devlist)
    for dev in devlist:
        print(hex(dev))
    
    print("BMP280 Demo...")
    bmp280 = bmp280.BMP280(i2c_bus=i2c, addr=0x76)
    bmp280.use_case(1)
    bmp280.oversample(1)
    bmp280.iir = 2
    bmp280.temp_os=2
    bmp280.press_os=2
    
    bmp280.print_calibration()
    print(bmp280.chip_id)
    
        
    while True:
        t = bmp280.temperature
        p = bmp280.pressure
        h = bmp280.altitude_p_t	# calculate altitude from pressure and temperature
        h1 = bmp280.altitude_p  # calculate altitude from pressure
        print("P:{:.2f}(kPa)".format(p/1000),"T:{:.2f}(C)".format(t), "H:{:.2f}(m)".format(h), "H1:{:.2f}(m)".format(h1))
        #print(p, t, h, h1)
        utime.sleep(0.5)
    

    运行效果:

    GNSS导航模块


    navigation.py

    #
    #  songyulong
    #  2022-11-03
    #  GNSS 模块库
    #  GNSS(Global Navigation Satellite System) 的全称是全球导航卫星系统
    
    
    # 保存配置参数命令 CAS00
    CMD_SAVE_CONFIG = const(b'$PCAS00*01\r\n')  # save configuration information to flash
    
    # 串口通信波特率设置命令 CAS01
    CMD_SET_BAUDRATE_4800bps  = const(b'$PCAS01,0*1C\r\n')
    CMD_SET_BAUDRATE_9600bps  = const(b'$PCAS01,1*1D\r\n')
    CMD_SET_BAUDRATE_19200bps = const(b'$PCAS01,2*1E\r\n')
    CMD_SET_BAUDRATE_38400bps = const(b'$PCAS01,3*1F\r\n')
    CMD_SET_BAUDRATE_57600bps = const(b'$PCAS01,4*18\r\n')
    CMD_SET_BAUDRATE_115200bps= const(b'$PCAS01,5*19\r\n')
    
    # 设定定位更新率 CAS02
    CMD_SET_UPDATE_FREQ_1HZ = const(b'$PCAS02,1000*2E\r\n')
    CMD_SET_UPDATE_FREQ_2HZ = const(b'$PCAS02,500*1A\r\n')
    CMD_SET_UPDATE_FREQ_4HZ = const(b'$PCAS02,250*18\r\n')
    CMD_SET_UPDATE_FREQ_5HZ = const(b'$PCAS02,200*1D\r\n')
    CMD_SET_UPDATE_FREQ_10HZ= const(b'$PCAS02,100*1E\r\n')
    
    # 设置要求输出或停止输出的 NMEA 语句。CAS03
    
    # 配置工作系统 CAS04  GPS:美国,BDS:中国, GLONASS:俄罗斯
    CMD_SET_SYS_GPS              = const(b'$PCAS04,1*18\r\n') 
    CMD_SET_SYS_BDS              = const(b'$PCAS04,2*1B\r\n')  
    CMD_SET_SYS_GPS_BDS          = const(b'$PCAS04,3*1A\r\n')  
    CMD_SET_SYS_GLONASS          = const(b'$PCAS04,4*1D\r\n')
    CMD_SET_SYS_GPS_GLONASS      = const(b'$PCAS04,5*1C\r\n')
    CMD_SET_SYS_BDS_GLONASS      = const(b'$PCAS04,6*1F\r\n')
    CMD_SET_SYS_GPS_BDS_GLONASS  = const(b'$PCAS04,7*1E\r\n')
    
    # 接收机重启 CAS10
    CMD_RESTART_Hot     = const(b'$PCAS10,0*1C\r\n') # 热启动 :不使用初始化信息,备份存储中的所有数据有效
    CMD_RESTART_Warm    = const(b'$PCAS10,1*1D\r\n') # 温启动 :不使用初始化信息,清除星历
    CMD_RESTART_Cold    = const(b'$PCAS10,2*1E\r\n') # 冷启动 :不使用初始化信息,清除备份存储中除配置外的所有数据。
    CMD_RESTART_Factory = const(b'$PCAS10,3*1F\r\n') # 出厂启动 :清除内存所有数据,并将接收机复位至出厂默认配置
    
    
    
    class NAVIGATION:
        def __init__(self, uart, mode=CMD_SET_SYS_GPS_BDS, update_freq=CMD_SET_UPDATE_FREQ_1HZ):
            self.uart = uart
            self.mode = mode
            self.update_freq = update_freq
            self.longitude = 0
            self.latitude = 0
            self.speed = 0
            self.course = 0
            self.year = 0
            self.month = 0
            self.day = 0
            self.hour = 0
            self.minute = 0
            self.second = 0
            self.rxbuf = bytes()
            self.send_command(self.mode)
            self.send_command(self.update_freq)
            
        def deinit(self):
            self.uart.deinit()
            
        def send_command(self, cmd):
            self.uart.write(cmd)
            
        def recv_loop(self):
            while self.uart.any() > 0:
                #self.rxbuf=self.uart.readline()
                #self.parse_message(self.rxbuf)            
                c = self.uart.read(1)
                self.rxbuf += c
                if c == b'\n': # 一行报文结收结束
                    self.parse_message(self.rxbuf)
                    self.rxbuf = b''
        
        def parse_message(self,msg):
            try:
                root = msg.decode('utf-8')
                #print(root)
                if (root.startswith('$GNRMC') or root.startswith('$BDRMC') or root.startswith('$GPRMC')): #                 
                    GNRMC = root.split(',')
                    if GNRMC[2] == 'A':  # 'A':有效, 'V':无效
                        #print(GNRMC)
                        self.hour = int(GNRMC[1][0:2])
                        self.minute = int(GNRMC[1][2:4])
                        self.second = int(GNRMC[1][4:6])
                        #ms = int(GNRMC[1][7:10])
                        
                        self.day = int(GNRMC[9][0:2])
                        self.month = int(GNRMC[9][2:4])
                        self.year = int(GNRMC[9][4:6])
    
                        if GNRMC[4] == 'N': # 北纬
                            self.latitude = float(GNRMC[3])                        
                        elif GNRMC[4] == 'S': # 南纬
                            self.latitude = -(float(GNRMC[3]))
                            
                        if GNRMC[6] == 'E': # 东经
                            self.longitude = float(GNRMC[5])
                        elif GNRMC[6] == 'W': # 西经
                            self.longitude = -(float(GNRMC[5]))
                            
                        self.speed = float(GNRMC[7])
                        self.course = float(GNRMC[8])
                        #print(self.longitude, self.latitude, self.speed, self.course)
                    else:
                        self.latitude = 0
                        self.longitude = 0
                    
                elif (root.startswitch('$BDGSV')):
                    print('BDGSV')
            except:
                pass
        pass
    
    
    from machine import Pin,I2C,UART
    from ssd1306 import SSD1306_I2C,SSD1306_SPI
    import framebuf
    
    import utime
    import navigation
    from navigation import *
    import _thread
    
    i2c0 = I2C(0, sda=Pin(8), scl=Pin(9),freq=400000)
    WIDTH = 128
    HEIGHT = 64
    oled = SSD1306_I2C(WIDTH,HEIGHT,i2c0)
    oled.fill(0)
    
    uart0 = UART(1, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(4), rx=Pin(5), )
    nav = navigation.NAVIGATION(uart0)
    nav.send_command(CMD_SET_SYS_BDS)
    nav.send_command(CMD_SET_UPDATE_FREQ_1HZ)
    
    # 导航模块结束数据任务
    def navigation_task(delay):
        while True:
            nav.recv_loop()
            utime.sleep_ms(delay)
            
    _thread.start_new_thread(navigation_task, (1,) )
    utime.sleep(1.5)
    
    while True:
        #nav.recv_loop()
        oled.fill(0)
        oled.text("Lat:{:.4f}".format(nav.latitude), 0, 0)
        oled.text("Lon:{:.4f}".format(nav.longitude), 0, 10)
        oled.text("Speed:{:.2f}".format(nav.speed), 0, 20)
        oled.text("Course:{:.2f}".format(nav.course), 0, 30)
        oled.text("{:02d}/{:02d}/{:02d}".format(nav.year, nav.month, nav.day), 0, 40)
        oled.text("{:02d}:{:02d}:{:02d}".format(nav.hour+8, nav.minute, nav.second), 0, 50)
        oled.show()
        #print("main loop....", nav.longitude, nav.latitude, nav.speed, nav.course)
        utime.sleep(1)
    
    

    无线串口模块






    简单数据透传Demo

    from machine import Pin,UART
    import utime
    
    class WIRELESS_UART:
        def __init__(self, uart, m0, m1, aux=-1, mode=0):
            self.uart = uart
            self.mode = mode
            self.m0 = Pin(m0, Pin.OUT)
            self.m1 = Pin(m1, Pin.OUT)
            if aux >= 0:
                self.aux = Pin(aux, Pin.IN)
            self.set_mode(mode)
            self.rxbuf = bytes()
            
        def set_mode(self, mode):
            self.mode = mode
            if self.mode == 0:
                self.m0.value(0)
                self.m1.value(0)
            elif self.mode == 1:
                self.m0.value(1)
                self.m1.value(0)
            elif self.mode == 2:
                self.m0.value(0)
                self.m1.value(1)
            elif self.mode == 3:
                self.m0.value(1)
                self.m1.value(1)
            else:
                print('Error mode must be in 0 ~ 3')
                
        def write(self, data):
            self.uart.write(data)
            
        def recv_loop(self):
            while self.uart.any() > 0:
                #self.rxbuf=self.uart.readline()
                #self.parse_message(self.rxbuf)            
                c = self.uart.read(1)
                self.rxbuf += c
                if c == b'\n': # 一行报文结收结束
                    print(self.rxbuf)
                    self.uart.write(b'\n'+self.rxbuf)
                    self.rxbuf = b''    
            
    uart0 = UART(0, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17) )    
    wuart = WIRELESS_UART(uart=uart0, m0=19, m1=18, aux=-1, mode=0)        
    wuart.set_mode(0) # mode:0,1,2,3
    
    while True:
        #wuart.write(b'good')
        wuart.recv_loop()
        utime.sleep_ms(10)
    
    

    支持参数配置Demo

    from machine import Pin,UART
    import utime
    import struct
    
    
    CMD_READ_CONFIG = bytes([0xC1,0xC1,0xC1]) # 读取模块配置参数,比如:C0 00 00 18 50 44。
    CMD_READ_INFO = bytes([0xC3,0xC3,0xC3]) # 读取模块版本信息,比如:C3 30 xx yy;30表示E30系列,
    CMD_RESET = bytes([0xC4,0xC4,0xC4]) # 复位模块
    
    # 串口校验模式
    UART_8N1 = 0x00<<6
    UART_8O1 = 0x01<<6
    UART_8E1 = 0x02<<6
    
    # 串口波特率
    BAUDRATE_1200   = 0x00<<3
    BAUDRATE_2400   = 0x01<<3
    BAUDRATE_4800   = 0x02<<3
    BAUDRATE_9600   = 0x03<<3
    BAUDRATE_19200  = 0x04<<3
    BAUDRATE_38400  = 0x05<<3
    BAUDRATE_57600  = 0x06<<3
    BAUDRATE_115200 = 0x07<<3
    
    # 无线空中速率
    AIRRATE_1KBPS = 0x00
    AIRRATE_2KBPS = 0x01
    AIRRATE_5KBPS = 0x02
    AIRRATE_8KBPS = 0x03
    AIRRATE_10KBPS = 0x04
    AIRRATE_15KBPS = 0x05
    AIRRATE_20KBPS = 0x06
    AIRRATE_25KBPS = 0x07
    
    
    # 定点发生使能
    TRS_MODE = 0x00<<7
    FIX_MODE = 0x01<<7
    
    # IO驱动
    IO_PPO = 0x01<<6 # Push-Pull Output 推挽输出
    IO_ODO = 0x00<<6 # Open Drain Output 开漏输出
    
    WAKEUP_250MS  = 0x00<<3
    WAKEUP_500MS  = 0x01<<3
    WAKEUP_750MS  = 0x02<<3
    WAKEUP_1000MS = 0x03<<3
    WAKEUP_1250MS = 0x04<<3
    WAKEUP_1500MS = 0x05<<3
    WAKEUP_1750MS = 0x06<<3
    WAKEUP_2000MS = 0x07<<3
    
    # FEC开关
    FEC_ON = 0x01<<2
    FEC_OFF = 0x00<<2
    
    # 发射功率
    POWER_10dBm = 0x00
    POWER_9dBm  = 0x01
    POWER_8dBm  = 0x02
    POWER_7dBm  = 0x03
    
    
    
    class WIRELESS_UART:
        def __init__(self, uart, m0, m1, aux=-1, mode=0):
            self.uart = uart
            self.mode = mode
            self.m0 = Pin(m0, Pin.OUT)
            self.m1 = Pin(m1, Pin.OUT)
            if aux >= 0:
                self.aux = Pin(aux, Pin.IN)
            self.HEAD = 0xC2 # 0xC0:设置参数到ROM, 0xC2:设置参数到RAM
            self.ADDH = 0x00 # 地址高字节 00H-FFH
            self.ADDL = 0x00 # 地址低字节 00H-FFH
            self.SPED = UART_8N1|BAUDRATE_9600|AIRRATE_1KBPS # 速率参数
            self.CHAN = 0xFF # 通信频率 信道
            self.OPTION = TRS_MODE|IO_PPO|WAKEUP_250MS|FEC_ON|POWER_10dBm  #选项
            print(self.SPED, self.OPTION)
            self.set_mode(mode)
            self.rxbuf = bytes()
            self.recv = bytes()
            
        def send_configurate(self, save=False):
            mode = self.mode
            self.set_mode(3)
            utime.sleep_ms(100)
            if save==True:
                self.HEAD = 0xC0
            else:
                self.HEAD = 0xC2
            cmd = bytearray([self.HEAD, self.ADDH, self.ADDL, self.SPED, self.CHAN, self.OPTION])
            print(cmd)
            self.uart.write(cmd)
            utime.sleep_ms(200)
            self.set_mode(mode)
            
        def set_mode(self, mode):
            self.mode = mode
            # mode_0: 一般模式
            # mode_1: 唤醒模式
            # mode_2: 省电模式
            # mode_3: 休眠模式
            if self.mode == 0:
                self.m0.value(0)
                self.m1.value(0)
            elif self.mode == 1:
                self.m0.value(1)
                self.m1.value(0)
            elif self.mode == 2:
                self.m0.value(0)
                self.m1.value(1)
            elif self.mode == 3:
                self.m0.value(1)
                self.m1.value(1)
            else:
                print('Error mode must be in 0 ~ 3')
        
        def read_configurate(self):
            mode = self.mode
            self.set_mode(3)
            self.uart.write(CMD_READ_CONFIG)
            utime.sleep_ms(200)
            recv = bytes()
            while self.uart.any():
                recv +=  self.uart.read(1)
            self.set_mode(mode)
            print(len(recv))
            if len(recv)>=6:
                umode = (recv[3]&0xC0)>>6 # [7,6] 串口校验位模式
                ubsp = (recv[3]&0x38)>>3 # [5,4,3] TTL串口速率(bps)
                wbps = (recv[3]&0x07)    # [2,1,0] 无线空中速率(bps)
                freq = 425+(int(recv[4]) * 0.1) # 通信频率 425M+CHAN*0.1M  00H-FFH,对应425~455MHz
                fcc = (recv[5]&0x04)>>2 #[2] FCC开关 0:关闭FCC, 1:打开FCC
                dBm = (recv[5]&0x03) #[1,0] 发射功率
                print('----------Configurate-------------')
                print('-- head {:#X}'.format(recv[0]))
                print('-- ADDH {:#X}'.format(recv[1]))
                print('-- ADDL {:#X}'.format(recv[2]))
                print('-- SPEED:{:x}'.format(umode))
                print('-- ubsp:{:x}'.format(ubsp))
                print('-- wbps:{:x}'.format(wbps))
                print('-- ch:{:x}'.format(recv[4]))
                print('-- freq:{:d}MHz'.format(freq))
                print('-- option:{:x}'.format(recv[5]))
                print('-- FCC:{:d}'.format(fcc))
                print('-- dBm:{:d}dBm'.format(dBm))
                
            else:
                print('error configuarte head')
            
            return recv
        
        def write(self, data):
            self.uart.write(data)
            
        def recv_loop(self):
            while self.uart.any() > 0:
                #self.rxbuf=self.uart.readline()
                #self.parse_message(self.rxbuf)            
                c = self.uart.read(1)
                self.rxbuf += c
                #print(c)
                if c == b'\n': # 一行报文结收结束
                    print(self.rxbuf)
                    self.uart.write(b'\n'+self.rxbuf)
                    self.rxbuf = b''    
            
    uart0 = UART(0, baudrate=9600, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17) )    
    wuart = WIRELESS_UART(uart=uart0, m0=19, m1=18, aux=-1, mode=0)        
    
    wuart.set_mode(0)
    
    wuart.send_configurate(False)
    utime.sleep(1)
    ret = wuart.read_configurate()
    for r in ret:
        print(r)
    
    utime.sleep(1)
    while True:
        #wuart.write(b'good')
        wuart.recv_loop()
        utime.sleep_ms(100)
    

    旋转编码器

    from machine import Pin
    import utime
    
    key = Pin(18, Pin.IN)
    rotary_clk = Pin(19, Pin.IN)
    rotary_dt  = Pin(20, Pin.IN)
    
    def rotary_encoder_task(pin):
        # 当CLK下降沿时,DT是低电平:顺时针旋转,DT是高电平:逆时针旋转
        if rotary_dt.value() == 0:
            print('----right---')
        else:
            print('----left---')
        
    rotary_clk.irq(trigger=Pin.IRQ_FALLING, handler=rotary_encoder_task)
    
    # 当按键按下或抬起时会有抖动,这里增加个变量以便过滤掉干扰脉冲
    key_pressed = False
    def key_task(pin):
        global key_pressed
        if key_pressed == False:
            if key.value()==0:
                key_pressed = True
                print('key down')
        elif key_pressed == True:
            if key.value()==1:
                key_pressed = False
                print('key up')
            
    key.irq(trigger=Pin.IRQ_FALLING|Pin.IRQ_RISING, handler=key_task)
    
    while True:
        utime.sleep(0.5)
    
    

    物联沃分享整理
    物联沃-IOTWORD物联网 » 《深入浅出:树莓派 RP2040 硬件接口功能与传感器模块使用大全》

    发表评论