视频演示
项目介绍
本项目的名称是"基于树莓派Pico W的简易网络天气时钟",以树莓派Pico W为主控板为核心,结合相关的模块实现对应的功能。
项目用到的主要模块有:
1、Pico W主控板
2、蜂鸣器模块
3、OLED显示模块
4、GPS模块
5、按键模块
项目中实现的主要功能有:
1、实时时钟显示,上电自动NTP网络对时
2、闹钟功能,闹钟时间随意设置,蜂鸣器响铃
3、GPS位置信息显示
4、天气信息显示,通过网络获取所在地区的天气状态和温度
5、LED指示程序运行状态
硬件接口如下:
Pico引脚 | 备注 | ||
LED | - | - | 内部引脚 |
蜂鸣器 | Data | GPIO16 | GPIO控制 |
GPS | TX | GPIO5 | Pico UART1的接收引脚 |
RX | GPIO4 | Pico UART1的发送引脚 | |
OLED | SCL | GPIO9 | IIC时钟 |
DAT | GPIO8 | IIC数据 | |
按键模块 | MID键 | GPIO28 | 功能选择和OLED界面切换 |
UP键 | GPIO21 | 闹钟小时调节(+) | |
DOWN键 | GPIO20 | 闹钟小时调节(-) | |
LEFT键 | GPIO19 | 闹钟分钟调节(-) | |
RIGHT键 | GPIO18 | 闹钟分钟调节(+) |
以上模块除了按键模块是制备模块以外,其它模块都是本次follow me第一期指定的模块。
树莓派Pico W使用MicroPython进行开发,MicroPyhton继承了Python语言的特点:简单易学、高级语言、解释型语言、可移植性、面向对象、强大的功能和丰富的库等。
另外,在对字符串的处理上MicroPython也非常灵活和便捷,特别是对于OLED这种显示类的设备来说,非常方便。
本项目根据功能进行了模块化的编程,每个功能都有自己对应的.py文件,方便管理。
alarm.py主要实现了闹钟检测和处理函数
button.py主要实现按键按压和松手检测,并做了防抖处理,非常有效地避免了按键的误触发
main.py是主程序,实现所有功能的有序调度
mgps.py主要实现对gps数据的读取
micropyGPS.py是GPS数据采集的开源库
mtimer.py主要实现了2个定时器,一个是30ms的定时周期,用于按键的检测和防抖,即30ms检测一次按键,连续检测多次,根据实测连续检测4次就能很好的做到防抖和快速响应。另外一个定时器是1s周期,用来获取实时时间,并更新到OLED,还有一些需要周期调度的功能也是通过该定时器实现的。
ssd1306.py是OLED的开源库,不做过多说明
ufont.py是字体开源库
wifi.py主要实现了wifi联网,网络对时,天气信息的获取等与网络相关的功能。
下面分别详细展示关键功能及部分关键代码
主任务
主程序main.py实现所有模块的初始化和任务有序调度:
import time
from machine import Pin, UART
import wifi
import mtimer
import oled
import button
import mgps
import alarm
if __name__ == '__main__':
oled.oled_init() # oled初始化
oled.oled_display(32,25,"初始化...\n")
#uart_dbg = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) # uart0
#mgps.gps_init() # gps初始化
wifi.wifi_connect()
wifi.time_sync()
mtimer.timer_init() # timer初始化
while True:
#mgps.gps_data_update()
if button.get_button_status() != 3:
wifi.clear_weather_dis_state()
if button.get_button_status() == 1: # 闹钟
alarm.alarm_display()
elif button.get_button_status() == 2: # GPS
mgps.gps_data_update()
elif button.get_button_status() == 3: # 天气
wifi.get_weather()
alarm.alarm_check(wifi.get_now_hour(), wifi.get_now_min())
wifi联网
wifi联网单独做成了一个函数,该函数在mian.py里被调用,在初始化阶段就会被调用。
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
def wifi_connect():
# wait for connect or fail
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
time.sleep(1)
# Handle connection error
if wlan.status() != 3:
raise RuntimeError('network connection failed')
else:
print('connected')
status = wlan.ifconfig()
print('ip = ' + status[0])
print(rp2.country())
天气信息获取
天气信息是获取的心知天气的实时天气信息,因为是免费用户,所有获取到的信息非常有限,只包含天气状态和温度,还有更新时间,其它的都是收费项目。因此 本次也只能显示这些信息。
url = 'https://api.seniverse.com/v3/weather/now.json?key={}&location={}&language=zh-Hans&unit=c'
key = '******' #心知天气的密钥,换成自自己的
city = 'shanghai'
weather_dis_state = 0
def get_weather():
global weather_dis_state
if weather_dis_state == 0:
result1=urequests.get(url.format(key, city))
j1=ujson.loads(result1.text)
city_name = "城市:" + j1['results'][0]['location']['name'] + "\n"
weather = "天气:" + j1['results'][0]['now']['text'] + "\n"
temp = "温度:" + j1['results'][0]['now']['temperature'] + "℃"
oled.oled_display(0,10, city_name + weather + temp, True)
weather_dis_state = 1
print(weather_dis_state)
周期定时器
本项目使用到了2个定时器,一个是用于按键检测和防抖,另外一个是用于时间获取和显示和任务调度。
from machine import Timer, Pin
import button
import wifi
import oled
import mgps
import alarm
led = Pin("LED", Pin.OUT, value = 0) # led on board
tim1 = Timer(period=5000, mode=Timer.ONE_SHOT, callback = None)
tim2 = Timer(period=5000, mode=Timer.ONE_SHOT, callback = None)
def timer_init():
global tim1
global tim2
tim1.init(period=30, mode=Timer.PERIODIC, callback=lambda t:cb_button_check())
tim2.init(period=1000, mode=Timer.PERIODIC, callback=lambda t:cb_time_update())
def cb_button_check():
button.button_state_check() # ok键检测
button.button_right_state_check() # 右键检测
button.button_left_state_check() # 左键检测
button.button_down_state_check() # 下键检测
button.button_up_state_check() # 上键检测
def cb_time_update():
global led
date_time_now = wifi.get_time()
if button.get_button_status() == 0: # 时间显示
#date_time_now = wifi.get_time()
date_now, time_now = date_time_now.split(' ')
if alarm.get_alarm_status() == 'ON':
oled.oled_display(20,10, date_now + '\n ' + time_now + '\n ' + 'Alarm ' + 'On', True)
else:
oled.oled_display(20,10, date_now + '\n ' + time_now + '\n ' + 'Alarm ' + 'Off', True)
if alarm.alarm_is_active() == True and alarm.get_alarm_status() == 'ON':
if alarm.buzzer_get_pin() == 1:
alarm.buzzer_drv(0)
else:
alarm.buzzer_drv(1)
# 翻转led
if led.value() == 0:
led.value(1)
else:
led.value(0)
GPS位置信息获取
gps位置信息使用了开源库,mgps.py里面又对开源库做了一次封装。
from micropyGPS import MicropyGPS
from machine import Pin, UART
import oled
import button
uart_gps = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) # uart1
gps = MicropyGPS() #GPS
def gps_init():
global uart_gps
global gps
uart_gps = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) # uart1
gps = MicropyGPS() #GPS
def gps_data_update():
global uart_gps
global gps
if uart_gps.any() > 0:
try:
status = gps.update(uart_gps.read(1).decode("ascii"))
if status:
oled.oled_display(0,0, gps.latitude_string() + "\n" + gps.longitude_string(), True)
except:
print('gps error')
OLED显示
OLED也是使用开源库,oled.py也是对开源库做了一次封装。
"""
演示硬件:
SSD1306(OLED 128*64 IIC)
RP2040 Pico W
所需文件:
ufont.py
unifont-14-12917-16.v3.bmf
ssd1306.py
链接引脚:
SCL = 9
SDA = 8
使用字体: unifont-14-12917-16.v3.bmf
"""
from machine import I2C
from machine import Pin
import ufont
import ssd1306
import time
i2c = None
display = None
font = None
def wait(info, _t=5):
print(info)
time.sleep(_t)
def oled_init():
global i2c
global display
global font
# 请修改为对应 FootPrint
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq = 400000)
display = ssd1306.SSD1306_I2C(128, 64, i2c)
# 载入字体
# 使用字体制作工具:https://github.com/AntonVanke/MicroPython_BitMap_Tools
font = ufont.BMFont("unifont-14-12917-16.v3.bmf")
def oled_display(x_pos, y_pos, text_str, clr = False):
global font
global display
font.text(display, text_str, x_pos, y_pos, font_size=16, show=True, clear=clr, auto_wrap=True)
项目总结
通过本次follow me活动,我学习到了很多之前没有学习到的知识。
第一次使用MicroPython进行项目开发,第一次使用树莓派Pico,第一次使用MicroPython开发环境Thonny,第一次使用GPS模块等。
通过这次项目开发,深深地体会到了Python的便捷性,特别是在字符串的处理上,比C语言开发不知道强多少。另外就是Python的库太好用了,获取天气信息并解析json格式也是比C语言开发简单许多,居然几行代码就搞定了,大大提高了开发效率,实在是佩服。
另外,开发过程中也遇到了不少的问题,但是都一一解决了,解决问题的过程中也促使我对MicroPython有了更加深入的了解。
总而言之,非常感谢这次follow me的活动,收获太多,期待下一期。
之前发布帖子
【得捷电子Follow me第1期】任务1:熟悉micropython的基本语法
本帖最后由 xinmeng_wit 于 2023-7-3 12:59 编辑原视频有点问题,现在补充录制了一份,如下: