|
|
View previous topic :: View next topic |
Author |
Message |
filjoa
Joined: 04 May 2008 Posts: 260
|
problem with press button and interrupts |
Posted: Thu Sep 18, 2014 3:10 pm |
|
|
Hi
I stay many time without programming, because work time... now I start like a "newer"
A simple program I need have a switch button to choose, some sequences on program.
but the 1º program stay in fact, when I press the switch (I have pulldown 1k) my interrupt count many times, and jump sequences.
Can one help to see the problem?
best regards
Code: |
#include <16F628A.h>
#fuses NOWDT,INTRC_IO, NOCPD, NOPROTECT, MCLR, NOPUT, BROWNOUT
#use delay(clock=4000000)
int8 count = 0, aux = 0;
#define LED1 PIN_A1
#define LED2 PIN_A0
#define LED3 PIN_A7
#define LED4 PIN_A6
#int_ext
void int_rb0()
{
count++;
delay_ms(50);
}
void seq1()
{
//###### sequenciador 1
output_high(LED1); output_low(LED2);output_low(LED3); output_low(LED4); delay_ms(100);
output_low(LED1); output_high(LED2);output_low(LED3); output_low(LED4); delay_ms(100);
output_low(LED1); output_low(LED2);output_high(LED3); output_low(LED4); delay_ms(100);
output_low(LED1); output_low(LED2);output_low(LED3); output_high(LED4); delay_ms(100);
aux=1;
}
void seq2()
{
//###### sequeciador 2
output_high(LED1); output_low(LED2);output_low(LED3); output_low(LED4); delay_ms(200);
output_high(LED1); output_high(LED2);output_low(LED3); output_low(LED4); delay_ms(200);
output_high(LED1); output_high(LED2);output_high(LED3);output_low(LED4); delay_ms(200);
output_high(LED1); output_high(LED2);output_high(LED3);output_high(LED4); delay_ms(200);
output_low(LED1); output_high(LED2);output_high(LED3); output_high(LED4); delay_ms(200);
output_low(LED1); output_low(LED2);output_high(LED3); output_high(LED4); delay_ms(200);
output_low(LED1); output_low(LED2);output_low(LED3); output_high(LED4); delay_ms(200);
output_low(LED1); output_low(LED2);output_low(LED3); output_low(LED4); delay_ms(200);
aux=2;
}
void seq3()
{
//###### sequeciador 3
output_high(LED1); output_high(LED2);output_high(LED3); output_high(LED4); delay_ms(200);
aux=3;
}
void seq4()
{
//###### sequeciador 4
output_high(LED1); output_low(LED2);output_high(LED3); output_low(LED4);delay_ms(100);
output_low(LED1); output_high(LED2);output_low(LED3); output_high(LED4);delay_ms(100);
output_high(LED1); output_low(LED2);output_high(LED3); output_low(LED4);delay_ms(100);
output_low(LED1); output_high(LED2);output_low(LED3); output_high(LED4);delay_ms(100);
aux=4;
}
void main (void)
{
int8 temp = 0;
int16 aux = 0;
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
setup_timer_2(T2_DIV_BY_1, 255, 1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(0); //0 até 255
while(TRUE)
{
if (count==0) seq1();
if (count==1) seq2();
if (count==2) seq3();
if (count==3) seq4();
if (count>3) count=0;
set_pwm1_duty(aux);
if (temp==0) aux=aux+20;
if (temp==1) aux=aux-20;
if (aux<=0) temp=0;
if (aux>=1020) temp=1;
}
}
|
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Sep 18, 2014 3:53 pm |
|
|
Your problem is very likely caused by switch bounce. Put very simply, the contacts of the switch are making-breaking-making-breaking-making...(etc) very rapidly even though it feels, to you, like one press. Humans don't "see" the bounce because it happens so quickly but your processor can see it.
You either need a software debounce routine or you'll need to add a capacitor to your switch circuitry to implement an RC circuit that will filter/smooth the bounce. In my experience, bounce usually stops within 20-30ms at worst, so use this fact to choose your R and C values. A software debounce routine can be as simple or as complex as you wish but it generally involves a timer that's triggered by the button interrupt -> timer expires -> is switch still pressed? -> NOW do what you originally wanted to do. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Sep 19, 2014 12:35 am |
|
|
Easier in many ways, is to forget using interrupts directly from the buttons at all....
Instead have a system 'tick' (a timer interrupt at say 100Hz).
Then in this, read the buttons.
If a button is set, set a flag to say 'may have'.
Then the next time the interrupt calls, if the button is set, and the 'may have' flag is also set, record a button.
If the button is no longer set, clear the flag.
This way a button has to be set, for two successive calls, before it is recorded.
It is more reliable, and extendible for as many buttons as you want.
Also, the same timer, can then be used for other 'housekeeping' tasks.
I doubt if any of the 'old hands' here, actually uses an external level interrupt directly to handle buttons. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Sep 19, 2014 5:02 am |
|
|
I'm with Ttelmah on this one.
Using an edge trigger for buttons never even crosses my mind.
I'd also be wary of connecting a C directly across any kind of switch contact.
Long term, repeated discharge is likely to damage the contact.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Fri Sep 19, 2014 5:16 am |
|
|
here's a simple approach that works well without using the 'timer' method.
LT is the I/O PIN that the switch is connected to( and ground), pullup resistor(10K) as well).
The delay value of 20ms can be changed ,less is faster response.
Code: | //armed function - wait for keypress -
int armed()
{
while (!input(LT) ) ; //wait if low
delay_ms(20); //debounce delay
while (input(LT) ) ; //wait if hi
delay_ms(20); //debounce delay
return (1); //set armed flag
} | as I said it is simple, easy to use, no timer involved....
jay |
|
|
|
|
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
|