element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Arduino Forum Keypad interfacing challenge
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • State Verified Answer
  • Replies 9 replies
  • Answers 1 answer
  • Subscribers 392 subscribers
  • Views 1349 views
  • Users 0 members are here
  • interrupt
  • keypad
  • Design
  • arduino
Related

Keypad interfacing challenge

Former Member
Former Member over 11 years ago

Hi everyone! I am trying to interface a 4 x 4 keypad with my Arduino UNO. I am able to get it little bit working but not 100% the way i want.

 

I want some keypad buttons to act different from others. So for example, i have 12 buttons that when RELEASED should trigger a particular function. However i want the remaining 4 buttons to trigger a different function when released and keep triggering that function when the keypad buttons are still in PRESSED state. So to give a proper example, I want to press a button on keypad which will wait for a little while and then it should start to increment a value (like increasing speed while the button is in pressed state).

 

I am able to get the RELEASED and HOLD states working from the Arduino keypad library.  But HOLD state only triggers once. If i am able to trigger the HOLD state over and over again after some delay, that would solve the problem i believe. Can anyone please help me.

 

#include <Keypad.h>


/**
  Globals
**/
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns


// Define the Keymap
char keys[ROWS][COLS] = {
  {'1', '2', '3', '4'}, /*  S1   S2 S3   S4  */
  {'5', '6', '7', '8'}, /*  S5   S6   S7   S8  */
  {'A', 'C', 'E', 'G'}, /*  F1U   F2U   ON   NC  */
  {'B', 'D', 'F', 'H'} /*  F1D   F2D   OFF   NC  */
};


// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 5, 4, 3, 2 };
// Connect keypad COL0, COL1, COL2 and COL3 to these Arduino pins.
byte colPins[COLS] = { 9, 8, 7, 6 };


// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


byte ledPin = 13;
boolean blink = false;




/**
  Setup
**/
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  digitalWrite(ledPin, HIGH);   // sets the LED on

  /* Keypad event listener - Interrupt */
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad




}




/**
  Loop
**/
void loop() {


  /* Check for keypad */
  keypad.getKey();



  if (blink) {
  digitalWrite(ledPin,!digitalRead(ledPin));
  delay(100);
  }
}




//take care of some special events
void keypadEvent( KeypadEvent key ){
  switch ( keypad.getState() ) {
  case PRESSED:
  break;


  case RELEASED:
  switch (key) {
  /* TOGGLES */
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
  case '7':
  case '8':
  Serial.print("SWITCH: ");
  Serial.println(key);
  //toggleSwitch(key);
  break;


  /* FAN 1 */
  case 'A':
  Serial.println("FAN 1 UP");
  break;


  case 'B':
  Serial.println("FAN 1 DOWN");
  break;




  /* FAN 2 */
  case 'C':
  Serial.println("FAN 2 UP");
  break;


  case 'D':
  Serial.println("FAN 2 DOWN");
  break;




  /* MASTER CONTROLLS */
  case 'E':
  Serial.println("ALL ON");
  break;


  case 'F':
  Serial.println("ALL OFF");
  break;




  default:
  Serial.print("UNMAPPED: ");
  Serial.println(key);
  break;
  }
  break;


  case HOLD:
  switch (key) {
  /* FAN 1 */
  case 'A':
  Serial.println("FAN 1 UP");
  break;


  case 'B':
  Serial.println("FAN 1 DOWN");
  break;




  /* FAN 2 */
  case 'C':
  Serial.println("FAN 2 UP");
  break;


  case 'D':
  Serial.println("FAN 2 DOWN");
  break;
  }
  break;


  case IDLE:
  break;
  }
}




void toggleSwitch( char num ) {
  Serial.println(num);
}

 

 

I want the FAN speeds to increase/decrease when the buttons 'A', 'B', 'C' and 'D' are held pressed.

  • Sign in to reply
  • Cancel
  • Robert Peter Oakes
    0 Robert Peter Oakes over 11 years ago

    You have nothing in the Pressed case therefor no way of knowing when a key is pressed, never mind being held pressed

     

    1.   switch ( keypad.getState() ) { 
    2.   case PRESSED: 
    3.   break;

     

    Your trying to perform the actions when the key is released which of course will only work once as there is no longer anything to detect once you have actually released the key

     

    what you need to do it set a variable equal to the key that is pressed. Do this in the pressed case part of the code, take no other action other than setting this variable

    in the release case, you clear the variable to an un-used value

     

    in the loop, you check if the variable is set to a value and if it is then perform your chosen task for that key

     

    this means you will have 3 sets of case statements but this can be simplified in the pressed and released case statements to simply recording the key that was pressed and move all the key processing to the main loop

     

    If the keyboard handler can detect multiple keys then you may want a different approach but I doubt it can based on simple matrix keyboards

     

    sudo code will look like this  (You will have to code it correctly, this is just to give you the idea)

     

    char mykey = 'x';

     

    loop()

    {

         if mykey != 'x'

         {

         switch mykey

             {

             /* FAN 1 */ 

              case 'A':    Serial.println("FAN 1 UP");  break;

              case 'B':  Serial.println("FAN 1 DOWN");  break; 

              etc

             }

    //take care of some special events 

    void keypadEvent( KeypadEvent key )

    { 

         switch ( keypad.getState() )

         { 

              case PRESSED:  mykey = key;  break;   

              case RELEASED:  mykey = 'x';  break; 

         }

    }


    you may also have to mess with the loop delay if it increments too fast

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Reject Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to Robert Peter Oakes

    Thank you very much Peter.

    I have tried to implement your logic in the code below. Its working as i wanted. However i have noticed something. When i add little code in my main loop after the keyPressed check logic, I have to decrease the delay adjustment value quite a lot. If i comment the code on line 110 onwards, the adjustment value on line 102 is 15000. However if i uncomment line 110 i have to change the adjustment value on line 102 to about 500 and if i uncomment the delay at line 111 i have to set the adjustment value on line 102 to about 8.

     

    So its quite a significant change in values. What if i change the standard 16MHz oscillator to 40MHz (which is the max i believe for Arduino UNO), will that mess up the delay functions?

     

    #include <Keypad.h>
    
    
    /**
      Globals 
    **/
    const byte ROWS = 4; // Four rows
    const byte COLS = 4; // Four columns
    
    
    // Define the Keymap
    char keys[ROWS][COLS] = {
      {'1', '2', '3', '4'}, /*  S1   S2 S3   S4  */
      {'5', '6', '7', '8'}, /*  S5   S6   S7   S8  */
      {'A', 'C', 'E', 'G'}, /*  F1U   F2U   ON   NC  */
      {'B', 'D', 'F', 'H'} /*  F1D   F2D   OFF   NC  */
    };
    
    
    // Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
    byte rowPins[ROWS] = { 5, 4, 3, 2 };
    // Connect keypad COL0, COL1, COL2 and COL3 to these Arduino pins.
    byte colPins[COLS] = { 9, 8, 7, 6 }; 
    
    
    // Create the Keypad
    Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
    
    
    byte ledPin = 13;
    boolean blink = false;
    boolean keyPressed = false;
    byte pressedKey = ' ';
    int keypadDelayCounter = 0;
    
    
    /**
      Setup
    **/
    void setup() {
      Serial.begin(9600);
      pinMode(ledPin, OUTPUT);      // sets the digital pin as output
      digitalWrite(ledPin, HIGH);   // sets the LED on
    
      /* Keypad event listener - Interrupt */
      keypad.addEventListener(keypadEvent); //add an event listener for this keypad
    }
    
    
    
    
    /**
      Loop
    **/
    void loop() {
    
    
      // Check for keypad
      keypad.getKey();
    
    
    
    
      // If key is pressed (HOLD state)
      if ( keyPressed ) {
      // Serial.println("KEYPRESSED");
      // Serial.println(pressedKey);
      // Serial.println(keypadDelayCounter);
      switch (pressedKey) {
      /* FAN 1 */
      case 'A':
      keypadDelayCounter++;
      break;
    
    
      case 'B':
      keypadDelayCounter++;
      break;
    
    
      /* FAN 2 */
      case 'C':
      keypadDelayCounter++;
      break;
    
    
      case 'D':
      keypadDelayCounter++;
      break;
    
    
      default:
      // Key held pressed other than Dimmers
      keypadDelayCounter = 0;
      break;
      }
    
    
      // Main keypad hold delay adjustment
      if ( keypadDelayCounter > 15000 ) {
      Serial.println("INCREMENT/DECREMENT");
      keypadDelayCounter = 0;
      }
      }
    
    
    
      //digitalWrite(ledPin,!digitalRead(ledPin));
      //delay(100);
    }
    
    
    
    
    //take care of some special events
    void keypadEvent( KeypadEvent key ){
      switch ( keypad.getState() ) {
      case PRESSED:
      break;
    
    
      case RELEASED:
      // Reset keypad delay and set keypressed to false
      keyPressed = false;
      keypadDelayCounter = 0;
      switch (key) {
      // TOGGLES
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      Serial.print("SWITCH: ");
      Serial.println(key);
      //toggleSwitch(key);
      break;
    
    
      // FAN 1
      case 'A':
      Serial.println("FAN 1 UP");
      break;
    
    
      case 'B':
      Serial.println("FAN 1 DOWN");
      break;
    
    
    
    
      // FAN 2
      case 'C':
      Serial.println("FAN 2 UP");
      break;
    
    
      case 'D':
      Serial.println("FAN 2 DOWN");
      break;
    
    
    
    
      // MASTER CONTROLLS
      case 'E':
      Serial.println("ALL ON");
      break;
    
    
      case 'F':
      Serial.println("ALL OFF");
      break;
    
    
    
    
      default:
      Serial.print("UNMAPPED: ");
      Serial.println(key);
      break;
      }
      break;
    
    
      case HOLD:
      keyPressed = true;
      pressedKey = key;
      break;
    
    
      case IDLE:
      break;
      }
    }
    
    
    
    
    void toggleSwitch( char num ) {
      Serial.println(num);
    }

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Robert Peter Oakes
    0 Robert Peter Oakes over 11 years ago in reply to Former Member

    I am not sure where your using the keypadDelayCounter for, i see not use for it

     

    also the old code is still in the released case statement so i can only assume this is not your current code

     

    Regards

     

    Peter, oh, If anyone provides the correct answer to a question, please check, click the "Correct Answer" flag so they will get credit for it

     

    thanks

     

    Peter

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to Robert Peter Oakes

    Well Peter on line 100 i have a condition based on "keypadDelayCounter".

     

    I want to keep my keypads in Released case because i want the action to trigger on "Release" state of the button. So that is my most recent code and its actually working the way i want it.

     

    I only have problems regarding delays and commands i write after the keypad logic in my main loop. That upsets my keypadDelayCounter value that i set.

     

    If i switch my OSC from 16 to 40 Mhz wont it increase the speed of the Arduino board and process faster?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Robert Peter Oakes
    0 Robert Peter Oakes over 11 years ago in reply to Former Member

    The MAX speed of an uno (ATMEGA328 is 16Mhz, possibly 20 depending on the chip)

     

    this is way more than enough speed for what your trying to do, the answer lies in how you code it

     

    forgetting about the code for a moment, can you describe in English what your trying to do, perhaps with a diagram or picture ?, im sure I can help you resolve you problem , I just need to better understand what it is your trying to do

     

    Thanks

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to Robert Peter Oakes

    What i am trying to do is turn on/off 8 lights and 2 fans using a microcontroller.

     

    8 lights are just toggles (on/off) where as the fans are level based dimmers ( 0%, 25%, 50%, 75% 100%).

     

    So one fan will have two buttons (One to increase speed, one to decrease speed).

     

    8 + (2 x 2) = 12 buttons.

     

    I am using a keypad 4 x 4 = 16 buttons with my microcontroller.

     

    For the lights i want them to change state when the button is RELEASED from the keypad. For the fans, i want to allow user to be able to hold the button to increase the speed ( if up button is pressed ) and down ( if down button is pressed ).

     

    I am able to do it currently with my code. However when i add code after my keypad hold button logic in main loop, the delay value i want to set varies according to the code i add after the keypad logic. That is because the main loop slows down when more and more code is added.

     

    I hope i am able to give you a better understanding of what i am trying to achieve.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Robert Peter Oakes
    0 Robert Peter Oakes over 11 years ago in reply to Former Member

    so the delay code needs to be different

     

    use something like this (Not full code but an idea)

     

    const long waitDelay = 300; // 300ms

    unsigned long waitTime = 0; // place holder for delay

    setup()

    {

    ...

    waitTime = millis() + waitDelay ;

    } // end of setup

     

    loop()

    {

     

    ... other stuff

     

    if (waitTime < millis()) // timed out so go into the if statement

    {

    // time expired so do what else you wanted when the delay normally expired like incrementing you fan speed if the button is still pressed

    waitTime = millis() + waitDelay ; // reset for the next loop

    }

    // now do other things that are not based on the loop, with this you will not be slowed down by the old DELAY(nnn) function

    // don't used delay function if you don't want to be slowed down, use the above example to have things trigger at a specified interval instead

    // Delay() stops ALL processing while it times out.

     

    } // end of loop()

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to Robert Peter Oakes

    Peter you are a genius image!

     

    Thanks, this makes much more sense.

     

    So as long as i don't use delays in my code, i am pretty much coding non-blocking right?

     

    Its a little early to ask but will LCD, IR, Serial Communication and Temperature interfacing block me in anyway? (because IR and LCD use serial data in/out)

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Robert Peter Oakes
    0 Robert Peter Oakes over 11 years ago in reply to Former Member

    Your absolutely correct

     

    and with care you should be ok with all the items your listing above, in fact I have done that exact thing in previous projects

     

    Good luck

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube