项目总结报告
一、项目介绍
该项目是硬禾学堂发布的“2022暑假在家一起练”基于rp2040游戏机的综合应用活动,使用MicroPython环境编写,完成了基于rp2040游戏机和esp32s2简易气象站的制作,并实现了以下功能:
1.通过esp32s2的wifi模块联网获取五个城市天气信息
2.通过驱动rp2040上的lcd显示温度、湿度、风速等气象信息
3.通过摇杆选择菜单栏切换选择不同城市气象信息
二、硬件介绍
esp32s2 wifi模块,rp2040嵌入式系统其中包括240*240LCD显示、摇杆和AB按键、usb转ttl模块,其中rp2040性能强大、高度灵活的可编程IO可用于高速数字接口片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度并且支持MicroPython、C、C++编程配套的ESP32 S2 开发板除了ESP32wifi模组之外还集成了USB TYPE -C接口,两个按键,一个电源指示灯,一个用户LED灯,2排10pin的排针,将重要IO引出。使用USB供电或通过排针3.3V供电。
xaxis = ADC(Pin(28))#控制杆x引脚
yaxis = ADC(Pin(29))#控制杆y引脚
buttonB = Pin(5,Pin.IN, Pin.PULL_UP) #B按钮引脚
buttonA = Pin(6,Pin.IN, Pin.PULL_UP) #A按钮引脚
spi_sck = Pin(2)
spi_tx = Pin(3)
reset = Pin(0,Pin.OUT)
dc = Pin(1,Pin.OUT)
spi=SPI(0,baudrate=31250000,phase=1,polarity=1,sck=spi_sck,mosi=spi_tx)
三、设计思路
首先进行程序初始化,显示出开机界面,等待三秒后,在屏幕上显示菜单栏包括:厦门、北京、上海、天津、武汉五个城市选项,通过摇杆的上下移动可以切换选择城市,选好后按下B键跳转执行esp32s2 at指令连接网络并通过心知天气api获取城市天气信息通过json转码后显示在屏幕上,此时按下A键返回到菜单界面可以通过摇杆再次选择城市
四、实现功能介绍
1.esp32s2模块的联网功能
首先接线将 ESP32 连接到 rp2040,并把esp32上的rx和tx分别接到树莓派的tx和rx上,并通过AT指令联接网络
def show_weather(position):
network_ = network.Network(uart=UART(0, baudrate=115200, tx=Pin(12), rx=Pin(13), timeout=3000, timeout_char=1000),
recvInfo="", # receive buffer global variable
cmd_retore='AT+RESTORE',
cmd_mode='AT+CWMODE=1', # config as station
cmd_inquiry='AT+CIPSTA?', # inquiry the IP address
cmd_connectRouter='AT+CWJAP="H1deFox","7896541230"', # connect to Router
cmd_httpget='AT+HTTPCLIENT=2,0,\"https://api.seniverse.com/v3/weather/now.json?key=SQ8FJShBtKSB_xyt9&location='+position+'&language=en&unit=c\",,,2',
cmd_ack='OK'
)
print('正在连接wifi...')
while network_.connectNetwork() != True:
print('连接失败,正在重连...')
print('连接上wifi')
2.通过心知天气API获取天气信息
首先注册心知天气取得心知天气私钥,并输入到httpget中key的位置,取得城市的不同气象信息再通过json的解码显示到屏幕上,由于心知天气免费版所提供的json天气数据过少并且只能获取国内天气数据,所以我使用了15天试用版能获取更多json数据和信息情况
print('正在获取天气信息...')
while network_.httpGet() != True:
print('获取天气信息失败,正在重试...')
print('获取天气信息成功...')
print('正在跳转...')
str_start = network_.recvInfo.find('{')
# print(str_start)
str_end = network_.recvInfo.find(']}')
# print(str_end)
weatherInfo_str = network_.recvInfo[str_start:str_end+2]
# json_wrong = network_AT.recvInfo.strip()
# print(json_wrong[json_wrong.find('{'):])
# print(weatherInfo_str)
weather_json = ujson.loads(weatherInfo_str)
weather_location = weather_json['results'][0]['location']['name']
print(weather_location)
weather_now = weather_json['results'][0]['now']['code']
print(weather_now)
weather_text = weather_json['results'][0]['now']['text']
print(weather_text)
weather_temp = weather_json['results'][0]['now']['temperature']
print(weather_temp)
weather_time = weather_json['results'][0]['last_update']
print(weather_time)
weather_humi = weather_json['results'][0]['now']['humidity']
print(weather_humi)
weather_wind_speed = weather_json['results'][0]['now']['wind_speed']
print(weather_wind_speed)
str1 = "/tu/"
str2 = str(weather_now)
str3 = ".bin"
image = str1+str2+str3
print(image)
f_image = open(image, 'rb')
buf = f_image.read(8000)
display.fill(st7789.BLACK) # 清屏
display.blit_buffer(buf, 40, 0, 51, 0)
display.text(font2, weather_location, 100, 0)
display.text(font2, 'temp:'+weather_temp, 0, 85) # 温度
display.text(font2, 'time:'+weather_time, 0, 200)#时间
display.text(font2, 'humidity:'+weather_humi, 0, 120)#湿度
display.text(font2, 'windspeed:'+weather_wind_speed, 0, 160)#风速
display.text(font2, weather_text, 10, 50)
3.基本设置
因为主程序繁杂,所以将基本按键和颜色设置放在另一个程序里之后引用,主要定义了显示颜色和按键引脚,为之后菜单显示提供基础
import machine,uos
import st7789 as st7789
from fonts import vga2_8x8 as font1
from fonts import vga1_16x32 as font2
from machine import Pin,SPI,ADC,I2C
class Attribute:
white = st7789.WHITE#白
black = st7789.BLACK#黑
magenta = st7789.MAGENTA#洋红
blue = st7789.BLUE#蓝
red = st7789.RED#红
background = st7789.color565(0, 120, 120)
info = str(uos.uname()).split(',')#元组
pen_color = background
font1 = font1
font2 = font2
4.菜单的显示
菜单首先定义lines=5,并先通过select显示五个城市选项,通过推动摇杆改变摇杆方向来上下改变lines值从而切换城市
while True: # 菜单
selects = {0: '', 1: 'XiaMen', 2: 'BeiJing', 3: 'Shanghai', 4: 'Tianjin', 5: 'Wuhan'}
display.fill(0)
display.text(att.font2, ' CITY ', 70, 4, att.white, att.background,)
for lists in range(1, len(selects)):
display.text(att.font2, ' {0:^12}'.format(selects[lists]), 0, 40*lists, att.white)
def ping(change): return min(5, max(1, change))
while True:
w, h = int(board.xaxis.read_u16()/3000)-10, int(board.yaxis.read_u16()/3000)-11 # 摇杆数值
if w > 5:
lines += 1
next_line = ping(lines-5)
up = next_line-1
display.text(att.font2, '< {0:^12}>'.format(selects[next_line]), 0, 40*next_line, att.white, att.background)
if up == 0:
pass
else:
display.text(att.font2, '< {0:^12}>'.format(selects[up]), 0, 40*up, att.white)
if w < -5:
lines -= 1
next_line = ping(lines-5)
up = ping(lines-4)
display.text(att.font2, '< {0:^12}>'.format(selects[next_line]), 0, 40*next_line, att.white, att.background)
display.text(att.font2, '< {0:^12}>'.format(selects[up]), 0, 40*up, att.white)
5.按键确定和返回
首先定义联网获取数据为def show_weather(position),通过按下按键B切换lines并连接网络进入所选城市显示,再按下A键返回菜单栏
""" 点击b按键 """
if not buttonB.value():
show_weather(selects[next_line])#进入所选城市天气信息
""" 等待a按键 """
while buttonA.value():
pass#返回菜单
break
五、遇到的问题和解决方法
1.开始时我选用arduino编写,但是发现无法驱动st7789这款屏幕,查找之后发现这块屏幕是国产代替屏,st7789驱动库无法使用,并且对esp32s2单独编写时,用usb转ttl模块连接3.3v上电时会进入下载模式,无法正常编写,后面转用micropython编写才成功
2.转换到micropython时看不懂代码,后面通过老师讲解和自己的学习,看了一些电子森林案例并在交流群里问了很多大神才慢慢摸索成功
3.代码很多地方很杂乱没有简洁化,全部做完才慢慢删减重复代码
4.在开始运行程序时很容易报错并且不稳定,没找到好的方法只能多上传几次
5.有一些自己的想法没办法实现,希望以后通过学习能实现
6.写程序时发现只能获取一个城市的天气信息,并且networkAT指令总是报错,发现是AT指令不能是局部指令要不然会出现未定义的问题,加入lines循环就可以获取选择城市的气象信息了
7.有些库不知道怎么调用,总是报错,只能寻找使用替代方法
六、未来规划
1.简化自己的代码,多学习micropython相关知识,通过学习将之前的方案实现
2.树莓派和esp32联网具有多样性,以后会学习制作复杂的项目
3.熟悉程序开发环境、学习计算机系统的操作方法
4.程序还存在很多疏漏和不合理之处。比如,程序复杂冗长,如果时间充裕,我将在不改变程序运行结果的基础上,简化程序,使每一句更加精辟,总体上更加简化。另外,在程序的外观上,我由于时间问题,没有做更多的修饰,运行起来显得比较死板、枯燥乏味。如果增添一些色彩和其他效果,程序也许会更加完美。