我们组装最简单的ZigBee网络,在Mbed下编程,通过MQTT进行通信

本文是一个很棒的入门级培训班,内容涉及如何将XBee模块与板载Mbed OS的微控制器结合使用。 ZigBee是智能家居系统中长期牢固的标准(例如,它与Samsung SmartThings集线器中的Z-Wave一起使用,请参阅我们的文章),其特点是功耗低,易于使用,并且最有趣的是,它具有创建功能自配置网状网络。您将在研讨会上看到确实如此-我们将通过便捷的可视化工具查看这种网络的结构。

假定您已经知道ZigBee是什么以及它的用途。现在,您想连接第一个XBee模块并解决它的问题,而无需对模块本身进行编程,而只是将其用作通信接口。最后,我们将通过一个临时的MQTT网关将所有数据发送到任何地方,甚至到本地服务器,甚至到Internet。我们决定将Mbed示例中的所有内容显示为对于初学者RTOS而言最简单,最易访问的示例。您将确信一切都“开箱即用”,并且即使在此之前您仅与Arduino打交道,您也可以立即开始制作项目。



该手册将包括以下部分:

  1. XBee模块的连接和配置
  2. 将模块连接到网络
  3. 我们配置模块时不将其从屏蔽罩中移除
  4. 资料检索
  5. 传送资料
  6. 制作一个简单的MQTT网关

但是首先,要列出一个组件列表:为了完成上述所有操作,需要具备哪些组件。

所需组件


  • 两个Mbed兼容板。我们建议STM32 Nucleo培训板相对便宜,并且出于教育目的而受欢迎。那里的编程过程尽可能地简化:在免费的在线IDE中收集程序,下载组装的固件,然后将其“拖放”到板上,这将在系统中显示为闪存驱动器。采取哪种具体模型并不重要,但采取的不是最旧的模型,请注意内存量。例如,F401RE-我们仅出于确定性而给出,这样您就不会对它们的种类以及STM处理器的最初令人困惑的字母代码感到困惑。


  • XBee-. Digi. «» , , , MBee, , , , . / : , . / Pro: , , Pro .

  • XBee Shield V2 ( SeeedStudio). - , RX TX XBee-.

  • 一个带XBee连接器的USB-UART转换器。初始配置需要它。XBee模块本身没有配备USB接口(与它们无关)。仅在模块和计算机之间进行通信时才需要USB,并且在设备中,USB可以在更简单的UART上工作。

    XBee模块的插槽间距为2.0毫米-在公制系统中,这是电子产品的非标准标准(按美国标准,我们通常习惯于看到步骤2.54)。因此,不幸的是,这样的模块没有插入到面包板中,并且它们总是需要适配器。

    任何适配器都适合这里,我们从Waveshare那里选了一个:


XBee模块的连接和配置


您可以使用模块执行的最简单的操作是通过USB直接将其连接到计算机。我们将立即访问其配置参数。

安装XCTU


要使用XBee,有一个官方的XCTU程序。下载并安装。该文档说,在Ubuntu中,您需要将用户添加到组中dialout以使用非超级用户的端口-如果尚未这样做,请执行以下操作:

sudo usermod -a -G dialout <username>

从链接下载zip存档,其中将包含一个文件.run需要使其成为可执行文件(通过chmod +x _控制台或:鼠标右键-属性-权限)并运行./40002881_V.run

重要的是不要从根目录开始安装(不带sudo),否则以后会出现问题。

设置看起来像这样:



XCTU程序


安装后,您可以通过app在安装程序的目录中运行文件来启动程序(默认为- ~/Digi/XCTU-NG)。
 
外观如下:



在此程序中,您可以将现有模块通过适配器添加到USB端口。单击带有放大镜的发现按钮。弹出一个窗口,要求您选择端口-如您所见,程序正确检测到系统中存在端口/dev/ttyUSB0,这是我们的USB-UART适配器。



窗口建议勾选搜索。当然,有一种诱惑是一次检查所有以确保找到您的模块。但是搜索将持续很长时间。实际上,将这些框默认保留为选中状态,并为数据传输速度选择最常用的选项是很有道理的,如下图所示。通常,新模块默认为9600,并且出于培训目的,这已经绰绰有余,这里的速度对我们而言并不重要。



结果,如果一切成功,则会要求您选择找到的模块:发现



一个小错误:有时模块不是以非标准速度运行,在搜索过程中使用重置按钮手动重置模块并将其波特率重置为标准(9600)很有帮助。

更改模块参数


此外,我们从事模块配置。一堆参数将丢失,大多数参数最初是难以理解的。幸运的是,只需更改其中的一部分即可快速入门。

网络ID-PAN ID。一个通用的网络密钥,所有设备都必须相同,以便它们独立连接到网络。输入任意数字,在我们的例子中为



42。CE-启用协调器。如果为1,则此模块充当协调器。如果为0,则该模块充当路由器(Router)-实际上,它只是确保数据包通过自身通过网络。大多数主机通常是路由器。我们的网络中需要一个协调器和两个路由器,因此在这里放置一个。

还有一个“终端设备”(终端设备)的角色-一个不执行数据包传输工作,仅与其他路由器通信并执行其有用功能的模块。通常,他只是处于睡眠模式,并按设定的时间间隔醒来,并确定是否有任何消息。这样的模块可以由电池供电,而路由器和协调器应始终处于“在线”状态,因此,需要恒定的功率来维持整个网络的健康。我们现在不考虑这样的示例,因为每个人分配路由器的角色并观察网络将如何自动更改其配置更加有趣。



AP-API启用。操作模式。 XBee模块可以两种模式运行:AT或API。对于初学者而言,AT模式更容易,它是串行端口的透明替代,并通过AT命令与模块一起使用。但是,API模式的功能要丰富得多,它允许您远程配置模块,包含发件人地址,返回程序包的交付状态等等。另外,用于与XBee交互的库假定该设备在API模式下使用。因此,立即将其替换为API模式,这是通过在相应字段中设置单位来完成的。



模块的名称是“节点标识符”。为模块提供易于理解的名称的便捷选择。我们给它起一个名字-协调员。



之后,您可以使用铅笔按下按钮将设置刷新到模块中:



2.将模块连接到网络


现在,如果配置三个模块,我们将看到什么样的网络。XCTU程序具有相当方便的网络可视化程序,我们将清楚地看到拓扑。

我们将使用以下参数依次配置所有三个模块:
  • PAN ID-总数,例如42
  • AP(启用API)-设置为1(在API模式下工作)
  • NI(节点标识符)-为模块提供易于理解的名称(协调器,指示灯和开关,例如我们正在做的智能家居系统模型)。
  • CE(启用协调器)-将模块之一设置为1,它将成为协调器。

然后为所有模块通电。像这样放置它们:协调器将位于USB-UART转换器中,其他两个(路由器)将位于Nucleo顶部的XBee Shield板上。

如果您仔细地做所有事情,那么美好的事情就会发生。模块将自动连接到网络。您可以通过协调器与路由器进行远程通信。

看起来像这样。单击“发现同一网络中的无线电节点”按钮。



您将看到自动检测并添加了两个模块:


您可以即时更改它们的参数! 

仍然很棒:现在,如果您切换到右上角的网络工作模式,则可以看到网络地图。



用鼠标散布网络节点后,您将看到一个三角形。请注意,到达最右边模块的流量有两种方式。而且,如果您在太空中移动模块,您会发现情况已经改变,现在,也许另一个模块将变得“极端”。这是自配置网络的本质。

3.设置XBee模块而不将其从屏蔽罩中卸下


当然,不是通过计算机使用XBee模块,而是通过使用微控制器上的程序对其进行控制,将会更加有趣。也就是说,将其连接到STM32Nucleo板。
让我们讨论XBee模块如何与微控制器通信。让我们从一个小任务开始:如何配置模块而不将其从扩展挡板中移除?您必须承认,来回移动模块很不方便,同时您想尝试参数,这很奇怪为什么需要单独的USB-UART模块,因为理论上STM32Nucleo板上有一个。

解决方案很简单:我们需要将Nucleo板变成XBee模块和板上的USB转换器之间的桥梁。

想法的一般描述


我们使用的STM32微控制器板上有多个UART接口。每个这样的接口代表一个通信通道。其中之一连接到USB-UART转换器,因此我们可以通过终端中的USB与计算机进行通信。尚未使用其他两个。我们将XBee模块连接到其中一个,它也具有这样的通信通道。您可以选择任何UART,我们已为确定性UART1选择了它。

可以通过按板选择按钮,然后在“引脚排列”选项卡上的右上角以MBed形式查看引脚排列。出于习惯,很难感知这张彩色图片。这里有很多事情,因为开发板有很多接口,并且有两个引脚号:相对于微控制器(PA_5,PA_6-引脚编号)和相对于板(D13,D12-Nucleo板上的铭文,端子附近的编号相同)。


 
事实证明,在微控制器上,UART1接口将与XBee模块和UART2进行通信(与以前一样)与计算机进行通信。内部代码会将UART1重定向到UART2,反之亦然。



通过连接,它看起来像这样:



通过微控制器搭建“桥梁”


在我们的案例中,我们可以通过屏蔽板上的跳线设置要连接ZigBee模块的编号。 TX通信模块将连接到开发板的引脚2(微控制器上的PA_9),而RX连接到引脚8(又称为PA_10)。

它看起来像这样:我们采用



的代码称为串行桥。这是两个通信渠道之间的“桥梁”。我们将代码加载到微控制器中,微控制器通过UART2将来自计算机输入的所有内容转发到UART1,反之亦然。就像我们在两个信息源之间插入管道一样(Linuxsoid会理解)。我们将XBee模块连接到UART1。
该代码非常简单,您唯一需要更改的就是设备所连接的引脚号。即,如上所述,将它们设为PA_9和PA_10。
#include "mbed.h"
// Make a serial bridge from a serial I/O device on mbed to the PC
Serial pc(USBTX, USBRX); // tx, rx
Serial device(PA_9, PA_10); // tx, rx
// Defaults to 9600 baud on each device - use .baud(baudrate) to change
int main() {
 pc.printf("Hello!");
 while(1) {
   if(pc.readable()) {
     device.putc(pc.getc());
   }
   if(device.readable()) {
     pc.putc(device.getc());
   }
 }
}

重要的是,如果您混淆结论的顺序-例如,您犯了一个错误并写了PA_10,PA_9而不是PA_9,PA_10-错误的顺序,编译器将不会向您报告错误,并且程序将在重启后在控制台中显示错误:
pinmap not found for peripheral

并且不会继续前进,也就是说,原则上什么都不会起作用。

下载此代码并正确设置了屏蔽板上的跳线之后,您可以安全地从计算机连接到XBee模块,就像以前使用USB-UART适配器所做的一样,而无需将其从屏蔽板上卸下。XCTU程序会定期检测到它。

即使您不需要此功能,也请检查程序是否正常运行,因为在以下示例中,我们将通过微控制器与XBee模块进行通信,并且应该已经建立了通过UART1的连接(即,正确设置了跳线,并在程序中指示了引脚号)。 。

4.数据采集


让我们看两个简单的示例:如何使用XBee模块作为外部通信接口在微控制器级别接收和发送数据。

制造商的官方图书馆 -Digi公司。它位于Mbed存储库中,其中有关于代码用法和逻辑的有用注释。

首先,我们将学习如何获取数据-有一个更简单的示例。我们将有一个XBee模块连接到USB-UART转换器,向Nucleo板发送问候语,它将问候语打印到控制台。在该库中



打开项目与往常一样,将其作为程序导入到在线编译器中。

修复S2C模块的库


请记住,如果您具有S2C系列模块:



则需要使用以下修补程序而不是标准库:XBeeLib_Fixed否则,这些程序将无法工作。只需从那里删除XBeeLib库,然后将其导入XBeeLibFix项目中,即可将其添加到项目中。无需更改。

因此:将这个库导入到在线编译器中:



项目导入窗口将会出现。在那里,您需要选择目标-我们导入的位置:



作为目标项目,选择示例XBeeZB_Receive_Data。



之后,库将被导入到项目中,然后大胆地删除错误版本的XBeeLib。



编译示例


因此,您导入了示例,并在必要时替换了其中的库。
看一下示例代码,这很简单。它定义了一个回调函数,当接收到数据包时将调用该函数。此功能将接收到的数据包的内容打印到控制台。因此,如果我们给她打招呼,她也会打印出来。

为了编译示例,您需要在示例中编写我们负责与XBee模块通信的结论,因为程序不知道我们将硬件连接到了哪些结论。

因此,我们转到config.h文件及其中的行:

//#define RADIO_TX NC /* TODO: specify your setup's Serial TX pin connected to the XBee module DIN pin */
//#define RADIO_RX NC /* TODO: specify your setup's Serial RX pin connected to the XBee module DOUT pin */

取消注释,然后根据连接跳线的结论编写NC而不是NC:

#define RADIO_TX PA_9
#define RADIO_RX PA_10

同样,我们修改以下行:

//#define DEBUG_TX NC /* TODO: specify your setup's Serial TX for debugging */
//#define DEBUG_RX NC /* TODO: specify your setup's Serial RX for debugging (optional) */

我们写:

#define DEBUG_TX USBTX
#define DEBUG_RX USBRX

如果在编译过程中遇到找不到的错误device.h,只需更新项目树中的Mbed库(右键单击它->更新),

此后程序将成功编译,您可以将其下载到开发板上。

运行示例


看完Nucleo板写的控制台后,您将看到以下内容:



我们如何发送数据?最简单的选择:通过XCTU程序中的控制台。在程序的主菜单中选择:工具-发送数据包。



在底部有一个窗口,上面有单词Send packet。通过单击右侧的“加号”来创建新程序包。将出现一个用于创建新软件包的窗口。在此处选择“十六进制”选项卡。



在此处输入这样的数据发送:(
7E 00 19 10 01 00 00 00 00 00 00 FF FF FF FE 00 00 48 65 6C 6C 6F 20 58 42 65 65 21 5A
使用数据包列表右侧的“发送所选数据包”按钮),

您将在侦听模块的控制台中看到结果:



请注意,它仅打印您发送的字节集的最后一部分。这是消息的实际有效负载。还要注意,如果发送“仅字节”(字节的任意组合),则接收器将不会输出它们。

如果
48 65 6C 6C 6F 20 58 42 65 65 21
在任何HEX-ASCIII转换器中放入一组字节:(  例如,一个),请确保其含义为“ Hello XBee!”。

独立执行的一个非常简单的任务:修改示例代码,以使其以ASCII而不是HEX的形式显示消息文本,您可以在终端中读取该文本。

5.发送数据


与前面的示例类似,我们现在考虑发送数据。



如上例所示,一切都在这里。只是有所不同,我们现在打开XBeeZB_Send_Data 示例

编译示例


重要的是,如果您有一个S2C模块(清楚地写在上面),



那么您将再次将该库与修订连接,否则将无济于事。上一个示例中介绍了如何执行此操作。 

另外,在这里为了成功进行编译,您需要指定使用的控制器引脚,您可以简单地从前面的示例中复制它们。

我们来看示例代码本身。它main使用几种方法发送数据。选择最简单的方法:将数据发送给协调器。我们甚至不需要注册协调员的地址,因为他已经在网络上注册。因此,在不更改示例的情况下,我们在所有行末尾添加注释:
send_data_to_coordinator(xbee);
//send_broadcast_data(xbee);
//send_data_to_remote_node(xbee, remoteDevice);
//send_explicit_data_to_remote_node(xbee, remoteDevice);

而且,当您开始时,您会看到以下内容:(



如果看不到,只需重新启动电路板即可)

如何确定数据到达协调器?例如,XCTU具有网络控制台模式。通过右上方的按钮打开。在这种模式下,您将看到网络上的所有数据包。当然,与此同时,您应该与协调器建立串行连接。并且不要忘记单击左上方的“打开”按钮以使其变为绿色。



通过在左侧列表中选择它,可以查看有关网络上每个软件包的详细信息:



滚动到软件包内容的末尾,您将看到一行带有文本“ send_data_to_coordinator”的行:



您可以尝试其他发送数据的方法,但是在那里(例如,发送到单独的选定节点),您需要注册节点地址。您可以在XCTU程序中看到所有模块的地址。该示例中详尽描述了如何注册特定地址。

6.我们制作了MQTT网关


一切都很好,但是现在我想以某种方式在XBee网络之外(例如,在Internet上)使用此数据。一种方法是将XBee的翻译器放入流行的MQTT协议中。然后,以通常的方式,我们可以订阅事件通知并从用户界面发送命令,并且该程序可以位于任何地方(如果您使用外部MQTT服务器而不是本地MQTT服务器),而不仅位于我们的计算机上。

以下是说明。简而言之,在计算机上启动的程序将通过USB连接从网络协调器交换数据。她将这些数据传输到MQTT协议。


安装和配置XBMQ


我们将用作MQTT网关的程序称为XBMQ,它是开放和免费的。存在两个版本:

将考虑使用Java版本,尽管这并不是太基本:我们将不会对其进行编程,只会安装并使用它。
为了使程序正常工作,您将需要RXTX库,可以从存储库中简单地安装它:
sudo apt-get install librxtx-java

当然,您需要JDK(Java开发套件)。它有两个版本-来自Oracle和OpenJDK,建议使用第二个版本。很可能OpenJDK已经安装在您的系统上;如果没有,请重新安装它。Java最多需要8位,因为Java 11排除了javax.xml.bind,并且您需要选择JDK-8作为默认选项的替代项,或者为此情况创建配置。

下载XBMQ程序的存储库:
git clone https://github.com/angryelectron/xbmq-java

下载源代码后,我们将收集程序的二进制文件。球队
ant dist

将为所有主要操作系统组装一个项目。最终的已编译程序将位于文件夹中dist
现在配置该程序。打开文件
dist/xbmq.properties

并在那里查看:
#
# Xbmq Properties.
#
#port = /dev/ttyUSB0
#baud = 9600
#rootTopic = ab123
#broker = tcp://test.mosquitto.org:1883
#username = user
#password = password

取消注释并更改您的参数。参数如下:ZigBee协调器连接端口,速度,根主题(所有数据都将落入其中),MQTT服务器地址,用户名和密码(如果服务器需要它们)。

在此示例中,仅服务器地址已更改-更改为本地mqtt服务器(来自Linux的标准mosquitto)。默认情况下,其他所有内容均保留:

port = /dev/ttyUSB0
baud = 9600
rootTopic = ab123
broker = tcp://127.0.0.1:1883
username = user
password = password

在下一步之前,您必须安装并运行本地mosquitto MQTT服务器: 
sudo apt-get install mosquitto


XBMQ发布


最后,可以启动该程序。连接USB-UART转换器并插入协调器模块后,运行程序:
./dist/xbmq.sh

运行脚本时,我们会在控制台中看到以下行:
INFO - Starting XBMQ gateway ab123/0013A2004154EA46

最后-这正是我们协调员的地址。如果您使用外部MQTT客户端订阅了所有主题,则将立即看到2条消息:
  • 在主题“ ab123/0013A2004154EA46/online将为1”中,这是“最后的意愿”(这是在现实生活中如何使用这些“特殊”参数的一个很好的例子)
  • 该主题ab123/0013A2004154EA46/log将包含您在控制台中已经看到的相同调试短语“ Starting XBMQ gateway ...”。

现在尝试从其他外部XBee模块发送消息-例如,以发送数据为例。

结果,在MQTT.fx程序中,如果您订阅了所有主题(#),您将看到以下内容:


MQTT.fx程序窗口,

即通过开始前面研究的示例,向协调器发送消息,我们将看到此文本(“ send_data_to_coordinator”) MQTT软件包。对我们来说,常见的父主题是程序配置中指定的父主题(ab123,您可以将其更改为自己的主题)。接下来是协调器的地址,然后是消息来自的模块的地址。最后,该主题称为DataOut,因为它是传出数据。 

当然,您将在其他任何MQTT客户端中看到这样的图片,无论是MQTTLens还是什至仅仅是mosquitto_sub在控制台中。

最后几点意见:
  • 以良好的方式,该程序应在守护程序模式下运行。为此有一个xbmqd文件,自述文件说明了如何使用它。
  • 请记住,由于它xbmq拥有端口,因此我们无法与XCTU同时运行此程序。

现在,您可以使用MQTT协议与系统一起工作,并编写复杂而有趣的程序!


Tatyana Volkova-物联网培训计划的作者“三星IT学院”,三星研究中心的企业社会责任计划专家

All Articles