LCD I2C is malfunctioning

I have the following project and code on tinkercad - Login | Tinkercad,


#include <Keypad.h>
#include <LiquidCrystal_I2C.h>


const byte ROWS = 4;
const byte COLS = 4;
const int NEWPASS = 10;

char keys[ROWS][COLS] {
  {'1','2','3', 'A'},
  {'4','5','6', 'B'},
  {'7','8','9', 'C'},
  {'*','0','#', 'D'}
};
byte colPins[] = {2,3,4, 11};
byte rowPins[] = {5,6,7,8};

LiquidCrystal_I2C lcd(0x20,16,2);
Keypad keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int state = 0;
int prevState = 2;

char* code = "1234\0";
char* input = "\0";

void setup()
{
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.print("smartlock");
  lcd.setCursor(0,1);
  lcd.print("demo ");
  delay(2000);
  lcd.clear();
}

char* chartostr(char out) {
  char buf[2];
  buf[0] = out;
  buf[1] = '\0';
  return strcat(buf, "");
}

char* charcat(char* dest, char out) {
  
  return strcat(dest, chartostr(out));
}

void correctPassword() {
  state = 1;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Correct password");
}

void loop()
{
  lcd.setCursor(0,0);
  
  if (digitalRead(NEWPASS) == 1 && state == 1) {
    state = 2;
  }
  
  if (state != prevState) {
    lcd.clear();
    char* msg;
    switch(state) {
      case 0:
      	msg = "Enter pass";
      	break;
      case 1:
      	msg = "Welcome home";
      	break;
      case 2:
      	msg = "Enter new pass";
      	break;
    }
    lcd.print(msg);
  }
  prevState = state;
  char key = keypad.getKey();
  if (key != NO_KEY) {
    if (key == '#') {
        if (state == 2) {
          Serial.println("HI");
          code = input;
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("new pass is");
          lcd.setCursor(0,1);
          lcd.print("no");
        }
      if (state == 0) {
          if (strcmp(code, input) == 0) {
            correctPassword();
          } else {
        
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Invalid password");
            prevState = !state;
          }
          
      }
      input = "";
      delay(1000);
      
    } else {
      input = charcat(input, key);
      lcd.setCursor(0,1);
      lcd.print(input);    
    }
  }
  delay(100);
}

The issue

As you can see, the state variable defines the state of program. So, when it comes to state being equal to 2. User has an option to change the code value using the keypad. The main issue is in the display output - when user is writing a new password, it is supposed to be written on the second row of the display. But, this undefined behavior occurs when I write a number that consists of more than 2 symbols:
image

I would really appreciate any help or solution provided, and I also excuse for the quality of my code, I planned to improve it after making everything work.

strcat returns the first string, here buf. And buf remains a local variable, make it global or at least static. Also take care to always reserve enough memory for the appended text.

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