led blinking error

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So i have being trying to toggle between two LEDs whenever i press a push button.I actually had two codes to execute the same with minor differences.

 

1) Using two if statements to check that the LED toggle only once when the push button is pressed

2)Using a conditional AND operation to check that the LED toggle only once when the push button is pressed.

 

For the time being i have ignored switch debouncing and the pushbutton is pulled low with an external 10k resistor.

 

 CODE 1        using two IFs

 

#include<avr/io.h>
#define F_CPU 4000000UL

int main(void)
{
DDRD|=1<<1;    //data direction register set as output for led 1 
DDRD|=1<<2;   //data direction register set as output for led 2
DDRD&=~1<<0;  //data direction register set as input for push button 
PORTD&=~1<<1; //led 1 low initially
PORTD|=1<<2;//led 2 high initially
int pressed=0;//flag to check toggle happens only once when push button is pressed
while(1)
{
if(PIND&(1<<0)) //when push button is pressed 
{
if(pressed==0) //and the toggle is happening for the first time within the duration of the button remaining pressed
{PORTD^=1<<1;//toggle leds
PORTD^=1<<2;
pressed=1;//set the flag so no more toggling takes place within the duration of one button press
}
}
else
pressed=0;//if led toggling has happened once during one press reset the flag for the next button press 
}
}



CODE 2 using conditional AND 

 

#include<avr/io.h>
#define F_CPU 4000000UL

int main(void)
{
DDRD|=1<<1;    //data direction register set as output for led 1 
DDRD|=1<<2;   //data direction register set as output for led 2
DDRD&=~1<<0;  //data direction register set as input for push button 
PORTD&=~1<<1; //led 1 low initially
PORTD|=1<<2;//led 2 high initially
int pressed=0;//flag to check toggle happens only once when push button is pressed
while(1)
{
if(((PIND&(1<<0))==1)&&(pressed==0) ) //when push button is pressed and the toggle is happening for the first time within the duration of the button remaining pressed
{

PORTD^=1<<1;//toggle leds
PORTD^=1<<2;
pressed=1;//set the flag so no more toggling takes place within the duration of one button press
}
else
pressed=0;//if led toggling has happened once during one press reset the flag for the next button press 
}
}



PROBLEM:

for the first code the led toggles only once when the button is kept pressed as expected but for the second code the leds toggle at a very fast rate for the button being kept pressed which should have only happened once due to the presence of the flag.

It is happening that the condition Pressed ==0 is always being true even though it has been changed to 1 once the led is toggled for the first time.

 

i felt that a conditional AND would not make any changes to the execution and would make the code compact but turns out the results were different.

 

Plz help me where i am going wrong with the conditional AND  decision making statement and thanks in advance.

soumikmukherjee

Last Edited: Sat. Apr 21, 2018 - 06:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The problem is not with the AND in Code 2.,
the problem is that the pressed flag is being reset on every loop of the while(1) when PIND.0 is low, or on every second loop if PIND.0 is high.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try

uint8_t pressed = 0; //flag to check toggle happens only once when push button is pressed

int main(void)
{
    DDRD  |= (1<<1);    //data direction register set as output for led 1
    DDRD  |= (1<<2);    //data direction register set as output for led 2
    DDRD  &= ~(1<<0);   //data direction register set as input for push button
    PORTD &= ~(1<<1);   //led 1 low initially
    PORTD |= (1<<2);    //led 2 high initially

    while(1)
    {
        if(((PIND & (1<<0)) == 1) && (pressed == 0) ) //when push button is pressed and the toggle is happening for the first time within the duration of the button remaining pressed
        {
            PORTD ^=  1<<1);    //toggle leds
            PORTD ^=  1<<2);
            pressed = 1;        //set the flag so no more toggling takes place within the duration of one button press
        }
        else if( (PIND & (1<<0)) == 0)
            pressed = 0;        //if button released reset the flag for the next button press
    }
}

 

Last Edited: Sun. Apr 22, 2018 - 04:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the help.i had to add an else if condition rather than the else condition to avoid the reseting of the flag for every while loop. 

soumikmukherjee

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for your effort.it is working in the expected way

soumikmukherjee

Last Edited: Sun. Apr 22, 2018 - 04:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Often, there are several solutions to a problem.
My personal preference would be for the Code 1 technique because it is easier to comprehend.