arduino crash due to Serial and String...

Guys,

There is a post i made here: Serial TX LED full time ON - Project Guidance - Arduino Forum which is like the same seeemed to me at here: Arduino freezing / locking up - Programming Questions - Arduino Forum

Now, here is my entire code in attachment.

Now, I'm not that good in programming.. but as said symptoms are identical and thus I think it's either a SRAM issue or something else. Coz when I keep the serial reading by a terminal, it runs forever nearly... but if not, just powered up and running, then the game starts... hangs after few hours...

Yes!! RAM i haven't found changed but how?? coz i was taking the serial readings via terminal at all...

If it is due to SRAM and Strings... then I need your kind assistance to convert it to c_str()

I'm ore comfortable with String as you have seen in my codes... Thus how can we move forward??

code.txt (29.4 KB)

One note just incase I forgot... The hardware runs well... Ethernet shield and SPI driven and there is not issues there... confirmed... the ONLY issue is it hangs after some time like the URL I gave, the same symptom. Also, earlier I used a blink LEd type thing for another disco light project (relay driven on/off) and there wa also serial output in code but it was running standalone... So Hope you now understands what I want to point...

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

...R

Robin2:
It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

...R

Ya I know... that's what I came to know lately.. but as I'm more of a String guy, I need kind assistance on how to convert them to what you said... I'm not saying rewriting the code for me... just one statement I need from experts as a sample...

In another of my project, I used String and then used

String datai2c = "MCS01";
  Wire.beginTransmission(displayI2CID); // transmit to device #8
  Wire.write(datai2c.c_str());    // sends five bytes
  Wire.endTransmission();
  datai2c = "";

for a i2c transmission. That's where upto my level of skill... But also as I need many
str_rx = Serial.readStringUntil("\n"); for the purpose self explanatory, I need a solution alternative of such... Any help???

It looks to me like you already have half of your answer in this code

String datai2c = "MCS01";
  Wire.beginTransmission(displayI2CID); // transmit to device #8
  Wire.write(datai2c.c_str());    // sends five bytes
  Wire.endTransmission();
  datai2c = "";

I think this will work

char datai2c[] = "MCS01";
  Wire.beginTransmission(displayI2CID); // transmit to device #8
  Wire.write(datai2c); 
  Wire.endTransmission();
  datai2c[0] = 0;

However I would recommend defining all your cstrings as global (at the top of your program) so you know exactly how much memory they need - especially if you are using a lot of text.

You can also use the F macro to store fixed pieces of text in PROGMEM so that they don't use up SRAM memory.

...R

Is it possible to write and make use of something like this?

void setup() {
  pinMode(hwSS, OUTPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(readerLED, OUTPUT);
  pinMode(systemLED, OUTPUT);
  pinMode(logicSource, OUTPUT);
  pinMode(debugEnable, INPUT);
  digitalWrite(logicSource, HIGH);
  digitalWrite(buzzer, LOW);
  digitalWrite(readerLED, HIGH);
  digitalWrite(systemLED, HIGH);
  delay(100);
  digitalWrite(buzzer, HIGH);
  rebootTimer = EEPROM.read(REBOOT_OFFSET) * 3600000;
  keepAliveTimer = EEPROM.read(KEEPALIVE_OFFSET) * 60000;

  if(debugEnable == HIGH) {
    #define DEBUG
  }

  #ifdef DEBUG
   #define DEBUG_PRINT(x)     Serial.print (x)
   #define DEBUG_PRINTDEC(x)     Serial.print (x, DEC)
   #define DEBUG_PRINTHEX(x, HEX)  Serial.print (x, HEX)
   #define DEBUG_PRINTLN(x)  Serial.println (x)
  #else
   #define DEBUG_PRINT(x)
   #define DEBUG_PRINTDEC(x)
   #define DEBUG_PRINTHEX(x, HEX)
   #define DEBUG_PRINTLN(x) 
  #endif
  
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  splashScreen();
  Serial.println();
  Serial.println(F("Type 'conf t' in 4 seconds to enter config mode\n"));
  smartDelayPrompt(4000);
  //Config the system
  if (str_rx == "conf t") {
    str_rx = ""; 
    configMode();
  }
  wdt_enable(WDTO_8S);
  wiegandInit();
  Serial.println();
  // start the Ethernet connection:
  if (inetInit()){
    Serial.println(F("Ethernet is up and ready with the config:"));
    showNetConfig ();
    keepAlive();
    digitalWrite(readerLED, LOW);
    digitalWrite(systemLED, LOW);
  } else {Serial.println(F("Ethernet failed to be ready."));soft_reset(3000);}
  
}

I have given the entire code here. The motivation is: I wish to keep an enable jumper, pin11 will be source and pin 12 will be a input_pullup. This way all I want to is manipulate the jumper use such a way, a if pin11 sends 0 then pin 12 will read LOW and thus will disable the debug. If we remove the jumper (as jumper removal will be ONLY for debug purpose), pin12 will see HI and will enable the debug process.

Robin2:
You can also use the F macro to store fixed pieces of text in PROGMEM so that they don't use up SRAM memory.

...R

That part is now a standard practice for me... :slight_smile:

And how about reading?? As i do read a lot of String...

aq_mishu:
I have given the entire code here.

Not as far as I can see.

And how about reading?? As i do read a lot of String...

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

...R

Robin2:
Not as far as I can see.

Nope... the attachment has the entire code (yes, not the libraries... but do we need them??)

Plus what about the "#define issue base on if clause via debug enable port??

aq_mishu:
Nope... the attachment has the entire code

Reply #5 (which I quoted from) has no attachment.

Please post the latest version of your complete program in your next Reply.

...R

The entire source code given... no hidings... :-p

Student_Attendance_fw1-6-0-TDS.ino (28.7 KB)

I have lost track of your question now.

Is it this, from Reply #5

I have given the entire code here. The motivation is: I wish to keep an enable jumper, pin11 will be source and pin 12 will be a input_pullup. This way all I want to is manipulate the jumper use such a way, a if pin11 sends 0 then pin 12 will read LOW and thus will disable the debug. If we remove the jumper (as jumper removal will be ONLY for debug purpose), pin12 will see HI and will enable the debug process.

If so that seems a sensible thinng but I don't understand what problem you are having. I don't see any attempt to read the status of enablePin in setup(). For example

debugEnabled == digitalRead(enablePin);

(I think debugPin would be a more obvious name but YMMV).

And you can't use the state of a pin at runtime to set a #define at compile-time. You can use a variable, for example debugEnabled, to determine whether things are printed - like this for example

if (debugEnabled == true) {
  Serial.println("my error message");
}

Separately, you still have String in lots of places and you also have lots of fixed text that is not using the F macro.

...R

Robin2:
Separately, you still have String in lots of places and you also have lots of fixed text that is not using the F macro.

...R

first of all, sorry for causing the loose of track!!

OK now, I got it after a lot of reading and a hecktik day of loosing my 20 years of data through a HDD crash of my cloud drive. Blah!!

Anyway... So, yep, i understood... though i tried to keep it a bit short, but discovered, i have to write so many of the "IF"s to achieve that. No sir, so far I can see in my codes, I have used a lot of F( as after learning that "F" thing it's now a defacto in my codes...

But still there are strings... (Strings). And I have tried to convert few, like:

//String str_rx = "";
char str_rx[30];

//String data = "";
int data;
if (str_rx == "conf t") {
    str_rx[0] = 0; 
    configMode();
  }
static void smartDelayPrompt(unsigned long ms) {
  unsigned long start = millis();
  do {
    while (Serial.available() > 0){  
      Serial.readBytesUntil(10, str_rx, 30);
    }
  } 
  while (millis() - start < ms);
  //do something
}

etc, now the next error is at:

    if ((str_rx.startsWith("?"))||(str_rx.startsWith("help"))) { //show the help

and dont know how to solve it... Plus,

void postData() {
  if (!inetOK) {
    inetInit();
  }
  wdt_reset();
  unsigned int strSize = EEPROM.read(SERVER_ADDR_SIZE);
  char server[strSize];
  eeprom_read_string(SERVER_ADDR_OFFSET, server, strSize);
  String myURL = "GET /attd_posting.php?tag=";
  myURL += data;
  myURL += " HTTP/1.1";
  digitalWrite(readerLED, HIGH);
  digitalWrite(systemLED, HIGH);
  client.stop();
  DEBUG_PRINTLN(F("Connecting to server..."));
  // if you get a connection, report back via serial:
  
.........
  
}

Here is also I think I need that String...

[God!!Why String is so giving pain... heap is why growing??]

From Reply #12

etc, now the next error is at:

if ((str_rx.startsWith("?"))||(str_rx.startsWith("help"))) { //show the help

When you use cstrings you must use different functions to manipulate them. I gave you a link in Reply #2.

I agree that cstrings are not as easy to use as the String class - but that convenience is a luxury that comes with a much more powerful processor - such as PC or RaspberryPi.

...R

ummm... just it become hang again... RESET also did not worked... I was wondering, why watchdog is not working...

looking into the link you gave...

One more thing... WDT Reset... can I use that?? Then I need a real describing of a practical step by step... like

if(condition matches) {
WDT Reset;
}

I am not familiar with using the watchdog so I won't offer any advice about it.

Do you really need it?

...R

#include <MemoryFree.h>
#include <avr/wdt.h>

// On Arduino Leonardo with ATmega32U4:
//
// Reported free memory with str commented out:
// 2373 bytes
//
// Reported free memory with str and Serial.println(str) uncommented:
// 2359 bytes
//
// Difference: 14 bytes (13 ASCII chars + null terminator)

// 14-bytes string
//char str[] = "Hello, world!";

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  wdt_enable(WDTO_8S);
}

void loop() {
//  Serial.println(str);
  wdt_reset();
  for (int i=0; i<30; i++){
    wdt_reset();
    Serial.print("Iteration: ");
    Serial.println(i);
    Serial.print("freeMemory()=");
    Serial.println(freeMemory());
  
    delay(1000);
    if (i==25){
      delay(9000);
    }
  }
}

This is a code that i used for testing the watchdog. Strangely, i found, it freezes the arduino and only a power cycle is the lat savior. Basically i was playing with the WDT and planning was WDT @ 8s, and it will go until a time, say 25 sec. on 25th sec, i added a delay of 9s so before that WDT will enabled and it will make a reset. But instead, it freezes...

Robin2:
Do you really need it?

...R

Just in case system is unstable, and needs a fresh restart (basically the kaboom heap growth issue), then i was planning on WDT. [apart from char[] :wink: ]

aq_mishu:
Just in case system is unstable, and needs a fresh restart (basically the kaboom heap growth issue),

The watchdog timer is the wrong solution or that problem.

The correct solution is to write the code properly so the heap does not grow out of bounds. Apart from anything else you are going to lose data if the WDT needs to be triggered.

...R

Robin2:
you are going to lose data if the WDT needs to be triggered.

...R

This will just read a RFID reader and will pass it to another machine. No storage at all... so I'm not worried about data loose for this project. But yes, this is not the right solution. I'm desperately trying to solve that char[] topic.

But I ws just hoping for a auto recovery, as the machine will run for a long time, and no gurantee of what may happen... thus was thinking of a reset (reboot) when it faces kaboom...