【发布时间】:2020-10-01 16:14:08
【问题描述】:
我正在帮助制造一台农业机器原型。它使用 Adafruit 无线电模块进行无线电控制:
https://learn.adafruit.com/adafruit-feather-32u4-radio-with-rfm69hcw-module/overview
系统工作正常,但接收器间歇性冻结,需要关闭/打开电源或重置才能恢复正常。由于系统是远程控制的,因此这是不可接受的,并且考虑到机器的性质,可能存在潜在危险。
下面是接收器的代码。基本上是一长串带有适当 digitalWrite 命令的“if”语句来关闭/打开各种输出。
我对编写这样的软件还很陌生,所以我确信有很多可以改进的地方。但是,当务之急是找出模块不时冻结的原因。
感谢您的任何帮助!谢谢。
// INCLUDE PACKAGES
#include <SPI.h>
#include <RH_RF69.h>
// DEFINE RADIO FREQUENCY
#define RF69_FREQ 433.0
// DEFINE OUTPUTS
#define A_UP 13
#define A_DOWN 12
#define B_UP 11
#define B_DOWN 10
#define D_DOWN 18
#define E_UP 9
#define E_DOWN 6
#define F_UP 5
#define F_DOWN 19
#define C_1 20
#define C_2 21
#define C_3 22
// DEFINE RADIO PINS
#define RFM69_CS 8
#define RFM69_INT 7
#define RFM69_RST 4
// LOAD RADIO DRIVER
RH_RF69 rf69(RFM69_CS, RFM69_INT);
// CREATE GLOBAL VARIABLES
int16_t packetnum = 0;
void setup()
{
Serial.begin(9600);
pinMode(RFM69_RST, OUTPUT);
digitalWrite(RFM69_RST, LOW);
Serial.println("Feather RFM69 RX Test!");
Serial.println();
// manual reset
digitalWrite(RFM69_RST, HIGH);
delay(10);
digitalWrite(RFM69_RST, LOW);
delay(10);
if (!rf69.init()) {
Serial.println("RFM69 radio init failed");
while (1);
}
Serial.println("RFM69 radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
// No encryption
if (!rf69.setFrequency(RF69_FREQ)) {
Serial.println("setFrequency failed");
}
// If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
// ishighpowermodule flag set like this:
rf69.setTxPower(20, true); // range from 14-20 for power, 2nd arg must be true for 69HCW
// The encryption key has to be the same as the one in the server
uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
rf69.setEncryptionKey(key);
pinMode(A_UP, OUTPUT);
pinMode(A_DOWN, OUTPUT);
pinMode(B_UP, OUTPUT);
pinMode(B_DOWN, OUTPUT);
pinMode(D_DOWN, OUTPUT);
pinMode(E_UP, OUTPUT);
pinMode(E_DOWN, OUTPUT);
pinMode(F_UP, OUTPUT);
pinMode(F_DOWN, OUTPUT);
pinMode(C_1, OUTPUT);
pinMode(C_2, OUTPUT);
pinMode(C_3, OUTPUT);
digitalWrite(A_UP,HIGH);
digitalWrite(A_DOWN,HIGH);
digitalWrite(B_UP,HIGH);
digitalWrite(B_DOWN,HIGH);
digitalWrite(D_DOWN,HIGH);
digitalWrite(E_UP,HIGH);
digitalWrite(E_DOWN,HIGH);
digitalWrite(F_UP,HIGH);
digitalWrite(F_DOWN,HIGH);
digitalWrite(C_1,HIGH);
digitalWrite(C_2,HIGH);
digitalWrite(C_3,HIGH);
Serial.print("RFM69 radio @"); Serial.print((int)RF69_FREQ); Serial.println(" MHz");
}
void loop() {
if (rf69.available()) {
// Should be a message for us now
uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf69.recv(buf, &len)) {
if (!len) return;
buf[len] = 0;
Serial.println((char*)buf);
if (strstr((char *)buf, "A UP ON")) {
digitalWrite(A_UP,LOW);
}else if (strstr((char *)buf, "A UP OFF")) {
digitalWrite(A_UP,HIGH);
}else if (strstr((char *)buf, "A DOWN ON")) {
digitalWrite(A_DOWN,LOW);
}else if (strstr((char *)buf, "A DOWN OFF")) {
digitalWrite(A_DOWN,HIGH);
}else if (strstr((char *)buf, "B UP ON")) {
digitalWrite(B_UP,LOW);
}else if (strstr((char *)buf, "B UP OFF")) {
digitalWrite(B_UP,HIGH);
}else if (strstr((char *)buf, "B DOWN ON")) {
digitalWrite(B_DOWN,LOW);
}else if (strstr((char *)buf, "B DOWN OFF")) {
digitalWrite(B_DOWN,HIGH);
}else if (strstr((char *)buf, "D ON")) {
digitalWrite(D_DOWN,LOW);
}else if (strstr((char *)buf, "D OFF")) {
digitalWrite(D_DOWN,HIGH);
}else if (strstr((char *)buf, "E UP ON")) {
digitalWrite(E_DOWN,HIGH);
digitalWrite(E_UP,LOW);
delay(3000);
digitalWrite(E_UP,HIGH);
}else if (strstr((char *)buf, "E UP OFF")) {
digitalWrite(E_UP,HIGH);
}else if (strstr((char *)buf, "E DOWN ON")) {
digitalWrite(E_UP,HIGH);
digitalWrite(E_DOWN,LOW);
delay(3000);
digitalWrite(E_DOWN,HIGH);
}else if (strstr((char *)buf, "E DOWN OFF")) {
digitalWrite(E_DOWN,HIGH);
}else if (strstr((char *)buf, "F UP ON")) {
digitalWrite(F_UP,LOW);
}else if (strstr((char *)buf, "F UP OFF")) {
digitalWrite(F_UP,HIGH);
}else if (strstr((char *)buf, "F DOWN ON")) {
digitalWrite(F_DOWN,LOW);
}else if (strstr((char *)buf, "F DOWN OFF")) {
digitalWrite(F_DOWN,HIGH);
}else if (strstr((char *)buf, "SPEED 0")) {
digitalWrite(C_1,HIGH);
digitalWrite(C_2,HIGH);
digitalWrite(C_3,HIGH);
}else if (strstr((char *)buf, "SPEED 1")) {
digitalWrite(C_1,LOW);
digitalWrite(C_2,HIGH);
digitalWrite(C_3,HIGH);
}else if (strstr((char *)buf, "SPEED 2")) {
digitalWrite(C_1,LOW);
digitalWrite(C_2,LOW);
digitalWrite(C_3,HIGH);
}else if (strstr((char *)buf, "SPEED 3")) {
digitalWrite(C_1,LOW);
digitalWrite(C_2,HIGH);
digitalWrite(C_3,LOW
);
}else if (strstr((char *)buf, "SPEED 4")) {
digitalWrite(C_1,LOW);
digitalWrite(C_2,LOW);
digitalWrite(C_3,LOW);
}
} else {
Serial.println("Receive failed");
}
}
}
更新:
- 看来该程序完全在我正在使用的 Adafruit 板的限制范围内 - 当我编译该程序时 Arduino IDE 会报告这一点:
Sketch 使用 10612 字节 (37%) 的程序存储空间。最大值为 28672 字节。 全局变量使用 663 字节的动态内存。
- 我已将 buf 声明为静态:
静态 uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
- 我已注释掉所有 Serial.print() 行,因为它们不是必需的(无法在设备内监控它们)
【问题讨论】:
-
我怀疑循环中的
buf[len] = 0;;当rf69.recv(buf, &len);读取它正在读取的任何内容时,是否允许它读取 一直 直到缓冲区的完整大小,这样buf[len]实际上会写到数组的末尾?在缓冲区定义中添加一个字节的填充可能会更好,然后从提供给recv()的长度中删除一个字节@ -
另外,它的间歇性如何?每5分钟一次?每 6 周一次?您能否将挂断与发送到设备的特定命令关联起来?我还想知道将设备告诉
F UP是否自找麻烦 :-) -
@SteveFriedl 感谢您的指点 - 它非常间歇性,但似乎在发送太多命令时发生。正如您对缓冲区的查询所暗示的那样,内存不足似乎是一个可能的原因,正如 Marcelo 在答案中所暗示的那样?
-
Marcelo 的回答比我的要中肯得多,而且看起来很正确。但如果我遇到这个问题,我会构建一个小测试夹具,让 Feather 坐在其中,也许将 LED 连接到输出引脚,然后练习以高速率发送测试命令,观察活动模式。更好的是连接到测试计算机的测试夹具,它可以读取引脚,然后进行端到端测试。通过无线电向 Feather 发送命令,读回引脚,用时间戳记录所有内容。找出是什么让它坏了。
标签: c++ c arduino radio adafruit