arduinoprojects

git clone https://git.tarina.org/arduinoprojects
Log | Files | Refs

DynamicKeypad.ino (9231B)


      1 /* @file   DynamicKeypad.pde
      2 || @version 1.2
      3 || @author Mark Stanley
      4 || @contact mstanley@technologist.com
      5 ||
      6 ||  07/11/12 - Re-modified (from DynamicKeypadJoe2) to use direct-connect kpds
      7 ||  02/28/12 - Modified to use I2C i/o G. D. (Joe) Young
      8 ||
      9 ||
     10 || @dificulty:  Intermediate
     11 ||
     12 || @description
     13 || |    This is a demonstration of keypadEvents. It's used to switch between keymaps
     14 || |    while using only one keypad.  The main concepts being demonstrated are:
     15 || |
     16 || |        Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding.
     17 || |        How to use setHoldTime() and why.
     18 || |        Making more than one thing happen with the same key.
     19 || |        Assigning and changing keymaps on the fly.
     20 || |
     21 || |    Another useful feature is also included with this demonstration although
     22 || |    it's not really one of the concepts that I wanted to show you.  If you look
     23 || |    at the code in the PRESSED event you will see that the first section of that
     24 || |    code is used to scroll through three different letters on each key.  For
     25 || |    example, pressing the '2' key will step through the letters 'd', 'e' and 'f'.
     26 || |
     27 || |
     28 || |  Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding
     29 || |    Very simply, the PRESSED event occurs imediately upon detecting a pressed
     30 || |    key and will not happen again until after a RELEASED event.  When the HOLD
     31 || |    event fires it always falls between PRESSED and RELEASED.  However, it will
     32 || |    only occur if a key has been pressed for longer than the setHoldTime() interval.
     33 || |
     34 || |  How to use setHoldTime() and why
     35 || |    Take a look at keypad.setHoldTime(500) in the code.  It is used to set the
     36 || |    time delay between a PRESSED event and the start of a HOLD event.  The value
     37 || |    500 is in milliseconds (mS) and is equivalent to half a second.  After pressing
     38 || |    a key for 500mS the HOLD event will fire and any code contained therein will be
     39 || |    executed.  This event will stay active for as long as you hold the key except
     40 || |    in the case of bug #1 listed above.
     41 || |
     42 || |  Making more than one thing happen with the same key.
     43 || |    If you look under the PRESSED event (case PRESSED:) you will see that the '#'
     44 || |    is used to print a new line, Serial.println().  But take a look at the first
     45 || |    half of the HOLD event and you will see the same key being used to switch back
     46 || |    and forth between the letter and number keymaps that were created with alphaKeys[4][5]
     47 || |    and numberKeys[4][5] respectively.
     48 || |
     49 || |  Assigning and changing keymaps on the fly
     50 || |    You will see that the '#' key has been designated to perform two different functions
     51 || |    depending on how long you hold it down.  If you press the '#' key for less than the
     52 || |    setHoldTime() then it will print a new line.  However, if you hold if for longer
     53 || |    than that it will switch back and forth between numbers and letters.  You can see the
     54 || |    keymap changes in the HOLD event.
     55 || |
     56 || |
     57 || |  In addition...
     58 || |      You might notice a couple of things that you won't find in the Arduino language
     59 || |    reference.  The first would be #include <ctype.h>.  This is a standard library from
     60 || |    the C programming language and though I don't normally demonstrate these types of
     61 || |    things from outside the Arduino language reference I felt that its use here was
     62 || |    justified by the simplicity that it brings to this sketch.
     63 || |      That simplicity is provided by the two calls to isalpha(key) and isdigit(key).
     64 || |    The first one is used to decide if the key that was pressed is any letter from a-z
     65 || |    or A-Z and the second one decides if the key is any number from 0-9.  The return
     66 || |    value from these two functions is either a zero or some positive number greater
     67 || |    than zero.  This makes it very simple to test a key and see if it is a number or
     68 || |    a letter.  So when you see the following:
     69 || |
     70 || |    if (isalpha(key))    // this tests to see if your key was a letter
     71 || |
     72 || |    And the following may be more familiar to some but it is equivalent:
     73 || |
     74 || |    if (isalpha(key) != 0)   // this tests to see if your key was a letter
     75 || |
     76 || |  And Finally...
     77 || |    To better understand how the event handler affects your code you will need to remember
     78 || |    that it gets called only when you press, hold or release a key.  However, once a key
     79 || |    is pressed or held then the event handler gets called at the full speed of the loop().
     80 || |
     81 || #
     82 */
     83 #include <Keypad.h>
     84 #include <ctype.h>
     85 
     86 const byte ROWS = 4; //four rows
     87 const byte COLS = 3; //three columns
     88 // Define the keymaps.  The blank spot (lower left) is the space character.
     89 char alphaKeys[ROWS][COLS] = {
     90     { 'a','d','g' },
     91     { 'j','m','p' },
     92     { 's','v','y' },
     93     { ' ','.','#' }
     94 };
     95 
     96 char numberKeys[ROWS][COLS] = {
     97     { '1','2','3' },
     98     { '4','5','6' },
     99     { '7','8','9' },
    100     { ' ','0','#' }
    101 };
    102 
    103 boolean alpha = false;   // Start with the numeric keypad.
    104 
    105 byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
    106 byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad
    107 
    108 // Create two new keypads, one is a number pad and the other is a letter pad.
    109 Keypad numpad( makeKeymap(numberKeys), rowPins, colPins, sizeof(rowPins), sizeof(colPins) );
    110 Keypad ltrpad( makeKeymap(alphaKeys), rowPins, colPins, sizeof(rowPins), sizeof(colPins) );
    111 
    112 
    113 unsigned long startTime;
    114 const byte ledPin = 13;                            // Use the LED on pin 13.
    115 
    116 void setup() {
    117     Serial.begin(9600);
    118     pinMode(ledPin, OUTPUT);
    119     digitalWrite(ledPin, LOW);                 // Turns the LED on.
    120     ltrpad.begin( makeKeymap(alphaKeys) );
    121     numpad.begin( makeKeymap(numberKeys) );
    122     ltrpad.addEventListener(keypadEvent_ltr);  // Add an event listener.
    123     ltrpad.setHoldTime(500);                   // Default is 1000mS
    124     numpad.addEventListener(keypadEvent_num);  // Add an event listener.
    125     numpad.setHoldTime(500);                   // Default is 1000mS
    126 }
    127 
    128 char key;
    129 
    130 void loop() {
    131 
    132     if( alpha )
    133         key = ltrpad.getKey( );
    134     else
    135         key = numpad.getKey( );
    136 
    137     if (alpha && millis()-startTime>100) {           // Flash the LED if we are using the letter keymap.
    138         digitalWrite(ledPin,!digitalRead(ledPin));
    139         startTime = millis();
    140     }
    141 }
    142 
    143 static char virtKey = NO_KEY;      // Stores the last virtual key press. (Alpha keys only)
    144 static char physKey = NO_KEY;      // Stores the last physical key press. (Alpha keys only)
    145 static char buildStr[12];
    146 static byte buildCount;
    147 static byte pressCount;
    148 
    149 static byte kpadState;
    150 
    151 // Take care of some special events.
    152 
    153 void keypadEvent_ltr(KeypadEvent key) {
    154     // in here when in alpha mode.
    155     kpadState = ltrpad.getState( );
    156     swOnState( key );
    157 } // end ltrs keypad events
    158 
    159 void keypadEvent_num( KeypadEvent key ) {
    160     // in here when using number keypad
    161     kpadState = numpad.getState( );
    162     swOnState( key );
    163 } // end numbers keypad events
    164 
    165 void swOnState( char key ) {
    166     switch( kpadState ) {
    167         case PRESSED:
    168             if (isalpha(key)) {              // This is a letter key so we're using the letter keymap.
    169                 if (physKey != key) {        // New key so start with the first of 3 characters.
    170                     pressCount = 0;
    171                     virtKey = key;
    172                     physKey = key;
    173                 }
    174                 else {                       // Pressed the same key again...
    175                     virtKey++;                   // so select the next character on that key.
    176                     pressCount++;                // Tracks how many times we press the same key.
    177                 }
    178                     if (pressCount > 2) {    // Last character reached so cycle back to start.
    179                         pressCount = 0;
    180                         virtKey = key;
    181                     }
    182                     Serial.print(virtKey);   // Used for testing.
    183                 }
    184                 if (isdigit(key) || key == ' ' || key == '.')
    185                     Serial.print(key);
    186                 if (key == '#')
    187                     Serial.println();
    188                 break;
    189 
    190         case HOLD:
    191             if (key == '#')  {               // Toggle between keymaps.
    192                 if (alpha == true)  {        // We are currently using a keymap with letters
    193                     alpha = false;           // Now we want a keymap with numbers.
    194                     digitalWrite(ledPin, LOW);
    195                 }
    196                 else  {                      // We are currently using a keymap with numbers
    197                     alpha = true;            // Now we want a keymap with letters.
    198                 }
    199             }
    200             else  {                          // Some key other than '#' was pressed.
    201                 buildStr[buildCount++] = (isalpha(key)) ? virtKey : key;
    202                 buildStr[buildCount] = '\0';
    203                 Serial.println();
    204                 Serial.println(buildStr);
    205             }
    206             break;
    207 
    208         case RELEASED:
    209             if (buildCount >= sizeof(buildStr))  buildCount = 0;  // Our string is full. Start fresh.
    210             break;
    211     }  // end switch-case
    212 }// end switch on state function
    213