a simple 32 character text writer with 4 keys, detect still pressed ?

Ok I have 6 keys, but I am only using 4 for entering the text.

(This is a combined keypad and LCD query so its in this subject )

I needed to be able to enter two 8 char team names on a scoreboard project via a small remote control unit. ( I want to use this commercially so didnt use the multitap library )

I am happy to say I have the sketch working so far without any help , ( any suggestions welcomed ) and a lo-tech proto running :-

The cursor starts top left as normal, and the up and down buttons sequence through the alphabet and numbers for that block.

The cursor stays where it is until you have chosen that character, and you then press left or right to move the cursor to the next block where you want to change the character.

You can go left or right, and it wraps round when it reaches block 0 or 32 .

( The display I am using is a Topway LMB162A and the scroll and auttoscroll functions of the LiquidCrystal.h library do not seem to work - I dont need them , I'm just pointing out my display might be different in other ways. )

The CL key works fine, resets all to blank, and returns cursor to 0,0 .

The S key will later send the data from each block via the RFM12B wireless module ( top left ) The big 4700Mfd cap above the keypad is to supply current from the 3v3 supply when the Tx draws a surge.

What I need now, is for a key to be held, and the character sequence fast forward ( like setting an alarm clock ) to save hitting the key many times to get to the number required.
I have done this before by letting the loop run through again and again while the key is pressed, but I can't find that sketch now.

Of course the if(key) function will only see a change in key and ignore the same one.

I tried including KeyState getState() but it says its not declared in this scope but it looks like a function of Keypad.h ?

Is there another option to if (key) that will not cause debounce hassles ?

#include <Keypad.h>  
#include <LiquidCrystal.h> // we need this library for the LCD commands
#include <avr/sleep.h>      // powerdown library
#include <avr/interrupt.h>  // interrupts library
char key;
int botRow;
int button;  // integer of button ascii number
int blinkLoop; // loopcount for the cursor blinking
char chars [] = {
  '_','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I',
  'J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','-','.','?' };
char blockChar [32];  //  the actual character for each block to display and send  
int q [32 ];
///////////////////////////////////////  keypad settings ////////////////////
const byte ROWS = 2; // two rows
const byte COLS = 3; // three columns
char keys[ROWS][COLS] =   {       
  {
    'C','U','L'         } 
  ,  // row 1  //   CLEAR, UP, LEFT
  { 
    'S','R','D'        }  
  ,  // row 2    //  SEND , RIGHT ,  DOWN
};
byte rowPins[ROWS] = { 
  19, 18  }; 
byte colPins[COLS] = { 
  15,16,17}; // Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
////////////////////////////////////////////////////////////////////////////////
LiquidCrystal lcd(4,5,6,7,8,9); // define our LCD and which pins to user 
int block  ; //  0 - 31 character position numbers  0 - 15 top row, 16 - 32

void setup()

{
  Serial.begin(9600);
  lcd.begin(16, 2); // need to specify how many columns and rows are in the LCD unit
  //lcd.clear();      // this clears the LCD. You can use this at any time
  Serial.println(" setup");     
  for ( int x = 0; x <=31; x++ ) { //   clears all the blocks to underscore which will show as blank on board  
    blockChar [x] = 0 ;   
  }
  lcd.display(); //enable lcd display
  blinkLoop = 0;
  resethome ();  //  clears display and zeros cursor
  block = 0;  //  start at block 0 top left 
  for ( int x = 0; x <=31; x++ ) { //  clear all values for all blocks
    q [x] = 0 ;  
  }
}  
void loop()   
{
  blinkLoop++; //   blink cursor so shows difference between E and F for example
  if (blinkLoop > 500) {
    lcd.cursor() ;
  } 
  else { 
    lcd.noCursor() ; 
  } 
  if (blinkLoop > 1000) {
    blinkLoop = 0;
  }
  char key = keypad.getKey();                 // reading the keypad
  if(key)  {          // same as if(key != NO_KEY)- did something change?        
    Serial.print("key read =");   
    Serial.println(key);
    button = key; // integer version of ascii 
    checkbutton ();  // actions for each key  
  }
}



void checkbutton () {

  Serial.print("key pressed =  "); 
  Serial.println(button);
  if ( button == 67 ) {    //  key = C or ascii 67  Clear
    Serial.print("key ch =  "); 
    Serial.println(key);
    resethome () ;
    Serial.println("key check = cancel  C  ");   
  }
  //*****************************************************************************  
  if ( button == 83 ) {//  key = S or ascii  83  Send
    Serial.print("key check =send S ");   //  still got to write this bit
  }    
  //******************************************************************************
  if ( button == 76 ) {   //  key = L or ascii  85  LEFT
    Serial.print("key check =   L  cursor left ");  
    block = block--;
    if ( block < 0 ) { 
      block = 31 ;
    }
    Serial.print("block ");
    Serial.print(block);
    if ( block >15 ) {  
      botRow = block - 16 ;
      lcd.setCursor(botRow,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }
  //*****************************************************************************    
  if ( button == 82 ) {   //  key = R or ascii 82
    Serial.print("key check = R   cursor right  "); 
    block = block++;
    if ( block > 31 ) { 
      block = 0 ;
    }
    Serial.print("block ");
    Serial.print(block);
    if ( block >15 ) {  
      botRow = block - 16 ;
      lcd.setCursor(botRow,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }

  ///***********************************************************************  
  if ( button == 85 ) {   //  key = U or ascii 85
    Serial.print("key check = U   char up one  ");   
    q [block] ++;    
    if ( q[block] >39 ) { 
      q[block]=0 ; 
    }
    Serial.print("q = "); 
    Serial.println(q[block]);     
    blockChar [block] = chars [ q[block] ];    
    Serial.print("q ");
    Serial.print(block);
    Serial.print("=  ") ;
    Serial.println(q[block]); 
    lcd.print(blockChar [block]);  

    if ( block >15 ) {  
      botRow = block - 16 ;
      lcd.setCursor(botRow,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }
  //*************************************************************************  
  if ( button == 68 ) {   //  key = D or ascii 68
    Serial.print("key check = D   char down one  ");  

    q [block] --;    
    if ( q[block] <0 ) { 
      q[block]=39 ; 
    }
    Serial.print("q = "); 
    Serial.println(q[block]);     
    blockChar [block] = chars [ q[block] ];    
    Serial.print("q ");
    Serial.print(block);
    Serial.print("=  ") ;
    Serial.println(q[block]); 

    lcd.print(blockChar [block]);    
    if ( block >15 ) {  
      botRow = block - 16 ;
      lcd.setCursor(botRow,1); 
    }
    else {   
      lcd.setCursor(block,0);
    }
  }
}

void resethome () {

  lcd.clear();  
  lcd.display(); 

  lcd.setCursor(0,0); 
  // lcd.print("per=");  for later showing period minutes
  // lcd.print(chars [3]);
  //  lcd.print(chars [1]);
  block = 0;
}

Hi Boffin1,

Boffin1:
I tried including KeyState getState() but it says its not declared in this scope but it looks like a function of Keypad.h ?

Is there another option to if (key) that will not cause debounce hassles ?

You were correct in assuming that getState() is what you would use to solve your problem. It returns one of four states IDLE, PRESSED, HOLD, or RELEASED which you can test, eg.

  if ( kpd.getState() == HOLD ) {
      // reset your repeat timer
  }

I don't understand why you are getting a scope problem, though. The function is public and you should be able to use it. Can you show me an example of what you wrote when it gave you the compile error?

Thanks Mstanley;

I added this to test what you suggested :-

char key = keypad.getKey();                 // reading the keypad
  if(key)  {          // same as if(key != NO_KEY)- did something change?        
 
       Serial.print("key read =");   
    Serial.println(key);
    button = key; // integer version of ascii 
    checkbutton ();  // actions for each key  
  }


  
    if ( kpd.getState() == HOLD ) {
      // reset your repeat timer
       Serial.print("key held =");   
  //  Serial.println(key);
  //  button = key; // integer version of ascii 
  //  checkbutton ();  // actions for each key 
      
  }

the rest of the code is the same . and it gives me :-

sundaylater.cpp: In function 'void loop()':
sundaylater:75: error: 'kpd' was not declared in this scope

( I am using v22 )

OK Sorted I changed the if ( kpd.getState() == HOLD ) { to if ( keypad.getState() == HOLD )

thanks Mark it now zaps through great with :-

 if ( keypad.getState() == HOLD )
    {
       Serial.print("key held =");   
       Serial.println(key);  
         if (( millis() - 200) > previousMillis ) 
         {
           previousMillis = millis();    
           checkbutton ();  // actions for each key 
         }
    }

( Sorry , I have left my quirky indents - Nature never meant me to be tidy - or thin or musical :stuck_out_tongue: )

This is great news and I'm really surprised that it works with v22 of the Arduino software. I attempted to maintain backward compatibility but in truth I never tested the library on anything older than Arduino 1.0.

Thanks for the info. It gives me greater confidence. :wink:

Thats odd, I have been using keyboard.h for a couple of years now?

I am a bit of an ostrich with my head in the sand about switching to v1.0, actually I just havnt had any time to get round to it, but I might get a chance in Jan when I catch up on work ( it might be v 1.2 by then )

The only odd thing with the sketch now is that I can hold down the character up and down buttons and it fast forwards through fine, but left and right sometimes the flashing cursor dissapears, I think I must change the speed of the cursor flashing, its probably beating with the fast forward speed of the button hold.

Thanks for the library