Need help with code that crashes

Hi All,
I am new here but was wondering if it would be possible for some clever contributor on here to review my bad coding and see if they are able to figure out why it crashes sometimes.
The code is to control some LEDs based on PIR and light level sensors and also incorporates some control from a touch screen and mobile phone.

If someone is able to help I will answer any questions I can.

I am a self taught amature so be gentle with me. Thanks in advance

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Please include the entire error message. It is easy to do. There is a button (lower right of the IDE window) called "copy error message". Copy the error and paste into a post in code tags. Paraphrasing the error message leaves out important information.

Please post a schematic.
Please post an image of your project.
Please describe the problem better then you just did.

Place your code between code tags </> . My glass sphere is by the magician for maintenance.

Without seeing your code there is no way to give any definitive answer. But in general there are 3 main things that cause random crashes.

  1. Using the String class without knowing what you are doing. See the evils of Strings.
  2. You are using arrays and somewhere in your code there is a bounds violation. You are stepping on memory that you do not "own".
  3. You are running out of SRAM memory.

There are, I am sure, other reasons, but those are the predominant ones.

1 Like

Thanks for ghe advice. I have read the strings article and think that memory could be the problem. I am using strings to commincare on the serial port between two controllers and the nano crashes intermittently but usually after a couple of hours.
I will read the article again and see if i can understand enough to cure the problem.
Thanks very much.

Read Robin2's serial input basics tutorial to see how to receive serial data into a C_string (null terminated character array).

If you need help modifying your code to use C_strings instead of the String class, post the code and we can help with the change.

Here is a reference for the functions to manipulate C strings and arrays. https://cplusplus.com/reference/cstring/

I will see if I can figure out a solution from the info sources that you have all pointed me to.

For reference the current code is below. (If this does not look right please let me know and I will post again.)
Loaded on a Nano controller it takes input from a hundatech touchscreen and sends to another controller and receives some sensor readings from the other controller which is then reflected on the screen.

I am sure that the code can be improved but I would like to get the crash issue sorted in the short term.

Thanks again for all the help.

// IIC Wire lcd Master Writer
// by martin xhli <http://www.hundatech.com>

const char EOPmarker = '>'; //This is the end of packet marker
char serialbuf[100]; //This gives the incoming serial some room. Change it if you want a longer incoming.
#define MAX_STRING_LEN 100
#include <LiquidCrystalDisplay.h>
#include <SoftwareSerial.h>
#include <string.h>
SoftwareSerial mySerial(6, 7); // RX, TX

const uint8_t String01[] = "Password ok!";
const uint8_t String02[] = "Password error!";
const uint8_t String03[] = "Error";
const uint8_t String04[] = "Input number ok!";
const uint8_t String05[] = "Input number error!";
//const uint8_t STRING[] = "TIME HERE PLEASE";
uint8_t   identifier, cnt;
uint8_t   cmd_buffer[CMD_MAX_SIZE];
uint8_t   data_size;
uint8_t   update_en;
uint8_t   command_cmd;
uint8_t   command_statu;
uint8_t   command_length;
uint8_t   page_Id_bk = 0;
uint8_t   page_Id = 0;
uint8_t   targe_Id = 0;

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 60000; // Timer for Date
unsigned long startMillis2;
unsigned long currentMillis2;
const unsigned long period2 = 5000; // Timer for time update on screen

int ContValue;
int ESP32R = 8;
LiquidCrystal TFTlcd(13);//RST pin13
int upper = 3700;
int lower = 3000;
int yold;
int v;
char* d;
char* t;
int z;
int y;

void setup()
{
  update_en = 0;
  data_size = 0;
  TFTlcd.queue_reset();

  Serial.begin(57600);
  Serial.flush();
  Serial.println(F("Paint!"));
  TFTlcd.begin();

  mySerial.begin(57600);
  mySerial.flush();
  pinMode(ESP32R, OUTPUT);
  digitalWrite(ESP32R, LOW);
  digitalWrite(LED_BUILTIN, LOW);
  delay(50);
  digitalWrite(ESP32R, HIGH);
  attachInterrupt(0, LcdIICInterrupt, FALLING); //Interrupt 0 is D2 PIN
  TFTlcd.SetPage(1);//main page id is 1
}

void LcdIICInterrupt()
{
  command_cmd = TFTlcd.I2C_Read();
  TFTlcd.queue_push(command_cmd);
  for (cnt = 0; cnt < 2; cnt++)
  {
    identifier = TFTlcd.I2C_Read();
    TFTlcd.queue_push(identifier);
    Serial.println(identifier, HEX);
  }
  command_statu = TFTlcd.I2C_Read();
  TFTlcd.queue_push(command_statu);
  identifier = TFTlcd.I2C_Read();
  TFTlcd.queue_push(identifier);
  command_length = TFTlcd.I2C_Read();
  TFTlcd.queue_push(command_length);
  if ((command_cmd == GET_EDIT_VALUE && command_statu == 0x6f) || (command_cmd == GET_TOUCH_EDIT_VALUE && command_statu == 0x6f))
  {
    for (cnt = 0; cnt < command_length; cnt++)
    {
      identifier = TFTlcd.I2C_Read();
      TFTlcd.queue_push(identifier);
      Serial.println(identifier, HEX);
    }
  }

}

void loop()
{

  data_size = TFTlcd.queue_find_cmd(cmd_buffer, CMD_MAX_SIZE);
  if (data_size > 0) //receive command
  {
    Serial.print("Data Size ");
    Serial.println(data_size, HEX);
    Serial.println(F("ProcessMessage"));
    ProcessMessage((PCTRL_MSG)cmd_buffer, data_size);//command process
  }

  if (update_en)
  {
    Serial.println(F("UpdateUI"));
    update_en = 0;
    delay(100);
    UpdateUI();
  }

  if (mySerial.available() > 0) { //makes sure something is ready to be read
    static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
    char inchar = mySerial.read(); //assigns one byte (as serial.read()'s only input one byte at a time
    if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
      serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
      bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
    }
    else { //once the end of package marker has been read
      serialbuf[bufpos] = 0; //restart the buff
      bufpos = 0; //restart the position of the buff

      //      Serial.println("parseData");
      //      Serial.println(serialbuf);
      char * pch;                     // pointer to tokens
      //      Serial.print("Splitting string ");
      //      Serial.print(serialbuf);
      //      Serial.println(" into tokens:");
      pch = strtok (serialbuf, ",/}");        // get first token
      while (pch != NULL)
      {
        int g = 999;
        //        Serial.print("string found ");
        //        Serial.println(pch);          // print it
        int x = atoi(pch);
        if (x == 40) {
          TFTlcd.SetPage(1);
          TFTlcd.SetBarGaugeValue(1, 91, v);
          TFTlcd.SetLableValue(1, 67, (unsigned char *)d);
          TFTlcd.SetLableValue(1, 68, (unsigned char *)t);
        }
        else if (x == 8 || x == 13) {
        }
        else if (x == 9) {
        }
        pch = strtok (NULL, ",/}");     // get next token
        //        Serial.print("string found ");
        //        Serial.println(pch);          // print it
        y = atoi(pch);
        //        Serial.println(y != yold);
        if (y == 1 && y != yold) {
          TFTlcd.SetProgressbarValue(1, 44, 100);
          yold = y;
        }
        else if (y == 0 && y != yold) {
          TFTlcd.SetProgressbarValue(1, 44, 0);
          yold = y;
        }
        pch = strtok (NULL, ",/}");     // get next token
        //        Serial.print("string found ");
        //        Serial.println(pch);          // print it
        z = atoi(pch);
        v = 100 - (z / 41);

        TFTlcd.SetBarGaugeValue(1, 91, v);
        TFTlcd.SetNumberValue(1, 45, v);

        pch = strtok (NULL, ",/}");     // get next token
        //        Serial.print("string found ");
        //        Serial.println(pch);          // print it
        d = pch;
        currentMillis = millis();
        if (currentMillis - startMillis >= period) {
          TFTlcd.SetLableValue(1, 67, (unsigned char *)d);
          startMillis = millis();
        }
        pch = strtok (NULL, ",/}");     // get next token
        Serial.print("string found ");
        Serial.println(pch);          // print it
        t = pch;
        currentMillis2 = millis();
        if (currentMillis2 - startMillis2 >= period2) {
          TFTlcd.SetLableValue(1, 68, (unsigned char *)t);
          startMillis2 = millis();
        }
        pch = strtok (NULL, ",/}");     // get next token

      }
    }
  }
}

char* subStr (char* input_string, char *separator, int segment_number) {
  char *act, *sub, *ptr;
  static char copy[MAX_STRING_LEN];
  int i;
  strcpy(copy, input_string);
  for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
    sub = strtok_r(act, separator, &ptr);
    if (sub == NULL) break;
  }
  return sub;
}

void ProcessMessage( PCTRL_MSG msg, uint16_t dataSize )
{
  uint8_t cmd_type    = msg->cmd_type;
  uint8_t control_id  = msg->control_id;
  uint8_t page_id     = msg->page_id;
  uint8_t _status     = msg->status;
  uint8_t key_type    = msg->key_type;
  uint8_t key_value   = msg->key_value;
  switch (cmd_type)
  {
    case NOTIFY_TOUCH_BUTTON:
      NotifyTouchButton(page_id, control_id, _status, key_type, key_value);
      break;

    default:
      break;
  }
}

void UpdateUI()
{
  int i;
  int value;
  Serial.print("page_Id =  ");
  Serial.println(page_Id);
  if (page_Id == Text_PAGE)
  {
    TFTlcd.SetNumberValue(page_Id, 19, 20);
    TFTlcd.SetNumberValue(page_Id, 20, 21);
    TFTlcd.SetNumberValue(page_Id, 21, 28);
    TFTlcd.SetNumberValue(page_Id, 22, 35);
    TFTlcd.SetNumberValue(page_Id, 23, 46);
    TFTlcd.SetNumberValue(page_Id, 24, 58);
    TFTlcd.SetLableValue(page_Id, 16, (unsigned char *)String03);
    TFTlcd.SetLableValue(page_Id, 17, (unsigned char *)String03);
    TFTlcd.SetLableValue(page_Id, 18, (unsigned char *)String03);
  }
}

void NotifyTouchButton(uint8_t page_id, uint8_t control_id, uint8_t  state, uint8_t type, uint8_t value)
{
  //TODO:


  ContValue = control_id;
  mySerial.write(ContValue);
  Serial.print("Contvalue sent = ");
  Serial.println(ContValue);

  if (type == CHANGE_PAGE && state == KEY_RELEASE)
  {
    page_Id = value;
    update_en = 1;
    Serial.println("CHANGE ?? ");
    //UpdateUI();
  }
  else if (type == ENTER && state == KEY_RELEASE)
  {
    targe_Id = value;//targe Edit Id
    TFTlcd.GetEditValue(page_Id, targe_Id);
    Serial.println("ENTER ?? ");
  }
  else if (type == CHAR)
  {
    Serial.println("CHAR ?? ");
  }
  else if (type == UPLOAD_CONTROL_ID)
  {
    Serial.println("UPLOAD ?? ");
  }
  else if (type == CLEAR)
  {
    Serial.println("CLEAR ?? ");
  }

  if (ContValue == 40)  {
  }
  else if (ContValue == 8 || ContValue == 13)
  {
    TFTlcd.SetBarGaugeValue(1, 91, v);
    TFTlcd.SetLableValue(1, 67, (unsigned char *)d);
    TFTlcd.SetLableValue(1, 68, (unsigned char *)t);
    TFTlcd.SetProgressbarValue(1, 44, 100);
    yold = 1;
    ContValue = 0;
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.