【问题标题】:Why are data packets missing in Zigbee arduino setup?为什么 Zigbee arduino 设置中缺少数据包?
【发布时间】:2024-01-12 20:11:01
【问题描述】:

我做了一个由 3 个 Zigbee、2 个路由器(Zigbee S2C's)和 1 个协调器(Zigbee S2)组成的设置。每个路由器都连接到 arduino nano,后者从 2 个 FSR 和一个 IMU(帧类型:zigbee 传输请求和数据包大小 46 字节)收集数据并将其发送到连接到 arduino UNO 的协调器。所有的 Xbee 都处于 API 模式 2 并以 115200 的波特率工作。我正在使用一个名为“Simple Zigbee Library”的库将所有收集到的数据发送到协调器。数据的收集和发送工作正常,只是途中有数据包丢失。 nano 的样本数据独立于 25Hz 左右的频率。协调器尝试在每个循环中读取从 zigbees(当然使用库)发送的数据,但不幸的是,它似乎只接收到大约 40-45 个样本。(应该是 25*2=50 个样本总数来自 2 xbees)。任何人都可以提出为什么会这样。我的设置需要尽可能少的数据丢失才能实现其目的。任何形式的帮助表示赞赏。

P.S:可能很重要的一点是,协调器在每个循环中只从一个 xbee 读取数据。

As can be seen under the "Source" heading of this image of data received by the coordinator, "19" and "106" are the addresses of the routers and there are data packets dropped intermittently

谢谢。

void setup()
{
    // Start the serial ports ...
    Serial.begin( 115200 );
    while( !Serial ){;}  // Wait for serial port (for Leonardo only).
    xbeeSerial.begin( 115200 );
    // ... and set the serial port for the XBee radio.
    xbee.setSerial( xbeeSerial );
    // Set a non-zero frame id to receive Status packets.
    xbee.setAcknowledgement(true);
}
void loop()
{
    // While data is waiting in the XBee serial port ...
    while( xbee.available() )
    {
        // ... read the data.
        xbee.read();
        // If a complete message is available, display the contents
        if( xbee.isComplete() ){
            Serial.print("\nIncoming Message: ");
            printPacket( xbee.getIncomingPacketObject() );
        }
    }
    delay(10); // Small delay for stability
    // That's it! The coordinator is ready to go.
}
// Function for printing the complete contents of a packet //
void printPacket(SimpleZigBeePacket & p)
{
    //Serial.print( START, HEX );
    //Serial.print(' ');
    //Serial.print( p.getLengthMSB(), HEX );
    //Serial.print(' ');
    //Serial.print( p.getLengthLSB(), HEX );
    //Serial.print(' ');
    // Frame Type and Frame ID are stored in Frame Data
    uint8_t checksum = 0;
    for( int i=10; i<p.getFrameLength(); i++){
        Serial.print( p.getFrameData(i), HEX );
        Serial.print(' ');
        checksum += p.getFrameData(i);
    }
    // Calculate checksum based on summation of frame bytes
    checksum = 0xff - checksum;
    Serial.print(checksum, HEX );
    Serial.println();
}

【问题讨论】:

  • 您是否考虑过数据包冲突数据损坏?通信协议是否足够先进以处理这些情况?
  • 此链接表示:这些模块(MAC 和 PHY 层)使用的无线电由 IEEE 802.15.4 标准定义,该标准指定使用载波侦听多路访问和避免冲突或缩写为CSMA/CA.electronics.stackexchange.com/questions/36932/…
  • 好极了,但我想到了比这更高级的东西。 CSMA/CA 在适当的情况下可以并且肯定无法防止 碰撞,尽管拥有它肯定比没有更好。 高层协议应该要求每个包被确认,如果在给定的超时。上次我使用 ZigBee 时,虽然我承认我没有使用 Arduino,但我必须自己实现。
  • 感谢@PatrickTrentin 的快速回答。我在API 模式下使用Xbees,数据包已按照您的描述进行确认。我正在使用的库(“Simple Zigbee 库”)为我完成了所有繁重的工作。此外,我的实际代码以 115200 波特而不是示例中给出的 9600 波特运行。
  • 很高兴知道,谢谢

标签: api arduino router serial-communication xbee


【解决方案1】:

虽然您声称使用 115,200bps,但发布的代码显示您以 9600 波特率打开串行端口,对于 2500 字节/秒(50 数据包/秒 * 45 字节/数据包 * 110% 的开销)接收速度肯定不够快来自 XBee 并由printPacket() 倾销)。请记住,802.15.4 始终是 250kbps 的空中传输速率,而 XBee 模块的串行端口配置仅用于与主机进行本地通信。

确保您的路由器发送单播(而不是广播)数据包以降低无线电流量。

在对协调器上的代码进行故障排除之前,您应该验证发送是否正常。更新路由器上的代码以查看是否为每个发送的数据包获得了成功的传输状态数据包。以 50Hz 为目标似乎有点多 - 您尝试每 20 毫秒发送 45 个字节(这是 API 帧的完整大小吗?)。

您是否在 Arduino 上为 XBee 模块和Serial.print() 使用硬件串行端口?每次拨打printPacket() 需要多少时间?如果您将printPacket() 中的代码减少到最低限度(发件人地址的最后一个字节和 1 字节的帧 ID),您是否看到所有数据包都通过了(表明您花费太多时间转储数据包) .

【讨论】:

  • 感谢回复@tomlogic 我对所有三个 arduino 都使用 115200 的波特率。示例代码中的错误已得到纠正。发送正在工作,因为我收到了两个路由器的确认消息。但是有些数据包没有得到确认。发生在大约十分之二的数据包中。(在两个 xbees 中)。 50 Hz 不是强制性的,但对我来说越高越好。我在所有 3 xbees 上使用软件序列号。即使我将 printPacket 中的代码减少到最低限度,所有数据包都不会通过。
  • 您仍在为每个收到的数据包打印大量信息(100 个字符 * 50 条消息 = 50kbps,最大 115.2kbps)——将其减少到仅几个字节以进行测试。您可能会花费大量时间打印数据包,以至于您落后了。 Arduino 上的串行缓冲区有多大?您可以使用硬件握手 (CTS/RTS) 来防止缓冲区溢出吗?
  • 我将代码调到了必要的最小数据(8 字节)。 arduino 的串行缓冲区大小为 64 字节。我尝试使用hobbytronics.co.uk/arduino-serial-buffer-size 中显示的方法增加UNO 的缓冲区大小,但它仍然会丢失数据字节。关于还有什么可以尝试的想法?
【解决方案2】:

我担心您在循环中使用的代码。我不知道 Arduino 的工作原理,但是 10 毫秒的延迟会阻止其他代码处理数据吗?如果简化它会怎样:

void loop()
{
    xbee.read();
    // Process any complete frames.
    while (xbee.isComplete()){
        Serial.print("\nIncoming Message: ");
        printPacket( xbee.getIncomingPacketObject() );
    }
}

但在走得太远之前,您应该通过将协调器连接到 PC 上的终端仿真器来监控帧速率来隔离问题。如果所有帧都到达,那么协调器就有问题。如果没有,请先处理您的路由器代码。

【讨论】:

  • 我删除了协调器代码中的延迟,将数据包大小缩减为 8 字节的有效负载(早先是 45,总数据包大小约为 15 字节)即使它看起来只是顽固地丢弃数据点。原始帖子中链接中显示的输出是使用 PC 上的终端仿真器获取的,该 PC 连接到带有 Xbee 屏蔽的 Uno。当我使用 Xbee Explorer 直接将 Coordinator 连接到 PC 时,我会显示乱码。那可能是因为我处于 API 模式。但我只是无法弄清楚为什么它不起作用。我的论文需要这个。任何帮助表示赞赏。
  • 您需要以十六进制形式查看数据才能理解它。注意 0x7E 作为帧字符的开始,后跟两个字节的长度和帧类型。就像我说的那样,您需要先确认您实际上是从路由器发送数据,然后再花更多时间对协调器进行故障排除。最简单的解决方案可能是降低刷新率,直到获得可靠的通信。
  • 在我参与的一个监控项目中,终端设备捕获了 5 分钟的数据,然后在 5 分钟窗口内发送了一个数据包,其中包含最小、最大和平均读数。也许类似的东西对你的项目有用。
  • 您也可以尝试使用提供数据的单个路由器运行,以查看您是否获得可靠的通信。这将是确认两端正确操作的快速方法。此时,要么是 ZigBee 网络上的网络拥塞问题,要么是协调器处理过多而无法跟上。如果一个有效,请尝试两个采样率的一半。
最近更新 更多