LCD showing weird Chars after a while - Arduino crashes - code issue?

Hey,

my first post an already an issue. Its been a pretty tough time for me wirting my first sketches as I am used to javascript and php and some things are not as easy as I am used for them to be...

I have now created a sketch in combination with a LCD, Keypad Matrix and a Speaker. If I boot the system everything works pretty well until approx. 30 minutes after booting... Then all of the sudden weird chars show up and inputs are not processed correctly anymore... I have gone through all the wiring but it seems pretty fine to me.

Setup consits of:

Arduino Uno

  • SD Card shield
  • Numpad Matrix
  • Speaker

Nanoesp

  • WiFi
  • IoT via MQTT

Arduino Uno and Nanoesp communicate via I2C

The best is propably to show you the two sketches

Nanoesp

#include <NanoESP.h>
#include <NanoESP_MQTT.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <Wire.h>

#define SSID "XXX"
#define PASSWORD "XXX"

String ip, mqttId;
const char* mqttServer = "XXX";
const int mqttPort = XXX;
const char* mqttUser = "XXX";
const char* mqttPassword = "XXX";

NanoESP nanoesp = NanoESP();
NanoESP_MQTT mqtt = NanoESP_MQTT(nanoesp);

LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
int currentStatus = 0;
String phone = "";
unsigned long lastAction = 0;

void setup() {
  Serial.begin(19200);
  Serial.println("Init LCD");
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Activate I2C Connection
  Serial.println("Init I2C Com");
  Wire.begin(1);                // join i2c bus with address #1
  Wire.onReceive(receiveEvent); // register event
  // Init ESP
  Serial.println("Setup");
  nanoesp.init();
  Serial.println("Connecting to station");
  //Serial.println(nanoesp.sendCom("AT+CWDHCP=1,1"));
  if(nanoesp.configWifi(STATION, SSID, PASSWORD)){
    Serial.println("Wifi ready");
    digitalWrite(13, HIGH);
    //Print IP in Terminal
    nanoesp.getIpMac(ip,  mqttId);
    Serial.println("My IP: " + ip);
    Serial.println("My MQTT ID: " + mqttId+"\n");
    mqtt_msg lastWill = {"Device/Offline", mqttId, 0, false};
    if(mqtt.connect(0,mqttServer, mqttPort, mqttId, true, 10, &lastWill, mqttUser, mqttPassword)) {
      Serial.println(F("Connected to Broker\n"));
      mqtt_msg msgOnline = {"Device/Online", String(mqttId), 0, false};
      if(mqtt.publish(0, &msgOnline)) Serial.println("Published to:\Device/Online" + mqttId + "\n");
      delay(500);
      
      /**
      if(mqtt.subscribe(0, "Device/Commands/" + mqttId)) Serial.println("Subscribed to:\Device/Commands/" + mqttId + "\n");
      **/
      resetPhone();
    }else{
      Serial.println(F("error connecting"));
      lcd.clear();
      lcd.setCursor(0, 0); // Col, Row
      lcd.print("MQTT Error");
    }  
  }else{
    Serial.println("Wifi not ready");
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("WiFi Error");
  }
}
int playingRingtone = 0;
void loop() {
  unsigned long currentMillis = millis();
  if( currentStatus == 1 && currentMillis >= (lastAction+2500) && phone != "" && playingRingtone == 0){
    playRingtone();
    playingRingtone = 1;
  }
  if( currentStatus == 1 && currentMillis >= (lastAction+10000) && phone != "" ){
    submitNumber();
    playingRingtone = 0;
  }
  if( currentStatus > 0 && currentMillis >= (lastAction+17000) ){
    resetPhone();
  }
  mqtt.stayConnected(0);
}

void resetPhone(){
  Serial.println("Reset Phone");
  currentStatus = 0;
  phone = "";
  lcd.clear();
  lcd.setCursor(0, 0); // Col, Row
  lcd.print("Press 1");
  lcd.setCursor(0, 1); // Col, Row
  lcd.print("to start!");
}
void playRingtone(){
    Wire.beginTransmission(2);
    Wire.write("Action:1");
    Wire.endTransmission();
}
void submitNumber(){
  byte key = 1;
  currentStatus = 3;
  Serial.println("Submitting Number");
  mqtt_msg msgHCommands = {"H/C/"+mqttId, String("WA1:"+phone), 0, false};
  if(mqtt.publish(0, &msgHCommands)){
    Wire.beginTransmission(2);
    Wire.write("Action:2");
    Wire.endTransmission();
    delay(500);
    Serial.println("Published to:\H/C\n");
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("Thank you for");
    lcd.setCursor(0, 1); // Col, Row
    lcd.print("registering!");
    delay(3000);
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("You will get");
    lcd.setCursor(0, 1); // Col, Row
    lcd.print("your code.");
    delay(3000);
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("See you");
    lcd.setCursor(0, 1); // Col, Row
    lcd.print("very soon!");
    delay(3000);
    resetPhone();
  }else{
    Serial.println("Error. Please try again.");
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("Submission Error!");
    lcd.setCursor(0, 1); // Col, Row
    lcd.print("Please try again.");
    delay(5000);
    resetPhone();
  }
}
void processPhoneInput(String input){
  int lineStart,lineEnd;
  Serial.println("Input: "+String(input)+", Status: "+String(currentStatus) );
  lastAction = millis();
    
      
  // Entering phone number
  if( currentStatus == 1){
    if( input == "0" || input == "1" || input == "2" || input == "3" || input == "4" || input == "5" || input == "6" || input == "7" || input == "8" || input == "9" ){
      phone += input;
    }
    if( input == "#" ){
      lineStart = 0;
      lineEnd = phone.length()-1;
      phone = phone.substring(lineStart,lineEnd);
    }
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("Your number:");
    lcd.setCursor(0, 1); // Col, Row
    lcd.print(phone);
  }
  // Process started
  if( currentStatus == 0 && input == "1" ){
    currentStatus = 1;
    lcd.clear();
    lcd.setCursor(0, 0); // Col, Row
    lcd.print("Enter your");
    lcd.setCursor(0, 1); // Col, Row
    lcd.print("phone number");
  }
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  int lineStart,lineEnd;
  String content,value;
  while (0 < Wire.available()) { // loop through all but the last
    char c = Wire.read();
    content.concat(c);
  }
  //Serial.println(content);         // print the character
  lineStart = content.indexOf(':')+1;
  lineEnd = content.length();
  value = content.substring(lineStart,lineEnd);
  //Serial.println(value);  
  //lcd.print(value);
  content = "";
  processPhoneInput(value);
}

I know its quite a lot, but I am very thankful for any help. Hopefully I can help others soon enough!

Best
Tassilo

I notice the word "String" amongst your code.

This "C++" class does not really work on devices with limited RAM and crashes in the way you describe.

Use pre-defined char arrays instead.