【问题标题】:Adafruit Feather RFM69HCW Freezes During Use Requiring Hard ResetAdafruit Feather RFM69HCW 在使用过程中冻结,需要硬重置
【发布时间】: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");
    }
  }
}

更新:

  1. 看来该程序完全在我正在使用的 Adafruit 板的限制范围内 - 当我编译该程序时 Arduino IDE 会报告这一点:

Sketch 使用 10612 字节 (37%) 的程序存储空间。最大值为 28672 字节。 全局变量使用 663 字节的动态内存。

  1. 我已将 buf 声明为静态:

静态 uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];

  1. 我已注释掉所有 Serial.print() 行,因为它们不是必需的(无法在设备内监控它们)

【问题讨论】:

  • 我怀疑循环中的buf[len] = 0;;当rf69.recv(buf, &amp;len); 读取它正在读取的任何内容时,是否允许它读取 一直 直到缓冲区的完整大小,这样buf[len] 实际上会写到数组的末尾?在缓冲区定义中添加一个字节的填充可能会更好,然后从提供给recv()的长度中删除一个字节@
  • 另外,它的间歇性如何?每5分钟一次?每 6 周一次?您能否将挂断与发送到设备的特定命令关联起来?我还想知道将设备告诉F UP 是否自找麻烦 :-)
  • @SteveFriedl 感谢您的指点 - 它非常间歇性,但似乎在发送太多命令时发生。正如您对缓冲区的查询所暗示的那样,内存不足似乎是一个可能的原因,正如 Marcelo 在答案中所暗示的那样?
  • Marcelo 的回答比我的要中肯得多,而且看起来很正确。但如果我遇到这个问题,我会构建一个小测试夹具,让 Feather 坐在其中,也许将 LED 连接到输出引脚,然后练习以高速率发送测试命令,观察活动模式。更好的是连接到测试计算机的测试夹具,它可以读取引脚,然后进行端到端测试。通过无线电向 Feather 发送命令,读回引脚,用时间戳记录所有内容。找出是什么让它坏了。

标签: c++ c arduino radio adafruit


【解决方案1】:
  1. 尝试将所有字符串包含在 F() 宏中,例如 F("blablabla")。也许你的内存快用完了,这很常见。
  2. 检查程序的链接并寻找潜在的内存不足:

Sketch 使用 3776 字节 (1%) 的程序存储空间。最大值为 253952 字节。

全局变量使用 646 字节 (7%) 的动态内存,剩下 7546 字节用于局部变量。最大为 8192 字节。

  1. 您在堆栈中声明了一个缓冲区,我不知道 RH_RF69_MAX_MESSAGE_LEN 的大小,但这可能是问题的原因之一。删除它 static uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];

【讨论】:

  • 非常感谢马塞洛的这些指点。我已经注释掉了所有串行打印行,因为它们不是必需的,并且已经删除了 static uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];我将代码发送给我的客户进行测试,看看它是否更可靠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多