《深入浅出:树莓派 RP2040 硬件接口功能与传感器模块使用大全》
树莓派-RP2040
实物图
引脚图
IDE工具(thonny)
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定时器
初始化并启动定时器:
mode: 定时器模式(Timer.ONE_SHOT , Timer.PERIODIC)
period:定时器周期
callback:定时器回调函数
启动一个定时器:
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
num代表ws2812的数量
sm是内核,目前需要设置为0
pin是使用的引脚
n是第几个ws2812
r, b, b是红绿蓝颜色
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)