Сбой Arduino и перезагрузка в случайных точках

Я работаю над очень важным школьным проектом, который представляет собой MP3-плеер с веб-интерфейсом и веб-сервером, использующим Arduino Mega. когда я хочу использовать любую функцию библиотеки Ethernet, мне приходится приостанавливать музыку, потому что экран Ethernet и экран mp3-плеера используют одну и ту же шину spi. Но когда я меняю громкость, это вызывает зависание музыки на 1 секунду. чтобы избежать этого, я создал новые функции, которые приостанавливают музыку, вызывают функцию ethernet 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("новый клиент")), ошибка возникнет в строке client.print(c) (после отображения 3 или 4 символов). Если я также удалю эту строку, она будет сбой где-то, но я не знаю, где.

Проверил память, у меня осталось вроде 600 байт на этом месте программы.

Любые идеи ?

Спасибо.


person RedSkidy    schedule 13.04.2016    source источник
comment
Как настроен ваш сторожевой таймер? Это отключено? Если нет, то где код, обслуживающий сторожевой таймер?   -  person Lundin    schedule 13.04.2016
comment
Я не знаю насчет кода, но просто чтение текста вопроса наполняет меня глубоким чувством беспокойства и предчувствия... Такое ощущение, что вы посещаете пациента с множественной травмой и спрашиваете, как наложить лейкопластырь: (Надеюсь, я ошибаюсь, но я думаю, что ваш дизайн истекает кровью.   -  person Martin James    schedule 13.04.2016
comment
@Lundin это было не так, поэтому я пытался отключить его, но ничего не изменилось, должен ли я включить его и настроить вместо этого?   -  person RedSkidy    schedule 13.04.2016
comment
@MartinJames это только потому, что я пытаюсь объяснить код примерно из 430 строк в 6, и я не очень хорошо разбираюсь в английском ... если вам нужны подробности, есть эта задержка в 1 секунду, потому что я должен получить данные от клиента и извлечь из него информацию. раньше у меня было что-то вроде: пауза - функция Ethernet - вещи, вызывающие задержку 1 с - функция Ethernet - возобновление. теперь я хочу что-то вроде паузы - функция Ethernet - возобновление - вещи, вызывающие задержку в 1 секунду - пауза - функция Ethernet - возобновление - поэтому у меня нет этого зависания каждый раз, когда я меняю громкость.   -  person RedSkidy    schedule 13.04.2016
comment
Сбой кода при запуске хорошо протестированной библиотечной функции, которая, в свою очередь, работает медленно, так как передача данных очень похожа на сторожевой таймер.   -  person Lundin    schedule 13.04.2016
comment
но эта строка не вызывала никаких проблем до того, как я начал использовать свои пользовательские функции.   -  person RedSkidy    schedule 13.04.2016
comment
когда я включаю сторожевой таймер, рабочая часть моего кода больше не работает редактировать: я тупой, я просто забыл его сбросить   -  person RedSkidy    schedule 13.04.2016


Ответы (1)


Вероятно, у вас мало оперативной памяти.

Кроме того, вы не должны использовать класс 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 в другом месте своей программы, вы должны использовать аналогичный подход для его устранения.

Еще один способ уменьшить объем оперативной памяти — избегать сохранения данных при их поступлении, а затем их последующего использования. Вместо этого используйте его немедленно:

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.

Вы не разместили всю свою программу для нашего обзора, поэтому вам придется искать другие переменные, которые слишком велики или могут быть объявлены внутри подпрограммы (т. е. локальной переменной) вместо этого. в области файла (т. е. глобальная переменная, объявленная вне каких-либо подпрограмм).

person slash-dev    schedule 13.04.2016
comment
спасибо за эти советы, но, к сожалению, это не сработало ... есть еще небольшое улучшение, вот что я получаю: new client GET / HTTP¯192.168.0.123 это происходит только с тех пор, как я добавил эти функции, но я не понимаю, почему. вот полный код: pastebin.com/BWFqVGEv - person RedSkidy; 13.04.2016
comment
Я также изменю строки в своей структуре mp3 - person RedSkidy; 13.04.2016
comment
@RedSkidy, я рад, что стало лучше. Кстати, вы можете отредактировать свой исходный вопрос и включить свой эскиз. Большинство людей не будут скачивать что-либо, чтобы ответить на вопрос... кроме библиотек. Если вы используете библиотеку, опубликуйте ссылку на ту, которую вы используете, не включайте ее в свое сообщение. - person slash-dev; 14.04.2016
comment
Я не думаю, что библиотеки очень важны в этом случае. Даже если есть небольшое улучшение, он все еще делает тот же сбой. Поскольку стало лучше использовать массивы символов вместо строк, я предполагаю, что проблема связана с нехваткой памяти, но это происходит только потому, что я добавил эти функции, есть ли какая-то причина, по которой они будут потреблять память? - person RedSkidy; 14.04.2016
comment
@RedSkidy, вы не думаете, что библиотеки или остальная часть вашего кода очень важны? Похоже, вы уже знаете ответ. - person slash-dev; 14.04.2016
comment
это больше, потому что я использую только основные функции хорошо протестированных библиотек, созданных людьми, намного более опытными, чем я, и я уже использовал эти функции, и они работали раньше, но вы, вероятно, правы, так что это используемые библиотеки: SFEMP3Shield: mpflaga.github.io/Sparkfun-MP3-Player- Shield-Arduino-Library/ Arduino Ethernet: arduino.cc/en/reference/ethernet также sdfatlib, но не используется в этой части кода: mosquino.googlecode.com/hg/libraries/sdfatlib-mosquino/html/ - person RedSkidy; 14.04.2016