I am having trouble with a 16x2 I2C LCD screen using a 4x3 keyboard.
The following are the steps I need to do: 1.Take a numeric value through the keyboard onto the top line of the screen. This numeric value should not exceed 3 digits. 2. The keyboard should only be active (and the screen editable) when * key is pressed once. 3. The keyboard should again become inactive when # key is pressed once. 4. Whatever value has been placed in the screen should be remembered so when a sensor runs it should be able to compare its value to the screen value, achieving equality to which the core process stops.
Below is my code which is not doing the job. Can someone suggest a solution? Thanks.
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
#include<stdio.h>
const int ROW_NUM = 4;
const int COLUMN_NUM = 3;
char keys[ROW_NUM][COLUMN_NUM] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'},
};
byte pin_rows[ROW_NUM] = {8,7,6,5};
byte pin_column[COLUMN_NUM] = {4,3,2};
Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
int counter = 0;
void setup() {
// put your setup code here, to run once:
lcd.init();
lcd.clear();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Volume. ml");
lcd.setCursor(0, 1);
lcd.print("Filled ml");
}
void loop() {
// put your main code here, to run repeatedly:
keypadfunction();
}
void keypadfunction()
{
char key = keypad.getKey();
if (key)
{
}
if (key == '*')
{
while (key != '#' || counter <=3)
{
lcd.setCursor(8, 1);
lcd.setCursor(8+counter, 1);
lcd.print(key);
counter = counter+1;
}
}
}
changes after suggestions from @C1sc0:
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
#include<stdio.h>
const int ROW_NUM = 4;
const int COLUMN_NUM = 3;
char keys[ROW_NUM][COLUMN_NUM] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'},
};
byte pin_rows[ROW_NUM] = {8,7,6,5};
byte pin_column[COLUMN_NUM] = {4,3,2};
Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column,
ROW_NUM, COLUMN_NUM );
char volume[3];
byte volumeCount = 0;
bool edit = 0;
int finalValue = 0;
void setup()
{
// put your setup code here, to run once:
lcd.init();
lcd.clear();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Volume ml");
lcd.setCursor(0, 1);
lcd.print("Filled ml");
}
void loop()
{
char key = keypad.getKey();
if(key) // check if any key was pressed
{
if(key == '*') // if * was pressed switch to edit mode
{
lcd.setCursor(0,0); // set your cursor at columnt 0, row 0
lcd.clear();
lcd.print("Enter volume: ");
edit = true;
lcd.setCursor(0,1); // set your cursor to second row
volumeCount = 0;
volume[0] = '0';
volume[1] = '0';
volume[2] = '0';
}
if(edit && volumeCount < 3) // enter edit mode
{
volume[volumeCount] = key; // save key to a char array
lcd.setCursor(volumeCount,1); // set your cursor to the
next position
lcd.print(volume[volumeCount]); // print the pressed button to lcd
volumeCount++; // increment the array index (cursor position)
}
if(volumeCount == 3 || key == '#') // array.length == 3 OR you pressed #
{
edit = false; // disable edit mode
volumeCount = 0; // reset your counter
lcd.setCursor(0,0);
lcd.clear();//new
lcd.print(volume);
finalValue = atoi(volume); // save your entered value for further usage
//volume[0] = '0';
//volume[1] = '0';
//volume[2] = '0';
}
}
buttonState1 = digitalRead(buttonPin1);
if (buttonState1 == HIGH)
{
//do process basis 'finalValue'
}
}
Create a bool (or byte) variable, for signaling the "edit" state
if (key == '*') { edit= true; }
in your loop (this will be your first if condition).
Create another if and here check the edit flag (if it is true, then you are waiting for the 3 values. You can read the pressed keys to a char array
char values[3];
// create this variable, before setup()
Here for the index you can use a counter
(which is already present in your code as I saw. So, put all these lines in your second if condition, and increment your counter by one here. And you can display the entered character here too:
lcd.setCursor(8+counter, 1);
lcd.print(key);
Create a third if block, and check the counter is # key or counter == 3
. If this condition will be satisfied you have to do 3 things reset the counter to zero, reset the edit state to false, and finally convert your value to an int (with atoi
function).
After it works, you can refactor your code to make it more efficient/readable.
You need something like this:
char volume[3];
byte volumeCount = 0;
bool edit = 0;
int finalValue = 0;
void loop()
{
char key = keypad.getKey();
if(key) // check if any key was pressed
{
if(key == '*') // if * was pressed switch to edit mode
{
lcd.setCursor(0,0); // set your cursor at columnt 0, row 0
lcd.print("Enter volume: ");
edit = true;
lcd.setCursor(0,1); // set your cursor to second row
volumeCount = 0;
volume[0] = '0';
volume[1] = '0';
volume[2] = '0';
}
if(edit && volumeCount < 3 && key != '*' && key != '#')
{
volume[volumeCount] = key; // save key to a char array
lcd.setCursor(volumeCount,1); // set your cursor to the next position
lcd.print(volume[volumeCount]); // print the pressed button to lcd
volumeCount++; // increment the array index (cursor position)
}
if(volumeCount == 3 || key == '#') // array.length == 3 OR you pressed #
{
edit = false; // disable edit mode
volumeCount = 0; // reset your counter
finalValue = atoi(volume); // save your entered value for further usage
volume[0] = '0';
volume[1] = '0';
volume[2] = '0'; # ty for the fix!!!
}
}
}