Simple Keypad Input to Screen Problem

I have a program that works, until I type "#" which I thought would only have made the char str[17] equal to 16 spaces again, but when I press "#" the first column of the keypad stops responding.

What am I doing wrong here?

I thought I was being safe using char to hold the 17 length string instead of String, but I must be affecting the program to make it misbehave.

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

LiquidCrystal_I2C lcd(0x27,20,4); 
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
char str[17]="                ";
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad
int d=0;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd 
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("PLAY SONG NUMBER....");
  lcd.setCursor(0,1);
  lcd.print("");
  lcd.setCursor(0,2);
  lcd.print("");
  lcd.setCursor(0,3);
  lcd.print("");
}

void loop(){

  char key = keypad.getKey();
  if (key=='#'){
    str[17]="                ";
    d=0;
  }
  if (key and key!='#' and d<16){
    Serial.println(key);
  str[d] = key;
  d=d+1;
  Serial.println(d);
  lcd.setCursor(0,3);
  lcd.print(str);
  }
}

No, that's not how it's done.

Try

strcpy(str, "                ");

One obvious problem is this

        str[17] = "                ";

You are trying to write 16 characters to the eighteenth position in an array

Also, the str array which you seem to want to use to hold a string never has a terminating zero character added to it so there is no obvious end marker on the string

Won't this do it?

Thats a beginners mistake. The array is defined to have 17 elements, indexed from 0 up to 16. Writing at index 17 is outside the array, into some unknown area, likely used for other things.

It is true that creates an array with 16 space characters and the terminating zero but we have no idea how many characters are being entered from the keypad and/or whether the resulting string should have trailing spaces or not

Then, of course, there is the problem of

        str[17] = "                ";

You can see in the program that no more that 16 characters are being written from the keyboard.

They are ignored if they are pressed.

I have made a change as suggested, and now it will not print "CLEARED SCREEN" to screen when I press "#". Is this expected behaviour?

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

LiquidCrystal_I2C lcd(0x27, 20, 4);
const byte ROWS = 4;  //four rows
const byte COLS = 4;  //three columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
char str[17] = "                ";
byte rowPins[ROWS] = { 5, 4, 3, 2 };  //connect to the row pinouts of the keypad
byte colPins[COLS] = { 9, 8, 7, 6 };  //connect to the column pinouts of the keypad
int d = 0;
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(9600);
  lcd.init();  // initialize the lcd
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("PLAY SONG NUMBER....");
  lcd.setCursor(0, 1);
  lcd.print("");
  lcd.setCursor(0, 2);
  lcd.print("");
  lcd.setCursor(0, 3);
  lcd.print("");
}

void loop() {

  char key = keypad.getKey();
  if (key == '#') {
    strcpy(str, "                ");
    lcd.setCursor(0, 3);
    lcd.print("CLEARED   SCREEN");
    d = 0;
  }

  if (key and key != '#' and d < 16) {
    Serial.println(key);
    str[d] = key;
    Serial.println(d);
    lcd.setCursor(0, 3);
    lcd.print(str);
        d = d + 1;
  }
}

What you say is true but is it OK for the string to have trailing spaces if only a few characters are entered ?

Have you fixed the problem with

        str[17] = "                ";

The 'string' is only getting used to print to the 20 width line of an LCD screen. That should be okay, shouldn't it?

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

LiquidCrystal_I2C lcd(0x27, 20, 4);
const byte ROWS = 4;  //four rows
const byte COLS = 4;  //three columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
char str[17] = "                ";
byte rowPins[ROWS] = { 5, 4, 3, 2 };  //connect to the row pinouts of the keypad
byte colPins[COLS] = { 9, 8, 7, 6 };  //connect to the column pinouts of the keypad
int d = 0;
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

void setup() {
  Serial.begin(115200);
  lcd.init();  // initialize the lcd
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("PLAY SONG NUMBER....");
  lcd.setCursor(0, 1);
  lcd.print("");
  lcd.setCursor(0, 2);
  lcd.print("");
  lcd.setCursor(0, 3);
  lcd.print("");
}

void loop() {

  char key = keypad.getKey();
  if (key) {
  if (key == '#') {
    strcpy(str,"                ");
    lcd.setCursor(0, 3);
    lcd.print("CLEARED   SCREEN");
    delay(50);
    d = 0;
  }

  if (key != '#' and d < 16) {
    Serial.println(key);
    str[d] = key;
    Serial.println(d);
    lcd.setCursor(0, 3);
    lcd.print(str);
        Serial.println(sizeof(str));
            Serial.println(str);
        d = d + 1;
  }
  }
}

I don't see why you ever need to fill the array with blanks.

edit: I see what you are doing, never mind, that could work, just looks odd…


    str[d] = key;
    Serial.println(d);

And you need to keep putting the null terminator as you build it, viz:

    str[d] = key;
    str[d + 1] = '\0';
    Serial.println(d);

HTH

a7

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