感谢21ic和Nordic所提供的nRF7002DK的评测 。nRF7002 DK是nRF7002 Wi-Fi 6协同IC的开发套件,它包含了在单板上启动开发工作所需的一切。这款DK具有一个nRF53多协议系统级芯片(SoC),作为nRF7002的主处理器。这款DK支持低功耗Wi-Fi应用的开发工作,并支持实现OFDMA、波束成形和目标唤醒时间等Wi-Fi 6功能。
1 开发环境的准备
要使用nRF7002 DK,首先要下载Nordic所提供的3个开发工具:
- nRF Connect for Desktop(https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-desktop/Download)
- nRF Command Line Tools(https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools/Download)
- nRF Connect Extension Pack for VSCode,从VSCode内部的插件市场下载并安装。
前两个工具是必须的,而第三个工具对于习惯于使用VSCode的开发者来说,是个非常方便的利器。
按照官方推荐的做法,接下来是使用nRF Connect for Desktop中的Toolchain Management安装nRF Connect SDK,这个软件包包括开发软件的全部工具和源代码。这个SDK是托管在Github上的,在国内下载速度较慢,而且Toolchain Management如果安装的过程中因为网络原因不能完全下载它有时也会显示安装成功,给后面的开发带来较**烦。我建议从Nordic中国团队提供的百度网盘上下载SDK和工具链。链接为:https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog%2F%E5%BC%80%E5%8F%91%E4%BD%A0%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AANCS(Zephyr)%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%2Fncs_v2.4.0&parentPath=%2F,密码是y8fb。官方有个中文视频教程,虽然是前几年录制的,但是仍然值得看看:http://www.eeyxs.com/livebroadcast/index/playback.html?tid=410&cid=4805。
安装以上工具成功后,就可以随便打开一个例子测试一下。比如点灯程序在v2.4.0\zephyr\samples\basic\blinky目录下面。使用VSCode打开这个目录后,就可以看到Quick Setup界面进行基本的配置。然后创建构建配置,就可以完成编译、下载和调试了。
这里有几点注意事项:
- 第一次对板子的烧写最好使用nRF Connect for Desktop中的编程工具完成,因为VSCode插件大概率会失败,一般第二次就可以使用VSCode插件烧写了;
- 有时VSCode不能检测到设备,可以退出VSCode再进入试试;
- 如果没有打开一个nRF Connect SDK的例子,很可能nRF Connect插件不能正常显示,所以一定先打开一个例子目录,再点击nRF Connect插件。
总体上,Nordic提供的工具还是非常全面,使用也比较便捷。其VSCode插件的用法和华为的DevEco Device Tools很像,上手也很容易。
2 修改MQTT程序接入巴法云
Nordic提供了上百个示例程序,下面我们就从其MQTT示例出发,对其进行修改,实现接入国内的巴法云服务器,并实现手机App对设备的控制。巴法云服务器虽然也支持MQTT,但是它的端口、认证方式和主题用法都和其他服务器不同,所以需要修改的地方还是比较多的。
2.1 MQTT示例的整体结构
MQTT的整体架构如下图所示。
nRF Connect SDK完全依赖Zephyr实时操作系统。模块间通信使用 Zephyr message bus (zbus)机制在模块间通过信道(channel)收发消息,采用的是发布/订阅机制。该例程的主要模块如下表所示。
模块 观察信道 订阅角色 描述
Trigger 无 按时间或者通过按钮触发向trigger信道发送消息
Sampler Trigger Subscriber 每次从trigger信道接收到消息,就产生样本数据。样本数据会发送到 payload 信道。
Transport Network Payload Subscriber 处理MQTT连接。只要网络可用,自动连接并保持MQTT连接。从网络信道接收网络状态消息。从 payload信道接收消息。
Network 无 启动后自动连接Wi-Fi或LTE。在 network 信道发送网络状态信息。
LED Network Listener 监听 network信道的网络状态信息。 如果网络连接,板卡上的LED 1 (丝印为LED 2)点亮。
Error Fatal error Listener 从 fatal error 信道接收错误信息。如果在fatal error 信道收到信息,默认动作是重启设备。
考虑到我们的需求,将做以下几点修改:
- 修改WiFi和MQTT网络相关参数;
- 修改Transport模块,改变MQTT的主题,并在接收到MQTT消息后将其发送LED模块;
- 增加一个Command信道,将Transport模块的MQTT消息传递给LED模块;
- 修改LED模块,当接收到MQTT消息后根据其中内容控制LED灯的亮灭。
2.2 利用Kconfig对系统参数进行修改
nRF Connect SDK的一个特色之处,是它的很多参数可以从Kconfig工具中修改,并且其Changes标签可以清晰地显示都做出了哪些修改。下图就是我们通过Kconfig对一些系统常量的修改,包括服务器地址、端口号、发布和订阅的主题,以及WiFi接入点的参数。
2.3 对Transport模块的修改
MQTT示例所采用的发布和订阅的主题格式是:client_id/topic,但是巴法云的主题不包括client_id,所以修改Transport的topics_prefix模块,将下面的语句
len = snprintk(pub_topic, sizeof(pub_topic), "%s/%s", client_id,
CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC);
……
len = snprintk(sub_topic, sizeof(sub_topic), "%s/%s", client_id,
CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC);
修改为
len = snprintk(pub_topic, sizeof(pub_topic), "%s", CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC);
……
len = snprintk(sub_topic, sizeof(sub_topic), "%s", CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC);
2.4 增加COMMAND通道以实现对LED的控制
为了实现MQTT平台对LED灯的控制,我们增加了COMMAND通道的定义,当Transport模块接收到MQTT平台发来的消息,通过COMMAND通道进行发布,而LED模块订阅该通道用于处理MQTT平台的消息。
在message_channel.h中增加COMMAND_CHAN的定义:
ZBUS_CHAN_DECLARE(TRIGGER_CHAN, PAYLOAD_CHAN, NETWORK_CHAN, FATAL_ERROR_CHAN, COMMAND_CHAN);
在message_channel.c中,增加如下宏:
ZBUS_CHAN_DEFINE(COMMAND_CHAN,
int,
NULL,
NULL,
ZBUS_OBSERVERS(IF_ENABLED(CONFIG_MQTT_SAMPLE_LED, (, led)), sampler),
ZBUS_MSG_INIT(0)
);
修改Transport模块的on_mqtt_publish函数,当收到MQTT消息后通过COMMAND通道进行发布。
static void on_mqtt_publish(struct mqtt_helper_buf topic, struct mqtt_helper_buf payload)
{
LOG_INF("Received payload: %.*s on topic: %.*s", payload.size,
payload.ptr,
topic.size,
topic.ptr);
char cmd[100];
memset(cmd, 0, sizeof(cmd));
strncpy(cmd, payload.ptr, payload.size);
zbus_chan_pub(&COMMAND_CHAN, cmd, K_NO_WAIT);
}
2.5 对LED模块的修改
nRF7002DK开发板中有两个LED,丝印为LED1和LED2,在MQTT示例中,分别对应这LED_0和LED_1。其中LED_1是用来显示网络状态的,连接上服务器即亮灯,否则灯灭表示网络未连接。我们增加了对LED_0的控制,根据COMMAND通道传输来的控制命令进行开灯和关灯的操作。
#define LED_0_GREEN 0
……
void led_callback(const struct zbus_channel *chan)
{
int err = 0;
const enum network_status *status;
const char * cmd;
if (&NETWORK_CHAN == chan) {
……
}
} else if (&COMMAND_CHAN == chan) {
if (!device_is_ready(led_device)) {
LOG_ERR("LED device is not ready");
return;
}
/* Get led status from channel. */
cmd = zbus_chan_const_msg(chan);
LOG_INF("Received command: %s", cmd);
if(strcmp(cmd, "on") == 0)
{
err = led_on(led_device, LED_0_GREEN);
if (err) {
LOG_ERR("led_on, error: %d", err);
}
}
else if (strcmp(cmd, "off") == 0)
{
err = led_off(led_device, LED_0_GREEN);
if (err) {
LOG_ERR("led_off, error: %d", err);
}
}
}
}
3 测试
程序修改完成后,使用VSCode工具链编译、下载之后,程序就可以正常运行了。从下面的日志可以看出,程序连接到手机提供的热点后,就连接MQTT服务器,并订阅light002主题,并定时发布light001主题。我们使用巴法云的控制台或者巴法App进行开关灯的操作,nRF7002DK收到on/off指令后执行开关灯的操作,完全达到了预期的目的。
按照计划,本来还要测试蓝牙和NFC功能,虽然nRF Connect SDK提供了这方面的例子,但是均未适配nRF7002DK开发板,也没有提供适配的文档,所以只好暂时搁下,待日后再测试。
4 总结
我对nRF 7002DK进行了全面的测试和评估,该产品具备完备的功能设计,能够满足物联网用户的需求并解决实际问题。同时,产品的配套开发工具也表现出了出色的实用性。它提供了友好的用户界面、易于上手的操作方式,并且一站式提供了开发所需要的全部工具,使开发人员能够更高效地进行嵌入式固件开发工作。
值得一提的是,nRF Connect SDK在嵌入式固件开发领域具有显著的前瞻性。nRF Connect SDK是一套功能强大且灵活的开发工具包,为开发人员提供了丰富的接口和大量的示例程序,使得他们能够更轻松地实现各种嵌入式固件应用。该SDK不仅支持多种无线通信协议,还提供了一系列先进的功能模块,如低功耗模式、安全保护等,进一步提升了开发效率和系统性能。因此,nRF Connect SDK在嵌入式固件开发上的前瞻性为产品的应用前景增添了更多的可能性。
|