|
|
View previous topic :: View next topic |
Author |
Message |
deltatech
Joined: 22 Apr 2006 Posts: 87
|
Cant get the Keypad code to work ! |
Posted: Sat May 06, 2006 11:39 am |
|
|
Hi Can any one tell me why i am geting non stop garbage on the serial monitor with this code . I am new to CCS and would appriciate any help .
I am trying to connect a 4x3 kaypad to PICDEM Mechatronics Board with a 16F917 on the J10 PINS PORTB
Code: | #include "G:\Program Files\PICC\Project\keypad2.h"
//This is a modification of CCS keypad driver (KBDD.c) with flexible pins connections.
//Code:
///////////////////////////////////////////////////////////////////////////
//// Flex_KBD.C ////
//// Generic keypad scan driver ////
//// ////
//// ////
//// c = kbd_getc(c) Will return a key value if pressed or /0 if not ////
//// This function should be called frequently so as ////
//// not to miss a key press. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//Keypad connection:
#define col0 PIN_B5
#define col1 PIN_B6
#define col2 PIN_B7
#define row0 PIN_B1
#define row1 PIN_B2
#define row2 PIN_B3
#define row3 PIN_B4
char kbd_getc( );
short int ALL_ROWS (void);
// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
#define KBD_DEBOUNCE_FACTOR 2//33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void main()
{char key;
// port_b_pullups(TRUE);
while(1)
{
//printf("KAISER");
key=kbd_getc();
printf(key);
}
}
char kbd_getc( ) {
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
switch (col) {
case 0 : output_low(col0);
output_high(col1);
output_high(col2);
break;
case 1 : output_high(col0);
output_low(col1);
output_high(col2);
break;
case 2 : output_high(col0);
output_high(col1);
output_low(col2);
break;
}
if(kbd_down) {
if(!ALL_ROWS()) {
kbd_down=false;
kchar=last_key;
last_key='\0';
}
} else {
if(ALL_ROWS()) {
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
} else {
++col;
if(col==3)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
short int ALL_ROWS (void)
{
if (input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
| |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 06, 2006 1:21 pm |
|
|
You shouldn't start a new thread every time you have a new question
on your keypad program. If you just add another post to your existing
thread, it will get "bumped" to the top of the list.
But anyway, here are some problems I see:
1. You need pull-ups on the Row pins. You have commented out
the line that enables them. You need to uncomment it.
2. In your while() loop, your method of using the keypad driver is
incorrect. You need to check if the returned value ('key') is
non-zero.
The value returned by kbd_getc() is valid only if it's non-zero.
See the CCS example file, EX_LCDKB.C which shows how to do this.
3. You're using printf() incorrectly. Printf needs to know how to
interpret the value that you've given it. If you want to display
a character, then give it the format specifier for a character.
Example:
printf("%c", key); |
|
|
deltatech
Joined: 22 Apr 2006 Posts: 87
|
Cant get the Keypad code to work ! |
Posted: Sat May 06, 2006 3:48 pm |
|
|
[color=blue][b]Thanks PCW Programmer you are great help . I changed the code to you sugection and it is almost working . What is happening now is that I smetime get the correct number but most of the time i am getting 1s and 6s continuesly even though i press the key one . i have tried different values in the deboince but to no avail . By they how do you work out the correct value for the debonce . how did you get the value 33 ?
Code: | #include "G:\Program Files\PICC\Project\keypad2.h"[/b][/color]
//This is a modification of CCS keypad driver (KBDD.c) with flexible pins connections.
//Code:
///////////////////////////////////////////////////////////////////////////
//// Flex_KBD.C ////
//// Generic keypad scan driver ////
//// ////
//// ////
//// c = kbd_getc(c) Will return a key value if pressed or /0 if not ////
//// This function should be called frequently so as ////
//// not to miss a key press. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//Keypad connection:
#define col0 PIN_B5
#define col1 PIN_B6
#define col2 PIN_B7
#define row0 PIN_B1
#define row1 PIN_B2
#define row2 PIN_B3
#define row3 PIN_B4
char kbd_getc( );
short int ALL_ROWS (void);
// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
#define KBD_DEBOUNCE_FACTOR 0//100 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void main()
{
char key;
port_b_pullups(TRUE);
while(1)
{
char i;
key=kbd_getc();
if(key!=0)
printf("%c",key);
}
}
char kbd_getc( ) {
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
switch (col) {
case 0 : output_low(col0);
output_high(col1);
output_high(col2);
break;
case 1 : output_high(col0);
output_low(col1);
output_high(col2);
break;
case 2 : output_high(col0);
output_high(col1);
output_low(col2);
break;
}
if(kbd_down) {
if(!ALL_ROWS()) {
kbd_down=false;
kchar=last_key;
last_key='\0';
}
} else {
if(ALL_ROWS()) {
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
} else {
++col;
if(col==3)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
short int ALL_ROWS (void)
{
if (input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 06, 2006 11:55 pm |
|
|
Do you have your programmer plugged into the board while you're
running the program ? If so, unplug it. If that doesn't fix it, then
check the wiring between your keypad the PIC.
Don't set the debounce value to 0. It's got to be set to some non-zero
value. The debounce value just controls the number of times per
second that the keypad is polled for a keypress. My board is running
at 4 MHz and the CCS value of 33 seems to work OK. |
|
|
PICdawg
Joined: 13 Dec 2007 Posts: 17
|
|
Posted: Fri Jul 18, 2014 5:30 pm |
|
|
Old post but I have a couple questions about the flex_kbd, and kbd.c drivers w.r.t. kbd_debounce_factor. I am implementing a keypad in a design for the first time. I've written a test program and it works utilizing PCM's password entry program(s). Thanks PCM. The code lives! However, I am trying to understand the kbd_debounce_factor which appears in the drivers and its associated comment....
The comment in all the drivers says 'Set this number to apx n/333 where n is the number of times per second....' This confuses me. I'm assuming 'apx' is short for 'approximately'. The driver defines this value as '33'. This is the value many on this forum use. If it's 33, then 'n' would be 333 X 33 = 10989. I'm doubting that anyone is calling their keypad routine every 91 microseconds (1/10989). Typically it's called every 10ms. kbd_call_count increments once per call (or poll)
I set my interrupt for every 10ms. That's 100hz. If I follow the comment, I should use a value of 100/333 which is less than 1. This makes no sense to me.
I believe PCM is slightly incorrect in his last post to this old thread. (PCM, don't flame me too bad if I'm completely off the mark...I'm an old guy!!!) kbd_debounce_factor does not control the number of times polled PER SECOND, just the number of times polled right? If you have a 10ms interrupt time, and kbd_debounce_factor of 33, you must hold the key for 33 polls which is 330ms per keypress. Am I missing something?
My experience as a hardware engineer has shown keybounce lasts significantly less than 330ms so the 33 number seems excessive. I'm using 3 right now and my test environment is working fine. I have regularly measured switch bounce on a scope in the neighborhood of 5ms-30ms.
So in summary, my two issues are 1) the comment verbiage in the drivers that doesn't make sense to me, and 2) the actual value and the reasoning behind the particular value chosen.
Please be kind if I've absolutely missed the most obvious thing any noob would catch..
FWIW I'm running a 16F876A at 20 Mhz. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 18, 2014 8:44 pm |
|
|
The CCS driver file kbd.c, and its associated example file ex_lcdkb.c
do not use interrupts. The keypad is polled in a loop. I setup a test
program which consists largely of ex_lcdkb.c, except without the lcd.
Inside kbd.c, right after the test where it decides to poll the keypad,
I placed a marker pulse for my scope.
Code: |
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
output_high(PIN_D7); // *** MARKER PULSE ***
delay_us(1);
output_low(PIN_D7);
|
Then I ran the program on a PicDem2-Plus (old type) with a 16F877A
with a 20 MHz crystal. The pulses occur at roughly every 190 usec.
This is about 5.2 KHz. If I was using a 4 MHz crystal, they would occur at
about every 950 usec, which is a rate of about 1 KHz. This measurement
was done with PortB pullups enabled, and with no keys pressed.
The CCS kbd.c does not use interrupts. There is no timer interrupt running
every 10ms. It's polled in a code loop, at the rates given above. |
|
|
PICdawg
Joined: 13 Dec 2007 Posts: 17
|
|
Posted: Sat Jul 19, 2014 10:29 am |
|
|
Thanks for your quick response PCM! I understand your comments and example completely. Makes sense when the driver is not used in an interrupt driven fashion. I hadn't looked at EX_LCDKB.C until you pointed it out!
The test programs I implemented were from your post to KONAMI (Keypad problem) back in 2011. Is it fair to say that in that example which utilizes the interrupt scheme in kbd_buffer.c that a key must be held for approx. 330ms, given the 10ms interrupt and the debounce factor of 33 or am I just way out in left field? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 19, 2014 11:26 am |
|
|
I looked at the files on my PC, which were still there from 2011. The
flex_kbd.c file had been edited as follows:
Code: | //#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
#define KBD_DEBOUNCE_FACTOR 0
|
In other words, the software-loop debounce has been disabled. It's
done at a 10ms rate by the #int_rtcc (same as #int_timer0) interrupt.
So it's not 330ms, it's 10 ms.
When you brought up the 330ms, I figured that something was wrong
with that, because there's no way that a 330ms sampling rate would
be snappy enough in terms of keypad response time. And that's how
it was. The debounce factor was set to 0, leaving debounce to be done
by the timer interrupt. |
|
|
PICdawg
Joined: 13 Dec 2007 Posts: 17
|
|
Posted: Sat Jul 19, 2014 12:23 pm |
|
|
Thanks PCM! We are now perfectly in sync. I've included additional comments to remind me about the debounce factor and using it in an interrupt vs polled environment. Your Password example is running and I can move to the next step of my code development. |
|
|
|
|
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
|