Arduino崩溃并重新启动"随机点"

时间:2016-04-13 10:06:24

标签: c++ c crash arduino reboot

我正在开展一个非常重要的学校项目,这是一个带有网络界面的MP3播放器和一个使用arduino mega的网络服务器。 当我想使用以太网lib的任何功能时,我必须暂停音乐,因为以太网屏蔽和mp3播放器屏蔽使用相同的spi总线。但是当我改变音量时,会导致音乐中的1s冻结。为了避免我创建了暂停音乐的新功能,调用以太网lib和简历的功能。

bool clientAvailable(EthernetClient &client){
  MP3player.pauseDataStream ();
  bool a = client.connected();
  MP3player.resumeDataStream ();
  return a;
}
int clientConnected(EthernetClient &client){
  MP3player.pauseDataStream ();
  int a = client.available();
  MP3player.resumeDataStream ();
  return a;
}
void stopClient(EthernetClient &client){
  MP3player.pauseDataStream ();
  client.stop();
  MP3player.resumeDataStream ();
}

void checkForClient(int loading){
  String firstLine;
  MP3player.pauseDataStream ();
  EthernetClient client = server.available();
  MP3player.resumeDataStream();
  if (client) {
    if(!loading){
      Serial.println(F("new client")); // CRASH HERE
      bool endLn(false);
      char chr;
      int i(0);
      while (clientConnected(client)) {
        char received[clientAvailable(client)+2];
        while (clientAvailable(client)) {
          MP3player.pauseDataStream ();
          char c = client.read();
          MP3player.resumeDataStream ();
           received[i] = c;
          Serial.print(c); // OR HERE
          if(!endLn){
            firstLine += c;
            if (c == '\n'){
            endLn = true;
            }
          }
          ++i;
        }
        received[i+1] = '\0';
        i = 0;
        if(endLn){
          Serial.println();
          endLn = false;
          Serial.print(F("first line : "));
          Serial.println(firstLine);
        }

我得到的输出:

new û192.168.0.123

最后有一个IP,因为这是arduino重启的地方,这是我展示的第一件事。 如果我删除" client.println(F(" new client"))行,则会在client.print(c)行上显示错误(显示3或4个字符后)。如果我也删除了这个,它会在某处崩溃,但我不知道在哪里。

我检查了内存,我在程序的这一点上还剩600个字节。

有什么想法吗?

感谢。

1 个答案:

答案 0 :(得分:0)

你的RAM状况可能很低。

此外,您不应将String类用于firstLine。它会导致许多问题,其中一些问题可能会在随机时间发生。

只需像received那样使用字符数组。将每个字符存储在数组中,直到换行符到达为止,并增加每个字符的长度:

void checkForClient(int loading){
  char    firstLine[60];
  uint8_t firstLineLen = 0;

  MP3player.pauseDataStream ();
  EthernetClient client = server.available();
  MP3player.resumeDataStream();
  if (client) {
    if(!loading){
      Serial.println(F("new client")); // CRASH HERE
      bool endLn(false);
      char chr;
      int i(0);
      while (clientConnected(client)) {
        char received[clientAvailable(client)+2];
        while (clientAvailable(client)) {
          MP3player.pauseDataStream ();
          char c = client.read();
          MP3player.resumeDataStream ();
          received[i] = c;
          Serial.print(c); // OR HERE
          if (!endLn) {
            if (firstLineLength < sizeof(firstLine)-2)
              firstLine[ firstLineLength++ ] = c;
            if (c == '\n') {
              endLn = true;
              firstLine[ firstLineLength ] = '\0'; // NUL-terminate
            }
          }
          ++i;
        }
        received[i+1] = '\0';
        i = 0;
        if(endLn){
          Serial.println();
          endLn = false;
          Serial.print(F("first line : "));
          Serial.println(firstLine);
        }

这也将节省大约1600字节的程序空间。避免使用String有很多理由,很多人都写过关于陷阱的文章。如果您在程序的其他地方使用String,则应使用类似的方法来消除它。

减少RAM的另一种技术是避免在数据进入时存储数据,然后再使用它。相反,立即使用它:

void checkForClient(int loading){

  MP3player.pauseDataStream ();
  EthernetClient client = server.available();
  MP3player.resumeDataStream();
  if (client) {
    if(!loading){
      Serial.println(F("new client")); // CRASH HERE

      Serial.print(F("first line : "));
      bool endLn(false);

      char chr;
      int i(0);
      while (clientConnected(client)) {
        char received[clientAvailable(client)+2];
        while (clientAvailable(client)) {
          MP3player.pauseDataStream ();
          char c = client.read();
          MP3player.resumeDataStream ();
          received[i] = c;
          if (!endLn) {
            Serial.print(c); // printed now instead of saved for later
            if (c == '\n') {
              endLn = true;
            }
          }
          ++i;
        }
        received[i+1] = '\0';
        i = 0;
        if (endLn) {
          Serial.println();
          endLn = false;
          //Serial.println(firstLine); // NOT NEEDED, already printed!
        }

这将保存您用于firstLine的所有RAM。

您没有发布整个程序供我们审核,因此您必须查找其他变量太大,或者可以在 例程中声明即,一个局部变量)而不是在文件范围(即,在任何例程之外声明的全局变量)。