View previous topic :: View next topic |
Author |
Message |
sareehy
Joined: 03 May 2016 Posts: 20
|
Can i modify keypad library kbd.c to work with 1x4 keypad |
Posted: Fri Aug 11, 2017 12:49 am |
|
|
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 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 11, 2017 2:54 am |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Fri Aug 11, 2017 5:19 am |
|
|
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: 1909
|
|
Posted: Fri Aug 11, 2017 7:36 am |
|
|
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: 20
|
|
Posted: Fri Aug 11, 2017 11:08 pm |
|
|
Thanks a lot PCM for your appreciated effort
Is it necessary to hardware debounce the buttons ? |
|
|
sareehy
Joined: 03 May 2016 Posts: 20
|
|
Posted: Fri Aug 11, 2017 11:10 pm |
|
|
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 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Sat Aug 12, 2017 5:08 am |
|
|
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: 19537
|
|
Posted: Sat Aug 12, 2017 8:28 am |
|
|
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: 1909
|
|
Posted: Sat Aug 12, 2017 8:46 am |
|
|
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: 19537
|
|
Posted: Sat Aug 12, 2017 8:50 am |
|
|
Also you can very easily do key repeat if you want with this. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Sat Aug 12, 2017 9:28 am |
|
|
Absolutely. Press and hold and after 1 second, "go baby go!" |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Aug 12, 2017 6:37 pm |
|
|
sareehy wrote: | Thanks a lot PCM for your appreciated effort
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: 20
|
|
Posted: Sun Aug 13, 2017 4:12 am |
|
|
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 ?
I have mc14490 ic, do you advise me to use it
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 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Sun Aug 13, 2017 6:55 am |
|
|
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: 21708
|
|
Posted: Sun Aug 13, 2017 9:10 am |
|
|
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 |
|
|
|