引言
几个月前,我曾体验过博流智能的 BL-HWC-G1 开发板,它上边有一块 BL602 模组,可以连接 WiFi。我当时试了试如何用 BL-IoT-SDK 发出 HTTP 请求,还写了这篇笔记:《让博流 BL602 连接互联网》。
最近看到今年的嵌入式竞赛开始了,博流赛道可选的 BL706 / BL604 两款平台中,BL604 也是可以使用 BL-IoT-SDK 来开发程序的。我刚好想做个 COVID-19 疫情数据显示板,就选择用 BL604 这个平台来试试。
然后做好了如下图所示的这个装置,它会每 10 分钟联网通过一个疫情数据 API 获取当前确诊人数,并显示在地图上。(数据来源以 实时更新|新冠肺炎疫情地图 中的说明为准;因屏幕限制,各城市之间的分界线仅供示意)
这个装置内运行的程序主要可分为以下几个步骤:
- 通过 WiFi 联网,从 新浪的疫情数据 API 上下载 JSON 格式的数据,并存入 Flash(因为文件较大,内存存不下)
- 从 Flash 里分段读出刚才下载的数据,并查找江苏南部(不是苏南)、浙江北部、宣城及部分周边城市当前的确诊数量
- 把确诊数量画在地图上,通过 SPI 传给电子墨水屏显示出来
这整体是个简单的装置,我把项目文件开源在了 GitHub 上,如果你想通过这个例子来了解如何使用 BL-IoT-SDK 实现联网、读写 Flash、通过 SPI 控制墨水屏等功能,可以去看代码了解详情:https://github.com/CSY-tvgo/an-http-demo-on-BL602
后文也将 零散 地聊聊我在做这个装置的过程中遇到的一些问题。
所需组件
- BL604E_MB_V1.0 开发板(如果用其他的 BL60x 开发板,可能改改分配的引脚就可以)
- GDEW042T2 电子墨水屏(如果用其他的电子墨水屏,可能改改通信部分的代码就可以)
选择合适的疫情数据 API
用搜索引擎搜索 疫情数据 API
,可以发现百度、腾讯、阿里、网易、新浪等许多互联网厂商都有公开的接口,还有一些热心网友开发了比如 DXY-COVID-19-Data 之类的项目,也能供大家获取数据。
了解了解这些 API 的详情,可发现 DXY-COVID-19-Data 提供的 API 功能很全,支持按城市来请求数据,每次传输的数据所需的空间都很小,非常适合内存有限的平台使用。
但是,这个 API 毕竟是由个人来维护的,很不幸它并不是一直都稳定,我只好看了看其他 API。其他 API 几乎都是一次性传来几百 KB 的包含所有城市的数据,BL604 的内存是存不下的,所以我们要考虑把数据存进 Flash 然后再从 Flash 里一段一段读出来解析。
对比了一下各种 API 提供的数据的格式,我最终选用了 新浪的疫情数据 API。在电脑上用测试工具(图中的是 REQBIN)向这个 API 发出 GET 请求,可发现,需要接收的数据有大约 200 多 KB。
擦 / 写 / 读 Flash
在 bl_iot_sdk\customer_app\peripheral\demo_flash
可以得知,我们能用以下三个函数来按地址擦 / 写 / 读 Flash。
hosal_flash_raw_erase()
hosal_flash_raw_write()
hosal_flash_raw_read()
在 bl_iot_sdk\flash_tool\chips\bl602\partition\partition_cfg_2M.toml
可以看到 Flash 分区信息,参考 demo_flash
里的代码,我们可以在地址 [0x192000, 0x1E9000) 的共约 356KB 的 media 分区里存下下载的数据。
C 语言标准库的 string.h
里提供了一些可以方便地处理字符串的函数。我在 get_covid19_data.c
里写了 strstr_from_flash()
和 strncpy_from_flash()
,相当于 Flash 版的 strstr()
和 strncpy()
,可方便地从 JSON 格式的数据中查找到所需的数据并复制出来。
绘图
电子墨水屏是老角色了,这次我又用了它。不过这次我优化了 eInk.c
,增加了一些新的简单的绘图函数,可以更容易地画点、画线、画矩形、打字、加文本框,详情可以看代码。
void eInk_init();
void eInk_resetCanvas();
void eInk_show();
void eInk_drawPixel(int x, int y, uint8_t set_black);
void eInk_drawLine(int ax, int ay, int bx, int by, uint8_t set_black); // 只允许横线或者竖线
void eInk_drawRectangle(int ax, int ay, int bx, int by, uint8_t border_black, int fill); // fill: -1 (填白), 0 (不管), 1 (填黑)
void eInk_print(int left_top_x, int left_top_y, char *content);
void eInk_print_withbox(int left_top_x, int left_top_y, char *content);
不足
可能因为我的代码在有些地方分配内存不太安全,读写 Flash 时操作系统有一定几率会因为越界访存、非法指令等问题出现内核崩溃,而我暂时还不知道如何分析这个开发板的 coredump,就暂时还没找到原因。感兴趣的读者们或许可以尝试解决这个问题。