CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

Can i modify keypad library kbd.c to work with 1x4 keypad
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sareehy



Joined: 03 May 2016
Posts: 16

View user's profile Send private message

Can i modify keypad library kbd.c to work with 1x4 keypad
PostPosted: Fri Aug 11, 2017 12:49 am     Reply with quote

Hi all,

I want to use the following keypad





So can i modify keypad library kbd.c to work with it?
If yes, what should i modify?

Does the keypad library solve the bouncing problem of the button ?

regards Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 20060

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 2:54 am     Reply with quote

It would take too long to explain the modifications so I'll just post it.

Attach the keypad to PortB, pins RB0 to RB3. Connect the common pin
on the keypad to ground.

Test program:
Code:

#include <18F46K22.h>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

#define use_portb_kbd
#include "kbd_1row.c"

//======================================
void main()
{
int8 k;

printf("Ready\n\r");

kbd_init();

while(TRUE)
  {
   k=kbd_getc();
   if(k!=0)
     {
      putc(k);
     }
  }

}


kbd_1row.c driver file:
Code:

#if defined use_portb_kbd
   #byte kbd = getenv("SFR:PORTB")
#else
   #byte kbd = getenv("SFR:PORTD")
#endif

#define ROW0 (1 << 0)   // Pin B0
#define ROW1 (1 << 1)   // Pin B1
#define ROW2 (1 << 2)   // Pin B2
#define ROW3 (1 << 3)   // pin B3

#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS)

// Keypad layout:
char const KEYS[4] = {'1','2','3','4'};


void kbd_init()
{
port_b_pullups(0x0F); 
}


char kbd_getc(void)
{
static int1 kbd_down = FALSE;
static char last_key = '\0';
BYTE kchar;
BYTE row;

kchar='\0';

kbd = input_b();

if(kbd_down)
  {
   if((kbd & (ALL_ROWS))==(ALL_ROWS))
     {
      kbd_down=FALSE;
      kchar=last_key;
      last_key='\0';
     }
  }
else
  {
   if((kbd & (ALL_ROWS)) != (ALL_ROWS))
     {
      if((kbd & ROW0)==0)
         row=0;
      else if((kbd & ROW1)==0)
         row=1;
      else if((kbd & ROW2)==0)
         row=2;
      else if((kbd & ROW3)==0)
         row=3;
      last_key =KEYS[row];
      kbd_down = TRUE;
     }
  }

delay_ms(10);  // Debounce delay

return(kchar);
}
temtronic



Joined: 01 Jul 2010
Posts: 5660
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 5:19 am     Reply with quote

One thing you have to remember is to call the kbd function often .
Unlike an interrupt driven keyboard routine, this one is 'polled' so that whatever you do in main() has to call it often otherwise the program won't see a key pressed when you press it.

I'm pretty sure someone's posted an ISR based version of this in the code library and 'one day' I have to try it as it would be the best way to access a keypad.

Jay
newguy



Joined: 24 Jun 2004
Posts: 1437
Location: Edmonton, Alberta

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 7:36 am     Reply with quote

I posted it a very long time ago. I'm going to apologize in advance as it's ugly compared to what I churn out now.

That said, I poll keys in my projects now; it's just simpler/easier most of the time...that I find, anyway.
sareehy



Joined: 03 May 2016
Posts: 16

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 11:08 pm     Reply with quote

Thanks a lot PCM for your appreciated effort Smile

Is it necessary to hardware debounce the buttons ?
sareehy



Joined: 03 May 2016
Posts: 16

View user's profile Send private message

PostPosted: Fri Aug 11, 2017 11:10 pm     Reply with quote

temtronic wrote:
One thing you have to remember is to call the kbd function often .
Unlike an interrupt driven keyboard routine, this one is 'polled' so that whatever you do in main() has to call it often otherwise the program won't see a key pressed when you press it.

I'm pretty sure someone's posted an ISR based version of this in the code library and 'one day' I have to try it as it would be the best way to access a keypad.

Jay


your idea isn't clear ^_^
could you explain more ?

Regards Smile
temtronic



Joined: 01 Jul 2010
Posts: 5660
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 5:08 am     Reply with quote

re; hardware debounce
With all mechanical switches there is a LOT of 'debounce', just look with an oscilloscope. I use a .68 mfd cap in parallel with all the pushbuttons in my products. You can use less, say .1 , .01 and it's loosely based on the pullup resistor and the required response time. What you need to see is a single, clean transistion from '1' to '0' to '1'. Three decades ago, when I was designing for the alarm industry, 1/4 second was the 'standard' debounce time.Might explain wHY I still have 2 reels of .68 mfd caps here!
If the simple cap isn't good enough, you can add a 'Schmitt' level buffer. These have a predefined 'hystersis' to give a proper signal. Some of the PIC pins actually have this technology, it's in the datasheet, 'somewhere' in the 400-500-600 pages....so it pays to read.
Software debounce is the deisners last chance to 'see' a perfect signal. Many methods can be used , which one you choose will be based on available program memory, ram, peripherals and speed.

re: ISR based KPD driver. For the fastest response,generally speaking, an ISR(Interrupt Service Routine) is the way to run a PIC( or ANY computer). In a 'polled' program main() is in a continuous loop of
top:
do stuff,
do more stuff,
check kpd,
do even more stuff,
loop to top.

The problem is depending on what 'stuff' is and how many 'things' you do, the PIC may NOT see the keypad being pressed as it wasn't checking WHEN the key was pressed. For small programs this doesn't happen but add a lot of math or printing and you may never see the kpd being pressed.

An ISR based routine will see the key pressed and inform or 'flag' the PIC that a key was pressed. This happens 'in the background', so the PIC cn be doing other things. Seems it was Newguy who posted an ISR based version of the kpd routine in the 'code library'. It'd be worthwhile to see what he did.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 12396

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 8:28 am     Reply with quote

The downside of using the interrupt from a keyboard, is that unless it is hardware de-bounced, you can end up with dozens or even hundreds of triggers from a single press and the processor becoming deadlocked by the interrupt.
So the other way to deal with the keyboard is scan on a 'tick'. If (for instance) you have a 100Hz tick routine, then this can simply check the keyboard. De-bounce can then be done as requiring the key to be in the same state for (perhaps) 3 successive interrupts before accepting it. Since this is being done at regular intervals, there are no extra calls if the key bounces more. This is actually how the original IBM keyboard for the PC is coded.
newguy



Joined: 24 Jun 2004
Posts: 1437
Location: Edmonton, Alberta

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 8:46 am     Reply with quote

Ttelmah wrote:
The downside of using the interrupt from a keyboard, is that unless it is hardware de-bounced, you can end up with dozens or even hundreds of triggers from a single press and the processor becoming deadlocked by the interrupt.
So the other way to deal with the keyboard is scan on a 'tick'. If (for instance) you have a 100Hz tick routine, then this can simply check the keyboard. De-bounce can then be done as requiring the key to be in the same state for (perhaps) 3 successive interrupts before accepting it. Since this is being done at regular intervals, there are no extra calls if the key bounces more. This is actually how the original IBM keyboard for the PC is coded.


That's more-or-less how I do it now. A change in button state isn't counted as a valid change unless the button is in the same state after the debounce count period has elapsed. The debounce period is ~50ms (minimum) - ~80ms (sometimes more), depending on the switch itself. I scan the button(s) inside a routine that runs every 10ms, based on a timer interrupt.
Ttelmah



Joined: 11 Mar 2010
Posts: 12396

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 8:50 am     Reply with quote

Smile

Also you can very easily do key repeat if you want with this.
newguy



Joined: 24 Jun 2004
Posts: 1437
Location: Edmonton, Alberta

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 9:28 am     Reply with quote

Absolutely. Press and hold and after 1 second, "go baby go!" Laughing
PCM programmer



Joined: 06 Sep 2003
Posts: 20060

View user's profile Send private message

PostPosted: Sat Aug 12, 2017 6:37 pm     Reply with quote

sareehy wrote:
Thanks a lot PCM for your appreciated effort Smile

Is it necessary to hardware debounce the buttons ?

No. The posted code has software debouncing. Look at the line
that has a 10 ms delay. That's the software debouncing.

temtronic wrote:

One thing you have to remember is to call the kbd function often.
Unlike an interrupt driven keyboard routine, this one is 'polled' so that
whatever you do in main() has to call it often otherwise the program won't
see a key pressed when you press it.
sareehy wrote:

Your idea isn't clear.
Could you explain more ?

Look at the test program I posted. It has a while(TRUE) loop that
continuously calls kbd_getc(). That's a polling loop.
sareehy



Joined: 03 May 2016
Posts: 16

View user's profile Send private message

PostPosted: Sun Aug 13, 2017 4:12 am     Reply with quote

Thank you all for your appreciated effort ^^


Quote:

No. The posted code has software debouncing. Look at the line
that has a 10 ms delay. That's the software debouncing.




.


Is the 10 ms enough ?


Does the following line affect on the output connected to rb4-rb7 pins ?
Code:
kbd=input_b();



I have mc14490 ic, do you advise me to use it Smile
This is the first time I want to build a circuit to use it as product in my home so I'm afraid from any problems I can solve it before completing the circuit.

Regards Rolling Eyes
temtronic



Joined: 01 Jul 2010
Posts: 5660
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Aug 13, 2017 6:55 am     Reply with quote

You really need to buy or borrow an oscilloscope for electronics. Even a 20MHZ, dual trace analog scope will be fine. Mine's 30 years old and does great service. having the ability to SEE the signals is very important.

As for timing, yes 10ms should be more than enough. With a scope you would see the 'bounce' (multiple on/off or high/low) that a mechanical switch makes. What 'debouncing' does is eliminate those multiple signals and gives one good one. If there is 5ms of 'bounce' then 10ms of debounce (either passive(cap), active(chip) or software) will be OK.

The 14490 has some 'quirks', like an internal pullup on the input, so you'll have to experiment with it, part of the fun of 'bench testing' and learning.

The flex-kpd code does work fine 'as-is', using 10k pullups with a 5V PIC.

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 20060

View user's profile Send private message

PostPosted: Sun Aug 13, 2017 9:10 am     Reply with quote

sareehy wrote:

Is the 10 ms enough ?

I have a membrane 4-position keypad that overall, works similarly to
your keypad. It worked fine with 10 ms. I tested it in hardware.

sareehy wrote:

Does the following line affect on the output connected to rb4-rb7 pins ?
kbd=input_b();

Yes. The program I posted uses the default i/o mode of the compiler,
which is called "standard i/o" mode. (See the CCS manual.)
In this mode, the input_b() function will make all pins on PortB into
input pins. If you're interested, the following threads have a discussion
of standard i/o and fast i/o modes:

Masking portb:
http://www.ccsinfo.com/forum/viewtopic.php?t=28653

Port input without changing port direction:
http://www.ccsinfo.com/forum/viewtopic.php?t=31858
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group