Tutorial: How to use Keypad | Text Entry Mode | Arduino

Introduction

In this article, I will discuss how we can use a matrix keypad for text entry purposes which is similar to T9 keypad used by Nokia and other bar phones.

The circuit is the same as the previous tutorial. Be sure to check it out here: 4×4 Keypad Introduction

Circuit Diagram

Bill Of Materials

  1. Arduino Uno or any compatible Arduino microcontroller board.
  2. 16×2 LCD for the LCD.
  3. 4×4 or 3×4 Keypad
  4. Breadboard, jumper wires, resistor, potentiometer, etc.

Hardware Instruction

  1. Connect the LCD pin 1 VSS to the Arduino GND
  2. Connect the LCD pin 2 VDD to the Arduino 5V
  3. Connect the potentiometer pin 1 and pin 3 to Arduino 5V and GND respectively, and the potentiometer center pin 2 to LCD pin 3 VEE/Vo
  4. Connect the LCD pin 4 RS to the Arduino digital pin 13
  5. Connect the LCD pin 5 RW to the Arduino GND because we only need to write to the LCD (no reading required)
  6. Connect the LCD pin 6 En to the Arduino digital pin 12
  7. Leave the LCD pin 7 D0 to pin 10 D3 not connected because we will use 4-bit mode of the LCD.
  8. Connect the LCD pin 11 D4 to the Arduino digital pin 11
  9. Connect the LCD pin 12 D5 to the Arduino digital pin 10
  10. Connect the LCD pin 13 D6 to the Arduino digital pin 9
  11. Connect the LCD pin 14 D7 to the Arduino digital pin 8
  12. Connect the LCD pin 15 Anode to the Arduino 5V via current limiting resistor (220 ohms).
  13. Connect the LCD pin 16 Cathode to the Arduino GND
  14. Connect the keypad Row1 (left-most) to the Arduino Uno digital pin D7.
  15. Connect the keypad Row2 to the Arduino Uno digital pin D6.
  16. Connect the keypad Row3 to the Arduino Uno digital pin D5.
  17. Connect the keypad Row4 to the Arduino Uno digital pin D4.
  18. Connect the keypad Column1 to the Arduino Uno digital pin D3.
  19. Connect the keypad Column2 to the Arduino Uno digital pin D2.
  20. Connect the keypad Column3 to the Arduino Uno digital pin D1.
  21. Connect the keypad Column4 (right-most) to the Arduino Uno digital pin D0.
  22. Upload the provided sketch making sure that the correct board and serial comm port is selected under the Tools menu of Arduino IDE.
  23. If it works, modify and experiment with it, and enjoy learning.

Video Demonstration

Call To Action

If you find this article as helpful, please consider supporting my Youtube Channel TechToTinker by SUBSCRIBING. Click THIS for TechToTinker Subscribe

Thank you and have a good day.

Source Code

  1/*
  2    July 16, 2020
  3    This will be use to explore the use of 4x4 keypad for
  4      1. T9 text entry
  5      2. A, B, C, and D will be use for the menu operations
  6    Author: George Bantique ( TechToTinker )
  7*/
  8
  9#include "LiquidCrystal.h"
 10#include "Keypad.h"
 11
 12#define DEFAULT_DELAY 300
 13
 14const byte ROWS = 4; //four rows
 15const byte COLS = 4; //four columns
 16
 17int x = 0;                // Holds the LCD x position
 18int y = 0;                // Holds the LCD y position
 19int minValue = 0;         // Lower character location for T9 text entry
 20int maxValue = 0;         // Max character location for T9 text entry
 21int keyPressTime = 100;   // Number of loops check of the key
 22String msg = "";          // Holds the created message
 23String num = "";          // Holds the mobile number
 24String alpha = "!@_$%?1 ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7 TUV8 WXYZ9 * 0# "; // Characters for T9 text entry
 25
 26char hexaKeys[ROWS][COLS] = { // Character matrix for the keypad
 27  {'1', '2', '3', 'A'},
 28  {'4', '5', '6', 'B'},
 29  {'7', '8', '9', 'C'},
 30  {'*', '0', '#', 'D'}
 31};
 32
 33byte rowPins[ROWS] = {7, 6, 5, 4};        // pin assignments for keypad rows
 34byte colPins[COLS] = {3, 2, 1, 0};        // pin assignments for keypad columns
 35
 36Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
 37LiquidCrystal lcd(13, 12, 11, 10, 9, 8);  // pin assignments for LCD
 38
 39byte charUp[8] = {  // arrow up character for LCD
 40  B00100,
 41  B01110,
 42  B11111,
 43  B00000,
 44  B00000,
 45  B00000,
 46  B00000,
 47  B00000
 48};
 49byte charDown[8] = {  // arrow down character for LCD
 50  B00000,
 51  B00000,
 52  B00000,
 53  B00000,
 54  B00000,
 55  B11111,
 56  B01110,
 57  B00100
 58};
 59byte charUpDown[8] = {  // arrow up and down character for LCD
 60  B00100,
 61  B01110,
 62  B11111,
 63  B00000,
 64  B00000,
 65  B11111,
 66  B01110,
 67  B00100
 68};
 69
 70byte menuLevel = 0;     // Level 0: no menu display, display anything you like
 71                        // Level 1: display main menu
 72                        // Level 2: display sub menu
 73                        // Level 3: display sub menu of sub menu
 74byte menu = 1;          // holds the menu level
 75byte sub = 1;           // holds the sub menu level
 76
 77
 78void setup()
 79{
 80  lcd.begin(16, 2);               // initialized the LCD as 16 characters with 2 lines
 81  lcd.createChar(0, charUp);      // arrow up character
 82  lcd.createChar(1, charDown);    // arrow down character
 83  lcd.createChar(2, charUpDown);  // arrow up and down character
 84  updateLevel_0();                // display the HOME screen
 85}
 86
 87void loop() {
 88  // Process the keys
 89  processkey();
 90
 91  // Do other stuffs here
 92  
 93}
 94
 95void processkey() {
 96  char key = customKeypad.getKey();
 97  if (isAlpha(key)) {   // check if key press is a letter
 98    processKeys(key);   // process it according to keys
 99  } 
100}
101
102void parseKey(int minValue, int maxValue, char keyPress) {
103  int ch = minValue;
104  char key = keyPress;
105  if (keyPress == '*') {              // if *, means backspace
106    if ( (x > 0) || (y > 0) ) {       // prevent backspace when no character yet
107      x = x - 1;                      // go back to previous character position
108      lcd.setCursor(x,y);             // set the new lcd position
109      lcd.print("*");                 // write *, which means for editing
110      msg.remove(msg.length() - 1);   // remove the last character from the string
111    }
112  } else {
113    for (int i = 0; i < keyPressTime; i++) {
114      if (key == keyPress) {          // make sure that same key is press
115        lcd.setCursor(x, y);          // set the lcd position
116        lcd.print(alpha[ch]);         // print the character according to the character position
117        ch++;                         // increment character position
118        if (ch > maxValue) {          // if the character counter reached the max value
119          ch = minValue;              // reset to min value
120          i = 0;                      // reset the loop counter
121        }
122      }
123      key = customKeypad.getKey();  // get the keypress
124      delay(10);                    // delay for some time
125    }
126    x++;                    // increment the x position
127    msg += alpha[ch - 1];   // add the character to the variable msg
128    if (x > 15) {           // if the lcd reached the rightmost position
129      y = 1;                // then wrap to the next line
130      x = 0;                // in first character in the left              
131    }
132  }
133}
134
135void enterMSG() {
136  char key;       
137  lcd.clear();  // clear the LCD display
138  x = 0;        // init the x position to zero
139  y = 0;        // init the y position to zero
140  msg = "";     // clear the msg variable
141  
142  do {
143    key = customKeypad.getKey();
144    if        (key == '1') {    // if a key is pressed, 
145      parseKey(0, 7, key);        // compare it to the alpha string array
146    } else if (key == '2') {
147      parseKey(8, 12, key);
148    } else if (key == '3') {
149      parseKey(13, 17, key);
150    } else if (key == '4') {
151      parseKey(18, 22, key);
152    } else if (key == '5') {
153      parseKey(23, 27, key);
154    } else if (key == '6') {
155      parseKey(28, 32, key);
156    } else if (key == '7') {
157      parseKey(33, 38, key);
158    } else if (key == '8') {
159      parseKey(39, 43, key);
160    } else if (key == '9') {
161      parseKey(44, 49, key);
162    } else if (key == '0') {
163      parseKey(52, 54, key);
164    } else if (key == '*') {
165      parseKey(50, 51, key);
166    } else if (key == '#') {
167      // do nothing
168    }
169  } while (key != '#');       // exit the loop when # is pressed
170
171  lcd.setCursor(0, 0);        // these are for verification only
172  lcd.print("created msg");   // feel free to modify it and
173  lcd.setCursor(0, 1);        // adapt to your specific requirements
174  lcd.print(msg);
175  delay(2000);
176}
177
178void enterNUM() {
179  char key;
180  lcd.clear();
181  x = 0;
182  y = 0;
183  num = "";
184  do {
185    key = customKeypad.getKey();
186    if (isDigit(key)) {                 // verify if the key press is a number
187      num = num + key;
188      lcd.setCursor(x,y);
189      lcd.print(key);                   // print it to the lcd
190      x++;                              // increment the x position
191      if (x > 15)                       // if the lcd reached the rightmost position
192      {                                 // then wrap to the next line
193        x = 0;
194        y = 1;
195      }
196    } else {                              // key press is not a number
197      if (key == '*') {                   // if *, means backspace
198        if ( (x > 0) || (y > 0) ) {       // prevent backspace when no character yet
199          x = x - 1;                      // go back to previous character position
200          lcd.setCursor(x,y);             // set the new lcd position
201          lcd.print("*");                 // write *, which means for editing
202          num.remove(num.length() - 1);   // remove the last character from the string
203        }
204      }
205    }
206  } while (key != '#');                   // exit the loop when # is pressed
207                                          // means entering number is complete
208  lcd.setCursor(0, 0);
209  lcd.print("created num");
210  lcd.setCursor(0, 1);
211  lcd.print(num);
212  delay(2000);
213}
214
215void sendSMS() {            // this is for demonstration only
216                            // you need to modify this and adapt
217                            // to your specific application
218  lcd.clear();
219  lcd.print("Sending SMS");
220  delay(500);
221  lcd.clear();
222  lcd.print("Done Sending");
223  delay(500);
224}
225
226void processKeys(char keyPressed) {
227  switch (menuLevel) {
228    case 0:                     // Level 0, home screen
229      switch ( keyPressed ) {
230        case 'D':               // Enter
231          menu = 1;
232          menuLevel = 1;        // go to main menu
233          updateLevel_1();      // show main menu
234          delay(DEFAULT_DELAY);
235          break;
236        case 'A': // Up
237          break;
238        case 'B': // Down
239          break;
240        case 'C': // Back
241          menuLevel = 0;        // go to home screen
242          updateLevel_0();      // show home screen
243          delay(DEFAULT_DELAY);
244          break;
245        default:
246          break;
247      }
248      break;
249    case 1:                     // Level 1, main menu
250      switch ( keyPressed ) {
251        case 'D':               // Enter
252          sub = 1;
253          menuLevel = 2;        // go to sub menu
254          updateLevel_2();      // show sub menu
255          delay(DEFAULT_DELAY);
256          break;
257        case 'A':               // Up
258          menu--;
259          updateLevel_1();      // show main menu
260          delay(DEFAULT_DELAY);
261          break;
262        case 'B':               // Down
263          menu++;
264          updateLevel_1();      // show main menu
265          delay(DEFAULT_DELAY);
266          break;
267        case 'C': // Back
268          menuLevel = 0;        // hide menu, go back to level 0
269          updateLevel_0();      // show home screen
270          delay(DEFAULT_DELAY);
271          break;
272        default:
273          break;
274      }
275      break;
276    case 2:                     // Level 2, sub menu
277      switch ( keyPressed ) {
278        case 'D':               // Enter
279          if        (sub == 1) {  // Create SMS
280            lcd.clear();
281            lcd.print("Enter message");
282            delay(1000);
283            enterMSG();
284            delay(500);
285            lcd.clear();
286            lcd.print("Enter number");
287            delay(500);
288            enterNUM();
289            menuLevel = 2;        // go to sub menu
290            updateLevel_2();      // show sub menu
291          } else if (sub == 2) {  // Send SMS
292            sendSMS();
293            menuLevel = 2;        // go to sub menu
294            updateLevel_2();      // show sub menu
295          } else if (sub == 3) {  // Read SMS
296            menuLevel = 3;        // go to sub menu of sub menu
297            updateLevel_3();      // show sub menu of sub menu
298          } else if (sub == 4) {  // Delete SMS
299            executeAction();
300            delay(1000);
301            menuLevel = 2;        // go to sub menu
302            updateLevel_2();      // show sub menu
303          }
304          delay(DEFAULT_DELAY);
305          break;
306        case 'A':               // Up
307          sub--;
308          updateLevel_2();
309          delay(DEFAULT_DELAY);
310          break;
311        case 'B':               // Down
312          sub++;
313          updateLevel_2();      // show main menu
314          delay(DEFAULT_DELAY);
315          break;
316        case 'C':               // Back
317          menuLevel = 1;        // go back to level 1
318          updateLevel_1();      // show main menu
319          delay(DEFAULT_DELAY);
320          break;
321        default:
322          break;
323      }
324      break;
325    case 3:                     // Level 3, sub menu of sub menu
326      switch ( keyPressed ) {
327        case 'D':               // Enter
328          //menuLevel = 2;        // go back to level 2
329          //updateLevel_2();      // show sub menu
330          delay(DEFAULT_DELAY);
331          break;
332        case 'A':               // Up
333          updateLevel_3();      // show sub menu
334          delay(DEFAULT_DELAY);
335          break;
336        case 'B':               // Down
337          updateLevel_3();      // show sub menu
338          delay(DEFAULT_DELAY);
339          break;
340        case 'C':               // Back
341          menuLevel = 2;        // go back to main menu
342          updateLevel_2();      // show main menu
343          delay(DEFAULT_DELAY);
344          break;
345        default:
346          break;
347      }
348      break;
349    default:
350      break;
351  }
352}
353
354void updateLevel_0() {
355  lcd.clear();
356  lcd.println("Keypad TextEntry");
357  lcd.setCursor(0, 1);
358  lcd.println("  - D for menu  ");
359}
360
361void updateLevel_1 () {
362  switch (menu) {
363    case 0:
364      menu = 1;
365      break;
366    case 1:
367      lcd.clear();
368      lcd.print(">Messages       ");
369      lcd.setCursor(0, 1);
370      lcd.print(" Contacts       ");
371      lcd.setCursor(15, 1);
372      lcd.write((byte)1);     // down arrow
373      break;
374    case 2:
375      lcd.clear();
376      lcd.print(" Messages       ");
377      lcd.setCursor(0, 1);
378      lcd.print(">Contacts       ");
379      lcd.setCursor(15, 1);
380      lcd.write((byte)2);     // up and down arrow
381      break;
382    case 3:
383      lcd.clear();
384      lcd.print(" Contacts       ");
385      lcd.setCursor(0, 1);
386      lcd.print(">Others         ");
387      lcd.setCursor(15, 1);
388      lcd.write((byte)0);     // up arrow
389      break;
390    case 4:
391      menu = 3;
392      break;
393  }
394}
395
396void updateLevel_2 () {
397  switch (menu) {
398    case 0:
399      break;
400    case 1:                                 // Messages
401      switch (sub) {
402        case 0:
403          break;
404        case 1:
405          lcd.clear();
406          lcd.print(" Messages:      ");
407          lcd.setCursor(0, 1);
408          lcd.print("  Create SMS    ");
409          lcd.setCursor(15, 1);
410          lcd.write((byte)1);     // down arrow
411          break;
412        case 2:
413          lcd.clear();
414          lcd.print(" Messages:      ");
415          lcd.setCursor(0, 1);
416          lcd.print("  Send SMS      ");
417          lcd.setCursor(15, 1);
418          lcd.write((byte)2);     // up and down arrow
419          break;
420        case 3:
421          lcd.clear();
422          lcd.print(" Messages:      ");
423          lcd.setCursor(0, 1);
424          lcd.print("  Read SMS      ");
425          lcd.setCursor(15, 1);
426          lcd.write((byte)2);     // up and down arrow
427          break;
428        case 4:
429          lcd.clear();
430          lcd.print(" Messages:      ");
431          lcd.setCursor(0, 1);
432          lcd.print("  Delete SMS    ");
433          lcd.setCursor(15, 1);
434          lcd.write((byte)0);     // up arrow
435          break;
436        default:
437          break;
438      }
439      break;
440    case 2:                                 // Relay 2
441      switch (sub) {
442        case 0:
443          break;
444        case 1:
445          lcd.clear();
446          lcd.print(" Contacts:      ");
447          lcd.setCursor(0, 1);
448          lcd.print("  Save Contacts ");
449          lcd.setCursor(15, 1);
450          lcd.write((byte)1);     // down arrow
451          break;
452        case 2:
453          lcd.clear();
454          lcd.print(" Contacts:      ");
455          lcd.setCursor(0, 1);
456          lcd.print("  Edit Contacts ");
457          lcd.setCursor(15, 1);
458          lcd.write((byte)2);     // up and down arrow
459          break;
460        case 3:
461          lcd.clear();
462          lcd.print(" Contacts:      ");
463          lcd.setCursor(0, 1);
464          lcd.print("  Del Contacts");
465          lcd.setCursor(15, 1);
466          lcd.write((byte)0);     // up arrow
467          break;
468        default:
469          break;
470      }
471      break;
472    case 3:                               // Relay 3
473      switch (sub) {
474        case 0:
475          break;
476        case 1:
477          lcd.clear();
478          lcd.print(" Others:        ");
479          lcd.setCursor(0, 1);
480          lcd.print("  Send AT       ");
481          lcd.setCursor(15, 1);
482          lcd.write((byte)1);     // down arrow
483          break;
484        case 2:
485          lcd.clear();
486          lcd.print(" Others:        ");
487          lcd.setCursor(0, 1);
488          lcd.print("  Send ATA      ");
489          lcd.setCursor(15, 1);
490          lcd.write((byte)2);     // up and down arrow
491          break;
492        case 3:
493          lcd.clear();
494          lcd.print(" Others:        ");
495          lcd.setCursor(0, 1);
496          lcd.print("  Send ATH      ");
497          lcd.setCursor(15, 1);
498          lcd.write((byte)0);     // up arrow
499          break;
500        default:
501          break;
502      }
503      break;
504    case 4:
505      sub = 3;
506      break;
507  }
508}
509
510void updateLevel_3 () {
511  switch (menu) {
512    case 0:
513      break;
514    case 1:
515      lcd.clear();
516      lcd.print(" Relay 1:");
517      lcd.setCursor(0, 1);
518      lcd.print("  Val 1 = ");
519      break;
520    case 2:
521      lcd.clear();
522      lcd.print(" Relay 2:");
523      lcd.setCursor(0, 1);
524      lcd.print("  Val 2 = ");
525      break;
526    case 3:
527      lcd.clear();
528      lcd.print(" Relay 3:");
529      lcd.setCursor(0, 1);
530      lcd.print("  Val 3 = ");
531      break;
532    case 4:
533      sub = 3;
534      break;
535  }
536}
537
538void executeAction () {
539  switch (menu) {
540    case 0:
541      break;
542    case 1:
543      lcd.clear();
544      lcd.print(" Executing # 1");
545      break;
546    case 2:
547      lcd.clear();
548      lcd.print(" Executing # 2");
549      break;
550    case 3:
551      lcd.clear();
552      lcd.print(" Executing # 3");
553      break;
554    case 4:
555      sub = 3;
556      break;
557  }
558}


Posts in this series



No comments yet!

GitHub-flavored Markdown & a sane subset of HTML is supported.