View previous topic :: View next topic |
Author |
Message |
piire
Joined: 04 Mar 2009 Posts: 19
|
simple led push button program |
Posted: Wed Feb 10, 2010 11:49 am |
|
|
Hi there, I'm trying to make a simple push button program, which turns on a led when it is pressed and then turns it off when pressed again. I have connected the + side of the led to pin C4. The push button allows power to go to pin C3 when pressed. I'm using a pic16f877a.
This is the code I've been trying to use:
Code: |
#include <16F877A.H>
#fuses XT, NOPROTECT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
//====================================
void main()
{
if(input(PIN_C3) == 1)
{
output_high(PIN_C4);
}
else if (input(PIN_C3) == 1 && input(PIN_C4) == 1 ){
output_low(PIN_C4);
}
delay_ms(200);
}
|
Can anyone spot my mistake, it's driving me mad?
Thanks for your help
piire! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
piire
Joined: 04 Mar 2009 Posts: 19
|
|
Posted: Fri Feb 12, 2010 6:17 am |
|
|
Hi there
I looked at your code thanks alot, but I need to connect more leds to do other operation and this code wont work for this task.
Can I use the set_tris_ operation to set inputs and outputs to get this to work with if statements ?
How would i use the set_tris_ operation for input pin C3 and output C4. I don't understand how the set_tris_ works?
I'm using pic16f778a.
Thanks for your help.
piire!! |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Fri Feb 12, 2010 7:02 am |
|
|
You don't need to use tris statements.
You problem is that you are first using C4 as an output and the compiler configures it as an output when it first uses
OUTPUT_HIGH(PIN_C4);
BUT, when you try to read the value back
else if (input(PIN_C3) == 1 && input(PIN_C4) == 1 )
This re-configures it as an input.
You have 2 options.
Use INPUT_STATE(PIN_C4) to read its value without changing it's direction or use a flag to indicate the current setting of PIN_C4.
INPUT_STATE may be affected by what is known as the RMW Read, Modify, Write issue. But I don't think so.
I am sure someone else can shed some light on this. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Feb 12, 2010 8:24 am |
|
|
Besides the problem mentioned by Wayne there is also a logical error: Code: | if(input(PIN_C3) == 1)
....
else if (input(PIN_C3) == 1 && input(PIN_C4) == 1 ){
....
| If the button on C3 is active, then the first test always will be executed and you never get to the 'else'.
You could solve this like: Code: | if (input(PIN_C3) == 1 && input_state(PIN_C4) == 1 )
....
else if (input(PIN_C3) == 1 && input_state(PIN_C4) == 1 ){
....
|
A weak issue in this solution is the mentioned RMW problem; it is possible that external capacitances on the line causes the line not to have the output level you think it has. Better is to use a variable to keep track of the LED output status.
Code: | #include <16F877A.H>
#fuses XT, NOPROTECT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#define BUTTON PIN_C3
#define LED PIN_C4
#define ON 0
#define OFF 1
void main()
{
int8 LedStatus = OFF;
while (TRUE)
{
if ((input(BUTTON) == 1) && (LedStatus == OFF))
{
output_high(LED);
LedStatus = ON;
}
else if (input(BUTTON) == 1 && (LedStatus == ON))
{
output_low(LED);
LedStatus = OFF;
}
delay_ms(200);
}
} |
|
|
|
aa7dj
Joined: 27 Apr 2007 Posts: 7 Location: St. George, UT
|
Oscillator Type |
Posted: Fri Feb 12, 2010 10:24 am |
|
|
Quote: | #include <16F877A.H>
#fuses XT, NOPROTECT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000) |
For 20 MHz fuse should be set to HS. See page 146 of PIC16F87xA Data Sheet. |
|
|
piire
Joined: 04 Mar 2009 Posts: 19
|
|
Posted: Sun Feb 14, 2010 10:12 am |
|
|
Thanks alot for your help. The system works, I do sometimes have to press the button twice to turn the led on, but I guess thats to do with the processing power of the PIC.
Thanks alot got your all help!
piire! |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Feb 14, 2010 4:12 pm |
|
|
Quote: | I do sometimes have to press the button twice to turn the led on, but I guess thats to do with the processing power of the PIC. | Processing power is part of the problem, the PIC is too fast for your switch.
A common problem in hardware switches is 'bouncing'. When the switch changes position it takes a little time to settle in the final position, it makes contact and then bounces back a few times. Depending on switch internals it can take up to 20ms to make final contact.
You'll have to add hardware for debouncing (a simple R/C combination on a Schmitt Trigger input) or add software debouncing (many implementations exist, the simplest is a delay of 20ms). |
|
|
|