View previous topic :: View next topic |
Author |
Message |
falcon1877
Joined: 30 Sep 2012 Posts: 24
|
Reduce noise of button |
Posted: Wed Oct 10, 2012 2:45 am |
|
|
Hello, I'm doing my project with button, I'm using int_rb(r4-r7) so I want to know how to reduce noise and how to detect hold key action . |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19505
|
|
Posted: Wed Oct 10, 2012 4:19 am |
|
|
Don't use the RB interrupts.
This has been covered before. They are not really suitable for this type of application.
1) Buttons are noisy.
2) The interrupts detect changes only, so are not suitable for detecting hold.
3) Because of the above it is very difficult indeed to reliably detect the required states: make, break, repeat
The normal good way of doing this, is to use a timer interrupt.
This is how the keyboard is handled in things like the PC keyboard.
Seriously, use the right tool for the job. Trying to do this with INT_RB, is making the task almost impossible, and vastly more work.
It's a bit like trying to use a hammer to drive a screw.
Best Wishes |
|
|
falcon1877
Joined: 30 Sep 2012 Posts: 24
|
|
Posted: Wed Oct 10, 2012 4:42 am |
|
|
OK, I understand what you are saying and .....if I use timer, what is the best way to check for hold key action ? Can you give a sample code |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19505
|
|
Posted: Wed Oct 10, 2012 5:07 am |
|
|
Difficult to be generic, without knowing your hardware details, with solutions changing if this is a key matrix, but something like (this for
four buttons on the upper four bits of portB - assuming interrupt every 1/100th second):
Code: |
int8 kchr;
#INT_TIMERx //Choose to suit your hardware
void tick(void) {
static int8 kseen[4];
static int8 klast=0;
int8 know, bit;
know=input_b(); //read port
swap(know); //move MSnibble to low nibble
know=(~know)&15; //mask low four bits, and invert bits - assuming
//low = key made
for (bit=0;bit<4;bit++) {
/* I check each bit in the input in turn */
if (bit_test(know,bit)) {
/* here this bit is set, and I have to check if it has allready been seen. */
if (bit_test(klast,bit)) {
/* Here the bit has allready been seen, and I respond if the counter
reaches zero (4/100th sec first response, 30/100th sec repeat). */
if (--kseen[bit]==0) {
bit_set(kchr,bit);
/* This sets the 'repeat' interval */
kseen[bit]=30;
}
}
else {
/* here it is a 'first' response */
bit_set(klast,bit);
/* set to respond on the next loop - increasing this will slow
keyboard debounce */
kseen[bit]=4;
}
}
else {
/* here this key is not pressed */
bit_clear(klast,bit);
}
}
}
|
kchr, will have the bit set corresponding to any key that is pressed. In your 'main' code, do what you want when this happens, and then clear the bit. If the key is held after 30/100th second, it'll be seen again. Key has to be 'down' for 4/100th second before it'll be seen.
The counter in kseen control how long the debounce is, and how fast the repeat.
Best Wishes |
|
|
falcon1877
Joined: 30 Sep 2012 Posts: 24
|
|
Posted: Wed Oct 10, 2012 6:08 am |
|
|
@Ttelmah : thanks for your help, I will test it immediately. |
|
|
falcon1877
Joined: 30 Sep 2012 Posts: 24
|
|
Posted: Wed Oct 10, 2012 8:26 pm |
|
|
@Ttelmah: Many thanks for you. Now my program works correctly. But I have a question. When do we need to use interrupt rb instead of timer ?? Can you give me some example |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19505
|
|
Posted: Thu Oct 11, 2012 3:09 am |
|
|
Classic use of INT_RB, would be something like an optical quadrature encoder. Here you have a signal source, that is warranted to give no bounce, two signals from the encoder, where you need to detect every edge (rising and falling on each signal), and respond fast (if you have -say- a 400line encoder on a shaft turning at 1000RPM, you have 26000 edges per second......).
Best Wishes |
|
|
|