My sketch hangs after some hours - Wifi to Lan Adapter the problem?

Hello there :slight_smile:

This community was very helpful because i am to total newbie and learned the most basic stuff just reading some posts.

But i still have a problem.

The sketch seems to run, but all of a sudden it hangs.

When i start the serial monitor it seems to be fine again and continues. How can i can i keep it running?

Thank you in advance

#include <Controllino.h>
#include <SPI.h>
#include <Ethernet.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

const int numBytes = 20;
int receivedIntegers[numBytes];
byte outByte[6];
boolean DatenKorrekt = false;

byte mac_addr[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE }; //mac vom Controllino setzen

IPAddress server_addr(192, 168, 2, 3); // MySQL Server IP
IPAddress ip(192, 168, 2, 153); //Controllino IP setzen
IPAddress gateway(192, 168, 2, 1);
IPAddress dnsserver(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);
char user[] = "XXXX";              // MySQL Server username
char password[] = "XXXX";        // MySQL Server password

EthernetClient client;
MySQL_Connection conn((Client *)&client);



void setup()
{
  Serial.begin(115200); //Baudraute serieller Monitor (USB)
  delay(500);
  Serial.println("started");
  Serial3.begin(38400,SERIAL_8N2); //Initialisierung Serial Controllino(RS 485)
  //Beim Mega oder Maxi Zugang zum /OVL pin und RS458 /RE DE Pins
  //Zuweisung /RE (PJ5) DE (PJ6) pins als Ausgang (1). Für /OLV (PE7) als Eingang (0)
  DDRJ |= B01100000;
  DDRE &= B01111111;

  Ethernet.begin(mac_addr, ip, dnsserver, gateway, subnet);
}

void loop()
{
  DatenSenden();
  delay(5);
  DatenEmpfangen();
  delay(5);
  DatenAnzeigen();
  delay(5);
  DatenSchreiben();
  delay(5);
}






void DatenSenden()
{
  //Beim Mega oder Maxi Zugang zum /RE (PJ5) and DE (PJ6) Pins zu LOW.
  //Beim Mega oder Maxi Zugang zum /RE (PJ5) and DE (PJ6) Pins zu HIGH.
  //Serial.println("Kommando wird gesendet");
  PORTJ |= B01100000;//SENDEN MODUS
  outByte[0]=1;
  outByte[1]=3;
  outByte[2]=15;
  outByte[3]=4;
  outByte[4]=8;
  outByte[5]=13;
  Serial3.write(outByte,6);
}

void DatenEmpfangen()
{
  static byte ndx = 0;
  int rc;
  PORTJ &= B10011111;//Empfangen MODUS
  delay(1000);
  do
  {
    if (Serial3.available() > 0)
    {
     rc = Serial3.read();
     receivedIntegers[ndx] = rc;
     ndx++;
    }
  } while (Serial3.available() > 0);
}

void DatenAnzeigen()
{
  static byte count = 0;
  int Xor = 0;
  Xor = receivedIntegers[0];
  for (count=0;count<18;count++)
  {
    Serial.println(receivedIntegers[count]);
  }
  for (count=0;count<16;count++)  //Vergleich, ob errechnete Xor CRC mit empfangener CRC übereinstimmt(Übertragungsfehler ausschließen)
  {
    Xor = Xor ^ receivedIntegers[count+1];
  }
 if (Xor == receivedIntegers[17] && receivedIntegers[0] != 0) //Wenn errechnte CRC übereinstimmt UND empfangene Daten ungleich 0(nach reset), dann ist alles ok?!
 {
  Serial.print("checkedXorCRC: ");
  Serial.print(Xor);
  Serial.print(" empfangenXorCRC: ");
  Serial.print(receivedIntegers[17]);
  Serial.println(" OK!!!");
  DatenKorrekt = true;
 }
 else if (Xor == receivedIntegers[17] && receivedIntegers[0] == 0)
 {
  Serial.print("checkedXorCRC: ");
  Serial.print(Xor);
  Serial.print(" empfangenXorCRC: ");
  Serial.print(receivedIntegers[17]);
  Serial.println(" Keine Daten empfangen!!!");
  DatenKorrekt = false;
 }
 else
 {
  Serial.println("irgendwas ist schief gelaufen");
  Serial.print("checkedXorCRC: ");
  Serial.print(Xor);
  Serial.print(" empfangenXorCRC: ");
  Serial.print(receivedIntegers[17]);
  DatenKorrekt = false;
 }
}

void DatenSchreiben()
{
  /*
  int A1 = 1;
  int A2 = 2;
  int A3 = 3;
  int A4 = 0;
  int A5 = 0;
  int A6 = 0;
  int A7 = 0;
  int A8 = 0;
  int A9 = 0;
  int A10 = 0;
  int A11 = 0;
  int A12 = 0;
  int A13 = 0;
  int A14 = 0;
  int A15 = 0;
  int A16 = 0;
  int A17 = 0;
  int CRC = 0;
  */

  if (DatenKorrekt == true)
  {
    Serial.println("Alles korrekt abgelaufen");
    // Initiate the query class instance
    Serial.println("Verbinde zum MySQL Server...");
    if (conn.connect(server_addr, 3306, user, password))
    {
      delay(1000);
      char INSERT_SQL[] = "INSERT INTO database.table1 (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,CRC) VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)";
      char query[500];
      sprintf(query, INSERT_SQL, receivedIntegers[0],receivedIntegers[1],receivedIntegers[2],receivedIntegers[3],receivedIntegers[4],receivedIntegers[5],receivedIntegers[6],
          receivedIntegers[7],receivedIntegers[8],receivedIntegers[9],receivedIntegers[10],receivedIntegers[11],receivedIntegers[12],receivedIntegers[13],receivedIntegers[14],
          receivedIntegers[15],receivedIntegers[16],receivedIntegers[17]);
      MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
      // Execute the query
      cur_mem->execute(query);
      // Note: since there are no results, we do not need to read any data
      // Deleting the cursor also frees up memory used
      delete cur_mem;
      conn.close();
      delay(10000);
    }
    else
    {
      Serial.println("Verbindung zum MySQL Server fehlgeschlagen.");
    }
  }
  else if (DatenKorrekt == false)
  {
    Serial.println("Leider nicht korrekt abgelaufen");
  }
memset(receivedIntegers, 0, sizeof(receivedIntegers));
}

Many standard Arduino boards (e.g. Uno, Mega, Nano, Pro Mini) will reset whenever you open Serial Monitor so that could be why the problem seems to be resolved after you open Serial Monitor.

ElPaso:

      MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

// Execute the query
      cur_mem->execute(query);
      // Note: since there are no results, we do not need to read any data
      // Deleting the cursor also frees up memory used
      delete cur_mem;

Use of dynamic memory allocation in the resource constrained environment of a microcontroller is generally a very bad idea. There are certain very specific conditions under which it can be done safely. I can't say whether that is the case here or not but certainly when you start getting strange behavior after some time that would make me suspicious.

A tool I have found useful for diagnosing the cause of code hanging is this library:

This library is only compatible with AVR microcontrollers (Uno, Mega, Leonardo, etc.).

Note that you should not use the watchdog timer on Pro Mini or old Nanos unless you have replaced their buggy bootloader which is not compatible with watchdog resets.

Note that the maximum watchdog timeout is 8 seconds so you would need to make some accommodations if you want to keep that 10 second delay.

Hello pert

Thanks a lot for the answer.

I will look into the dynamic memory allocation part.

Concerning the watchdog. As far as i understand it will only help me in case the sketch hangs in general. Because i can only see the hanging point from disassembling the compiled sketch on my harddrive.

My sketch runs for like 3-4 hours without problems. Then it hangs for no reason.

Do you think the dynamic memory allocation is the most probable cause then?

Thanks again

ElPaso:
Concerning the watchdog. As far as i understand it will only help me in case the sketch hangs in general. Because i can only see the hanging point from disassembling the compiled sketch on my harddrive.

I don't know what you mean by "hangs in general". You do certainly need to wait for a hang to cause the watchdog timer to time out. After that you need to read the EEPROM address you set via WatchdogLog.begin(), then you need to disassemble the compiled sketch and find the address at which the watchdog reset occurred. If the results are not conclusive t might be helpful to repeat this process multiple times to see whether the results differ.

ElPaso:
Do you think the dynamic memory allocation is the most probable cause then?

I'm not sure. It certainly is an area of suspicion but the particular usage of it in this sketch looks like it could possibly be safe since it allocates the memory, does one thing with it, then deallocates. However, I'm not sure what could happen between the allocation and deallocation.