即时通讯工具、arduino 和 NRF24L01
instant messenger, arduino and NRF24L01
我正在尝试使用 arduino、NRF24L01 芯片和 TMRH20 的库 RF24 创建一个即时通讯工具。
它专为 2 个 arduino 板设计。
这是我的 Messenger 的问题:大多数时候,接收者没有收到消息,有时他收到了消息,但一切都搞混了,比如错误的编码错误...
代码如下:
http://pastebin.com/TP53VyeH
要尝试它,您需要 2 个 arduino 板,插入 2 个不同的 USB 端口。对于其中一个板,您必须更改第 10 行的数字。
ps:在我的工作站上,如果我尝试 "GettingStarted_HandlingData",一切正常,所以问题不是我的 arduinos...
您正在将数据直接抓取到 String 对象中,而不是它的缓冲区中。
radio.read( &message, sizeof(message) );
这很糟糕,因为不仅字符串 class 大约有 6 个字节长,而且您还覆盖了存储指向其缓冲区的指针的字节。因此,当您读取 String 时,它的指针现在位于某个任意位置。您将读取那里的任何内容,这可能是其他变量、寄存器,甚至 GPIO 引脚。 (此时您的应用程序可能非常损坏)。
您需要使用字符缓冲区。
编辑:
it seems that the message get cut after 32 character, and not 50... No idea why. I tried replacing 50 with 200, and the message still get cut after 32 character.
您应该使用radio.getPayloadSize()
来确保您的数据能够接收到尽可能大的数据包。此外,如果您需要发送大量数据,或者想要发送较小的数据包,您可以使用 radio.setPayloadSize()
。但是,最大 32 字节。
radio.startListening();
char buffer[ radio.getPayloadSize() ]; //Note: an array like this is a GCC extension, not standard C++
if(radio.available()) {
radio.read( &buffer, radio.getPayloadSize() );
}
message = buffer; //Not really needed, you can just use the buffer.
使用循环似乎不对,radio.available()
是如果接收到整个数据包。在这里循环只会丢弃除最后一个数据包以外的所有数据包。你也许应该循环整个接收端(在 radio.startListening();
之后),这样你就可以 print/process 每个数据包进来。
您不能真正使用 String 对象,因为它不识别新数据(如果直接使用其内部缓冲区,其长度将不会更新)。我现在 a patch I'm trying to get merged 进入核心,这将允许这样的事情:
message.buffer( radio.getPayloadSize() );
radio.read( message.c_str(), radio.getPayloadSize() );
message.validate(); //Allow String to detect new contents (Not in the core yet).
不过,我会 post 这个问题作为另一个很好补充的原因。
我终于让它工作了。我在传输过程中使用了char而不是String,这解决了所有问题。
这意味着设置最大消息长度限制(我设置了50个字符,这绰绰有余)。
这是工作代码:
http://pastebin.com/5Ryjr8sD
(ps :对于串行通信,输出仍然是一个字符串,所以我使用以下方法将其转换为字符:message.toCharArray(messagechar,50);
编辑:消息似乎在 32 个字符后被截断,而不是 50 个...不知道为什么。我尝试用 200 替换 50,但消息在 32 个字符后仍然被截断
edit2: 这是最后的代码,防止用户写超过 32 个字符。 http://pastebin.com/TVgu16zx
我正在尝试使用 arduino、NRF24L01 芯片和 TMRH20 的库 RF24 创建一个即时通讯工具。 它专为 2 个 arduino 板设计。
这是我的 Messenger 的问题:大多数时候,接收者没有收到消息,有时他收到了消息,但一切都搞混了,比如错误的编码错误...
代码如下: http://pastebin.com/TP53VyeH
要尝试它,您需要 2 个 arduino 板,插入 2 个不同的 USB 端口。对于其中一个板,您必须更改第 10 行的数字。
ps:在我的工作站上,如果我尝试 "GettingStarted_HandlingData",一切正常,所以问题不是我的 arduinos...
您正在将数据直接抓取到 String 对象中,而不是它的缓冲区中。
radio.read( &message, sizeof(message) );
这很糟糕,因为不仅字符串 class 大约有 6 个字节长,而且您还覆盖了存储指向其缓冲区的指针的字节。因此,当您读取 String 时,它的指针现在位于某个任意位置。您将读取那里的任何内容,这可能是其他变量、寄存器,甚至 GPIO 引脚。 (此时您的应用程序可能非常损坏)。
您需要使用字符缓冲区。
编辑:
it seems that the message get cut after 32 character, and not 50... No idea why. I tried replacing 50 with 200, and the message still get cut after 32 character.
您应该使用radio.getPayloadSize()
来确保您的数据能够接收到尽可能大的数据包。此外,如果您需要发送大量数据,或者想要发送较小的数据包,您可以使用 radio.setPayloadSize()
。但是,最大 32 字节。
radio.startListening();
char buffer[ radio.getPayloadSize() ]; //Note: an array like this is a GCC extension, not standard C++
if(radio.available()) {
radio.read( &buffer, radio.getPayloadSize() );
}
message = buffer; //Not really needed, you can just use the buffer.
使用循环似乎不对,radio.available()
是如果接收到整个数据包。在这里循环只会丢弃除最后一个数据包以外的所有数据包。你也许应该循环整个接收端(在 radio.startListening();
之后),这样你就可以 print/process 每个数据包进来。
您不能真正使用 String 对象,因为它不识别新数据(如果直接使用其内部缓冲区,其长度将不会更新)。我现在 a patch I'm trying to get merged 进入核心,这将允许这样的事情:
message.buffer( radio.getPayloadSize() );
radio.read( message.c_str(), radio.getPayloadSize() );
message.validate(); //Allow String to detect new contents (Not in the core yet).
不过,我会 post 这个问题作为另一个很好补充的原因。
我终于让它工作了。我在传输过程中使用了char而不是String,这解决了所有问题。
这意味着设置最大消息长度限制(我设置了50个字符,这绰绰有余)。
这是工作代码: http://pastebin.com/5Ryjr8sD
(ps :对于串行通信,输出仍然是一个字符串,所以我使用以下方法将其转换为字符:message.toCharArray(messagechar,50);
编辑:消息似乎在 32 个字符后被截断,而不是 50 个...不知道为什么。我尝试用 200 替换 50,但消息在 32 个字符后仍然被截断
edit2: 这是最后的代码,防止用户写超过 32 个字符。 http://pastebin.com/TVgu16zx