【得捷电子Follow me第1期】作品提交+ 在线新闻浏览器
[复制链接]
【得捷电子Follow me第1期】+ 在线新闻浏览器
2aaf57ea8f1a8ab31c50d3a74b0f25ab
- 项目描述
这款《在线新闻浏览器》使用了Raspberry Pi Pico W开发板及OLED屏幕模块,充分利用了Raspberry Pi Pico W强大的WIFI联网能力及大内存(本项目需要显示中文,而所用的中文字库文件就达到了近500KB)。而且所用的MicroPython也支持高级编程语言,支持requests及Json解析,大大方便了信息流的获取及处理,想想如果这是传统单片机,实现同样的功能要多少代码量。
首先,回顾下Raspberry Pi Pico W所搭载的资源,可以看到还是非常丰富的,为实现各类物联网项目打下了坚实基础。
采用了 Raspberry Pi 官方自主设计的 RP2040 微控制器芯片
• 搭载了双核 ARM Cortex M0 + 处理器,运行频率高达 133MHz 灵活时钟(可超频)
• 内置了 264KB 的 SRAM 和 2MB 的片上 Flash
• 板载2.4GHz无线接口芯片(802.11n或Wifi4)。
• 支持蓝牙 5.2
• 邮票孔设计,可直接焊接集成到用户自主设计的底板上
• USB1.1 主机和设备支持
• 支持低功耗睡眠和休眠模式
• 可识别为 USB 大容量存储器进行拖放式程序更新
• 多达 26 个多功能的 GPIO 引脚
• 2 个 SPI,2 个 I2C,2 个 UART,3 个 12 位 ADC,16 个可控 PWM 通道
• 精确的片上时钟和定时器
• 温度传感器
• 片上加速浮点库
• 8 个可编程 I/O (PIO) 状态机,用于自定义外设支持
在线新闻浏览器项目主要分3个模块。
第一部分
连接WIFI
第二部分
获取新闻
第三部分
在OLED屏幕上显示新闻
- 各功能对应的主要代码片段及说明
import time
import network
import urequests
import urequests as requests
import ujson
from machine import Pin, I2C, ADC, PWM
from time import sleep
import ufont
import ssd1306
ssid = 'ccqp'
password = ''
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
# 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] )
import ntptime
def sync_ntp():
ntptime.NTP_DELTA = 3155644800#3155673600#3155644800 # 可选 UTC+8偏移时间(秒),不设置就是UTC0
ntptime.host = 'ntp1.aliyun.com' # 可选,ntp服务器,默认是"pool.ntp.org"
ntptime.settime() # 修改设备时间,到这就已经设置好了
sync_ntp()
# 已经设置好了,随便用
from machine import RTC
rtc = RTC()
print(rtc.datetime())
#可以通过字典对象上值的键来获取每个单独的JSON值
##可借助ujson库来解析内容
import urequests
Url = 'https://api.seniverse.com/v3/weather/now.json?key=SK6E_7MBhPJr0_Cs3&location=shenzhen&language=zh-Hans&unit=c'
r = urequests.get(Url)
r.json()
print (r.json()['results'][0]['location']['name'],r.json()['results'][0]['now']['temperature'],r.json()['results'][0]['now']['text'])
i2c = I2C(1, scl=Pin(7), sda=Pin(6), 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")
request_url = 'https://v.juhe.cn/toutiao/index?key=5f78766a1e82f665528a474b411a59dc&type=guoji&page=1&page_size=10&is_filter=1'
resp = urequests.get(request_url)
#resp_json = ujson.loads(resp.text)
print (resp.json()['result']['data'][0]['title'])
print (resp.json()['result']['data'][1]['title'])
print (resp.json()['result']['data'][2]['title'])
print (resp.json()['result']['data'][3]['title'])
titile=resp.json()['result']['data'][1]['uniquekey']
print (titile)
request_url1 = 'https://v.juhe.cn/toutiao/content?key=5f78766a1e82f665528a474b411a59dc&uniquekey='+ titile
#resp1 = urequests.get(request_url1)
#print (resp1.json()['result']['content'])
font.text(display, resp.json()['result']['data'][0]['title'], 0, 0, font_size=16, show=True, clear=True)
font.text(display, resp.json()['result']['data'][1]['title'], 0, 16, font_size=16, show=True, clear=True)
font.text(display, resp.json()['result']['data'][2]['title'], 0, 32, font_size=16, show=True, clear=True)
font.text(display, resp.json()['result']['data'][3]['title'], 0, 48, font_size=16, show=True, clear=True)
第一部分,就不再赘述。
第二部分,也是最有难度的部分是获取新闻,如何连上新闻服务器,获取并返回我们要的新闻?
本文重点讲解此部分代码。
https://www.juhe.cn/
我们打开他的官网,找到API,再找到新闻头条。
可以看到普通会员(免费注册的)每天可以查询50次。
接下来我们看下接口文档及示例代码。
可以看到新闻列表的接口地址是http://v.juhe.cn/toutiao/index
新闻正文的接口地址是 http://v.juhe.cn/toutiao/content
主要的代码就是Python下的Request语句。这条语句的主要参数有三个参数,url、type和key。
第一个参数url也就是网址,上文提到了新闻列表和新闻正文各自对应的url。
第二个参数是type,也就是你要获取的新闻的类型:
top(推荐,默认)
guonei(国内)
guoji(国际)
yule(娱乐)
tiyu(体育)
junshi(军事)
keji(科技)
caijing(财经)
youxi(游戏)
qiche(汽车)
jiankang(健康)
第三个参数,就是在聚合数据免费注册的普通会员,每个应用对于的密钥。
比如,这是我免费申请的Key。
以上3个参数弄明白后,就可以着手准备咱们的micropython代码了。
在这里主要参考了一段天气预报的代码,如下:
import urequests
Url = 'https://api.seniverse.com/v3/weather/now.json?key=SK6E_7MBhPJr0_Cs3&location=shenzhen&language=zh-Hans&unit=c'
上面这句至关重要,可以看到几个重要参数,第一个就是网址url,第二个就是key也就是密码,第三个就是位置,这里设置为深圳。
r = urequests.get(Url)
urequests.get这句就是核心语句,从指定网址的指定接口抓取信息,抓到的信息存在对象r中。
r.json()
将数据以json的格式整理。
json的全称为:JavaScript Object Notation,是一种轻量级的数据交互格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
简单来说:json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。
我们如果直接把带参数的url输入到浏览器,就会返回一长串看似杂乱的字符串,其实这就是Json格式的信息。
为了便于读懂这段Json格式的信息,我们可以使用“聚合数据”自带的JSON在线格式化工具,方便整理读懂信息。
https://tool.juhe.cn/
按上图的逻辑关系:
['results'][0]['location']['name']就对应“深圳”
['results'][0]['now']['temperature']就对应“29”
['results'][0]['now']['text']就对应“阴”
所以最后把你想要的信息打印出来。
print (r.json()['results'][0]['location']['name'],r.json()['results'][0]['now']['temperature'],r.json()['results'][0]['now']['text'])
运行结果如图红框内。
理解了天气预报的逻辑,获取新闻就简单了。
request_url = 'https://v.juhe.cn/toutiao/index?key=5f78766a1e82f665528a474b411a59dc&type=guoji&page=1&page_size=10&is_filter=1'
resp = urequests.get(request_url)
print (resp.json()['result']['data'][0]['title'])
print (resp.json()['result']['data'][1]['title'])
print (resp.json()['result']['data'][2]['title'])
print (resp.json()['result']['data'][3]['title'])
我们将带参数的网址粘贴到浏览器。
https://v.juhe.cn/toutiao/index?key=5f78766a1e82f665528a474b411a59dc&type=guoji&page=1&page_size=10&is_filter=1
因此,
['result']['data'][0]['title'] 就对应“小型飞机闯入禁区被法战机拦截:嫌犯高空抛下15个袋子 疑为毒品”
['result']['data'][1]['title'] 就对应“反复“退群”“返群”,美国把加入国际组织当作逛公园”
上面只是这条新闻的标题,那如果想要获取新闻的正文怎么办呢?
回到前面的介绍。
新闻正文的接口地址是 http://v.juhe.cn/toutiao/content
这里有两个关键参数,第一个仍然是密码,前文有说。
第二个参数就是uniquekey,这其实对应的是刚刚第一步获取新闻标题里JSON数据里的uniquekey。
我们直接把获取新闻正文的网址输入浏览器:
http://v.juhe.cn/toutiao/content?key=5f78766a1e82f665528a474b411a59dc&uniquekey=2f9c89949952eb81819adc104a75c949
titile=resp.json()['result']['data'][1]['uniquekey']
此句获取新闻的'uniquekey'
print (titile)
打印出'uniquekey'
request_url1 = 'https://v.juhe.cn/toutiao/content?key=5f78766a1e82f665528a474b411a59dc&uniquekey='+ titile
抓取新闻正文的链接
resp1 = urequests.get(request_url1)
抓取新闻正文
print (resp1.json()['result']['content'])
第三部分 中文显示
这里用到了
需要把上图3个文件下载到PICO W板卡上。
i2c = I2C(1, scl=Pin(7), sda=Pin(6), freq = 400000)
display = ssd1306.SSD1306_I2C(128, 64, i2c)
# 载入字体
# 使用字体制作工具:
font = ufont.BMFont("unifont-14-12917-16.v3.bmf")
font.text(display, resp.json()['result']['data'][0]['title'], 0, 0, font_size=16, show=True, clear=True)
font.text(display, resp.json()['result']['data'][1]['title'], 0, 16, font_size=16, show=True, clear=True)
font.text(display, resp.json()['result']['data'][2]['title'], 0, 32, font_size=16, show=True, clear=True)
font.text(display, resp.json()['result']['data'][3]['title'], 0, 48, font_size=16, show=True, clear=True)
执行结果如下图
MMMMMM
2. 功能展示及说明
功能展示如图所示,列出了4条国际新闻标题,由于MicroPython-uFont 默认超出边界不换行,因此标题未显示完全。
另外,由于此屏幕比较小,128*64,只能显示4行中文,而且没有按钮等翻屏工具,因此目前没有再深入编写进一步的功能,也算给后续开发留点悬念吧。
其他的展示:
任务1:熟悉micropython基本语法
这里要特别指出,单击要上传的文件,右键有“上传到/”就可以很便捷地实现程序上传功能。
另外,为了便于学习python语言,推荐以下网址:
任务2:驱动外设
- 点亮LED灯
- 驱动蜂鸣器
自己编写了一首《卡农》,代码见附件,效果见视频。
- 驱动OLED屏幕
任务3:同步网络时间
任务4:实现定位功能
由于在室内,GPS信号不支持,放到室外就好很多。
- 对本活动的心得体会
本次活动是我第一次开发树莓派,也是第一次体验Micro-Python,以往的开发经历比如51单片机及MSP430单片机,都需要特别关注处理器的底层细节,比如时钟、寄存器,还需要专门的烧录工具,而且由于51单片机及MSP430单片机的资源比较有限,时钟频率也不高,可玩性就不那么丰富,这次Digi-Key联合EEWORLD发起的"Follow me活动”,给了我一个完整的开发体验,Digi-Key上有丰富的外设资源,完全能满足我的开发需求。
最后附上全部代码,包括原创的《卡农》。
|