My setup consists of an Arduino Uno, 4x4 matrix keypad, 16x2 LCD display. I’m using the i2c communication protocol. To run the auto counter with 99,999 being the max count, first the count is set through a piece of code. Next the interval in milliseconds is set through another code and finally the counter is implemented through a third and a separate code. Following are the codes that I’m implementing and all three are functional alone. Please suggest if any of the codes need to be corrected or any other improvements needed.
- Code to set the 5 digit count:
#include <EEPROM.h>
#include <Wire.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip
// LCD geometry
const byte LCD_COLS = 16;
const byte LCD_ROWS = 2;
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] =
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {11, 10, 9, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool getNumber = true;
unsigned long count;
const byte entryMaxSize = 5;
static char digits[entryMaxSize + 1];
static byte index;
void setup()
{
Serial.begin(115200);
lcd.begin(LCD_COLS, LCD_ROWS);
lcd.setCursor(3, 0);
lcd.print(" PRIYA");
lcd.setCursor(3, 1);
lcd.print("ELECTRONICS");
delay(100);
for (int positionCounter = 0; positionCounter < 40; positionCounter++)
{
lcd.scrollDisplayLeft();
delay(120);
}
delay(800);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Count:");
lcd.setCursor(11, 0);
lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM & print in it
}
void loop()
{
if (keypad.getKeys()) // check for keypad activity
{
// we won't handle multiple keypresses, just single ones, so just key index 0
const byte key = keypad.key[0].kchar;
const byte state = keypad.key[0].kstate; // IDLE, PRESSED, HOLD, RELEASED
switch (key)
{
case 'A': initializeCounter(); break;
case 'D': setCount(); break;
default: getCount(state, key);
}
}
}
void initializeCounter()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Count:");
index = 0; // reset the counter
getNumber = true;
lcd.setCursor(11, 0);
lcd.print(EEPROM.get(0, count)); // <<<<<<<<< read from EEPROM here & print it
}
unsigned long tempcount; // temporary count created by key entry
void getCount(const byte state, char key)
{
if (state == PRESSED)
{
if (getNumber)
{
// if not 5 characters yet
if (index < entryMaxSize)
{
// add key to userinput array and increment counter
if ( key >= '0' && key <= '9' ) // key is of type char and has a value between 0 and 9 so do something with it.
{
digits[index++] = key;
digits[index] = '\0';
tempcount = atol(digits);
char displayText[17] = "";
snprintf(displayText, sizeof(displayText), "Set Count: %5lu", tempcount);
lcd.setCursor(0, 0);
lcd.print(displayText);
}
}
else
{
Countwarning();
}
}
}
}
void setCount()
{
if (getNumber)
{
if (index == 0)
{
invalidCount();
}
else
{
lcd.clear();
lcd.print("Count Set: ");
for (byte i = 0; i < index; i++)
{
lcd.print(digits[i]);
getNumber = false;
}
unsigned long count = atol(digits);
Serial.print(count);
EEPROM.put(0, count); // <<<<<<<<< save to EEPROM here
}
}
}
void invalidCount()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Invalid Count!!");
lcd.setCursor(0, 1);
lcd.print("Press A"); // suggesting the user to enter the count again
getNumber = false;
}
void Countwarning()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("5 Digits Only!!"); // warning for the user if more than permitted digits are entered
lcd.setCursor(0, 1);
lcd.print("Press A"); // suggesting the user to enter the count again
getNumber = false;
}
- Code to set the interval in milliseconds:
#include <EEPROM.h>
#include <Wire.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip
// LCD geometry
const byte LCD_COLS = 16;
const byte LCD_ROWS = 2;
#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] =
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {11, 10, 9, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
bool acquireInterval = true;
unsigned long interval;
const byte entryMaxSize2 = 4;
static char digits2[entryMaxSize2 + 1];
static byte index2;
void setup()
{
Serial.begin(115200);
lcd.begin(LCD_COLS, LCD_ROWS);
lcd.setCursor(0, 0);
lcd.print("Set Intv:");
lcd.setCursor(10, 0);
lcd.print(EEPROM.get(100, interval)); // <<<<<<<<< read from EEPROM here & print it
lcd.print("ms");
}
void loop()
{
if (keypad.getKeys()) // check for keypad activity
{
// we won't handle multiple keypresses, just single ones, so just key index 0
const byte key = keypad.key[0].kchar;
const byte state = keypad.key[0].kstate; // IDLE, PRESSED, HOLD, RELEASED
switch (key)
{
case '*': initializeInterval(); break;
case 'D': setInterval(); break;
default: getInterval(state, key);
}
}
}
void initializeInterval()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Intv:");
index2 = 0; // reset the interval
acquireInterval = true;
lcd.setCursor(10, 0);
lcd.print(EEPROM.get(100, interval)); // <<<<<<<<< read from EEPROM here & print it
lcd.print("ms");
}
unsigned long tempinterval; // temporary interval created by key entry
void getInterval(const byte state, char key)
{
if (state == PRESSED)
{
if (acquireInterval)
{
// if not 4 characters yet
if (index2 < entryMaxSize2)
{
//add key to userinput array and increment counter
if ( key >= '0' && key <= '9') // key is of type char and has a value between 0 and 9 so do something with it.
{
digits2[index2++] = key;
digits2[index2] = '\0';
tempinterval = atol(digits2);
if (tempinterval > 1000)
{
invalidInterval();
}
else
{
char displayText[18] = "";
snprintf(displayText, sizeof(displayText), "Set Intv: %4lums", tempinterval);
lcd.setCursor(0, 0);
lcd.print(displayText);
}
}
}
else
{
Intervalwarning();
}
}
}
}
void setInterval()
{
if (acquireInterval)
{
if (index2 == 0)
{
invalidInterval();
}
else
{
lcd.clear();
lcd.print("Intv Set: ");
for (byte i2 = 0; i2 < index2; i2++)
{
lcd.print(digits2[i2]);
acquireInterval = false;
}
unsigned long interval = atol(digits2);
lcd.print("ms");
Serial.print(interval);
EEPROM.put(100, interval); // <<<<<<<<< save to EEPROM here
}
}
}
void invalidInterval()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Invalid Interval!!");
lcd.setCursor(0, 1);
lcd.print("Press *"); // suggesting the user to enter the interval again
acquireInterval = false;
}
void Intervalwarning()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("4 Digits Only!!"); // warning for the user if more than permitted digits are entered
lcd.setCursor(0, 1);
lcd.print("Press *"); // suggesting the user to enter the interval again
acquireInterval = false;
}