项目描述 项目介绍
这个是由硬禾学堂发布的暑假在家天天练的活动。我选择的是基于RP2040的简易气象站。本次的目标是制作一个简单的气象台,能够实时播放5个城市的气象信息。
具体要求:
- RP2040 Game Kit板通过提供的ESP32-S2的WiFi模块连接网络
- 在RP2040 Game Kit上显示某一个城市的气象信息 - 时间、温度、湿度、 气压....
- 通过RP2040 Game Kit上的按键能够切换显示不同城市的信息 ,比如:上海、苏州、东京、洛杉矶、伦敦
设计思路
设计思路是通过对设计思路是通过使用Thonny对RP 2040模块进行编程之后,先让esp32模块能够连接上WiFi。然后当连接上网络之后,开始搜索心知天气网提供的天气情况,然后再传到RP2040的屏幕上,之后便会在RP2040的屏幕上显示第一个城市的天气情况,当点击RP2040上的B按键时,便会跳转到下一个城市,从而实现五个城市之间的切换。
运行框图
硬件介绍
- 采用树莓派Pico核心芯片RP2040: 双核Arm Cortex M0+内核,可以运行到133MHz264KB内存性能强大、高度灵活的可编程IO可用于高速数字接口片内温度传感器、并支持外部4路模拟信号输入,内部ADC样率高达500Ksps、12位精度支持MicroPython、C、C++编程。
- ESP32模块:ESP32是由我国的乐鑫公司设计研发的一款可作为独立系统运行应用程序或是主机 MCU 的从设备,通过 SPI / SDIO 或 I2C / UART 接口提供 Wi-Fi 和蓝牙功能。
二、主要代码
- 网络部分
WiFi连接部分,使用的是at的连接方式,我并没有在esp32上写程序而是直接在rp2040上写了网络连接的程序network直接来调用他。下图的代码中可以随意更改网络设置,只要在有wifi的地方都可以进行设置,其中cmd_connectRouter='AT+CWJAP="WIFI-2","W13950022382"的这个就是WiFi的名称和密码。
etwork.Network(uart=UART(0, baudrate=115200, tx=Pin(12), rx=Pin(13), timeout=3000, timeout_char=1000),
recvInfo="",
cmd_retore='AT+RESTORE',
cmd_mode='AT+CWMODE=1',
cmd_inquiry='AT+CIPSTA?',
cmd_connectRouter='AT+CWJAP="WIFI-2","W13950022382"',
cmd_httpget = 'AT+HTTPCLIENT=2,0,\"https://api.seniverse.com/v3/weather/now.json?key=S2mKKog4GYXPm17kk&location=beijing&language=en&unit=c\",,,2',
cmd_ack='OK'
)
而这一次的network网络模块我也进行了一定的编写,以下就是我改编写的主要代码部分,可以达到一个分段查找的作用.
def httpGet(self):
print('Start Get Weather info from seniverse')
self.uart.write(self.cmd_httpget + '\r\n')
time.sleep(1)
recv_str = self.uart.read().decode()
list_str = recv_str.split('\r\n+HTTPCLIENT:')
list_str2 = []
if len(list_str2) > 2:
print('存在分段发送...')
for item in list_str:
start = item.find(',')
list_str2.append(item[start+1:])
recv_str1 = ''
for item in list_str2[1:]:
recv_str1 += item
self.recvInfo = recv_str1
if len(self.recvInfo) == 0:
return False
else:
return True
2.各个天气气象信息获取
获取天气和温度我们可以通过心知天气的API进行。首先要通过在心知天气注册属于自己的账号,然后得到自己的秘钥然后才能得到访问的权限。主要的步骤为通过esp32的wifi库连接到互联网通过esp32的http库,向心知天气的服务器发送请求获取天气和温度的数据,获取到的数据格式为json,对json格式的数据进行解析,然后就能获取需要的内容了 。json是一种特殊的数据结构,esp32中有一个内置的库,叫做cjson,用来处理json格式的数据,并且获取内容。
network_AT = network.Network(uart=UART(0, baudrate=115200, tx=Pin(12), rx=Pin(13), timeout=3000, timeout_char=1000),
recvInfo="",
cmd_retore='AT+RESTORE',
cmd_mode='AT+CWMODE=1',
cmd_inquiry='AT+CIPSTA?',
cmd_connectRouter='AT+CWJAP="WIFI-2","W13950022382"',
cmd_httpget = 'AT+HTTPCLIENT=2,0,\"https://api.seniverse.com/v3/weather/now.json?key=S2mKKog4GYXPm17kk&location=beijing&language=en&unit=c\",,,2',
cmd_ack='OK'
)
3.城市切换部分
城市切换部分,我使用的是一个while的循环函数。每当要连接上网络之后,就会显示出第一个城市的天气情况。然后我选择的是在每一次切换天气情况之前都要再进行一次网络搜索,这样能保最大限度的保证气象的精准性。然后所以我设置的这个按键是b键,按第一次是进行搜索,是进行网络搜索,再按一次才是切换到下一个城市。如果说一旦网络连接没有成功的话,这时候就会再次跳出进行重新进行网络连接。
while True:
if network_status == 0:
if network_AT.connectNetwork() == True:
print('config network Done!')
network_status = 1
else:
network_status = 0
print('NetWork Config Error!')
elif network_status == 1:
if network_AT.httpGet() == True:
count = (count+1) % 5
network_AT.cmd_httpget = 'AT+HTTPCLIENT=2,0,\"https://api.seniverse.com/v3/weather/now.json?key=S2mKKog4GYXPm17kk&location=' + pos[count]+'&language=en&unit=c\",,,2'
time.sleep(3)
network_status = 3
print('HttpGet Done!')
else:
network_status = 2
elif network_status == 2:
network_status = 1
time.sleep(1)
print('HttpGet try again!')
elif network_status == 3:
4.屏幕显示部分
屏幕部分需要先下载st7789的库,然后我这里使用的是一个display的函数来运用,也可以直接用电子森林上已经开源的开源项目。这里我设置使屏幕呈现了时间日期,气压,湿度。天气的多种气象信息。
while True:
if network_status == 0:
if network_AT.connectNetwork() == True:
print('config network Done!')
network_status = 1
else:
network_status = 0
print('NetWork Config Error!')
elif network_status == 1:
if network_AT.httpGet() == True:
count = (count+1) % 5
network_AT.cmd_httpget = 'AT+HTTPCLIENT=2,0,\"https://api.seniverse.com/v3/weather/now.json?key=S95Bj6jTY544NZSY5&location=' + pos[count]+'&language=en&unit=c\",,,2'
time.sleep(3)
network_status = 3
print('HttpGet Done!')
else:
network_status = 2
elif network_status == 2:
network_status = 1
time.sleep(1)
print('HttpGet try again!')
elif network_status == 3:
str_start = network_AT.recvInfo.find('{')
str_end = network_AT.recvInfo.find(']}')
weatherInfo_str = network_AT.recvInfo[str_start:str_end+2]
weather_json = ujson.loads(weatherInfo_str)
weather_location = weather_json['results'][0]['location']['name']
print(weather_location, end=' ')
weather_now = weather_json['results'][0]['now']['code']
print(weather_now, end=' ')
weather_temp = weather_json['results'][0]['now']['temperature']
print(weather_temp, end='℃ ')
weather_time = weather_json['results'][0]['last_update']
print(weather_time)
weather_humidity = weather_json['results'][0]['now']['humidity']
print(weather_humidity)
weather_pressure = weather_json['results'][0]['now']['pressure']
print(weather_pressure)
str1="/tianqi/"
str2=str(weather_now)
str3=".bin"
pic=str1+str2+str3
print(pic)
f_pic = open(pic, 'rb')
buf=f_pic.read(5000)
display.fill(st7789.BLACK)#清屏
display.blit_buffer(buf,10,0, 51,0)
display.text(font2, weather_location, 10, 40)
display.text(font2, weather_temp+"Celsius", 35, 150)#温度
display.text(font2, weather_time[11:16], 30, 200)
display.text(font1, weather_time[0:10], 60, 0)
display.text(font2, 'humidity:'+weather_humidity, 0, 120)
display.text(font2, 'pressure:'+weather_pressure, 0, 75)
network_status = 4
elif network_status == 4:
pass
if p5.value() == 0:
network_status = 1
time.sleep_ms(100)
三、主要难题及解决方法、未来的计划或建议
遇到的主要难题是在一开始进行烧录esp 32固件和rp 2040的时候经常烧录不进去。后来为了使用按住复位重新插入电源的方式来解决。然后刚开始使用thonny的时候,经常报错,不熟悉,因为平常在学校学的是c语言和c++。经常打错。经常格式导致经常报错。后来全部改正之后也经常报错,也得到了相应的解决办法,多按几次便可以了。然后再进行网络连接的时候常常会连不上。被原因后来通过修改了网络连接里面的代码也可以得到了很好的解决。
在未来的时间里,我会继续努力,进一步学习自己的专业知识,不断巩固自己的专业知识,让自己能够更好的适应各种板子的使用方法,学习到更多的使用技巧。也很感谢硬禾学堂这一次提供了这一次机会,让我们在暑假能够在家自己动手练习起来。未来的话还有一点小建议,就是希望硬禾学堂能够多多再多上几节直播教学课,让我们更好的更全面的学习。