Why LED is not turning OFF - 8051 Timers

trebla

Joined Jun 29, 2019
542
I see following five possible states: button release debounce active, button press acknowledged, idle, button press debounce active, button press debounced.
Draw these states and try figure out which kind of transitions (or dependencies) are between different states. You can add output signal (LED toggle) as connection to another process but keep in mind that "toggling a LED" is transition between states not a state itself.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I see following five possible states: button release debounce active, button press acknowledged, idle, button press debounce active, button press debounced.
I do not understand how your states will work. Button has only two states, button is pressed and button is released.

Button release debounc activate state :
We can check if button is released and wait for debounce period

Button pressed debounc activate state :
We can check if button is pressed and wait for debounce period debounced mean?

What is debounce active mean?
What is button press acknowledged mean
What is button press debounced?
 

trebla

Joined Jun 29, 2019
542
I suggested you to imagine how MCU works. I try explain again and you try to imagine this:

MCU in our embedded system has many external connections to drive in real time and periodically check. One of inputs is our button. For this purpose we have one function (call it "button function") which is called periodically.
If button is not pressed a while, this function marks its state to "idle" and the MCU deals with other processes.
If button is suddenly pressed then our function marks its state to "button acknowledged", this state sends output signal for another process (like "toggle LED") and debounce timer.
Debounce timer starts an changes state to "button press debounce active ". Meanwhile MCU manages again with other tasks.
If debounce timer runs out then it changes state to "button press debounced".
If MCU reaches again the "button function" then it looks the current state and checks button input. If button is released, function sends signal to debounce routine and this marks state to "button release debounce active ".
If button still pressed then state remains unchanged and MCU can deal with other tasks until reaches the "button function" again. But in "button release debounce active " state, if debounce timer runs out it marks state back to "idle".
I believe you can now draw the state diagram.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I suggested you to imagine how MCU works. I try explain again and you try to imagine this:
@trebla I am trying my best to understand I took many time to figure out myself but I still do not understand your states.

My guess is that you want to use the timer interrupt for the debounce routine. Set the time interrupt for small interval ie. 1ms and if button is pressed, increment counter and when count will equal to 40 counts and button is still pressed it confirmed button has been pressed

I am sorry , i don't really know what you thought
 

trebla

Joined Jun 29, 2019
542
For debounce timer we can use interrupt routine or just poll the timer interrupt flag regularly. Interrupt gives more precise timing than software polling. In the other hand, if we have some other tasks that require specific strict sequence and timing then we must dealing with disabling interrupts temporarily or use software polling instead. As button debouncing does not need precise timing we can just poll the timer interrupt flag in convient place in our software. Our priority is waste minimum time for checking debounce states. One possible solution for debounce timer routine is setting a timer for 1 ms period and activate timing by loading a countdown variable. Then we can poll timer interrupt flag in regular basis and if 1 ms is passed, decrement the countdown value until zero or let the interrupt based routine make same thing. If countdown variable reaches zero then the debounce timer routine changes debounce state as described in #178.

As you see now, there will be more than one functions are needed to be complete button debounce task in non-blocking mode. Therefore is reasonable create a state diagram before writing the code or even drawing the flowchart.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
. One possible solution for debounce timer routine is setting a timer for 1 ms period and activate timing by loading a countdown variable.
It will be very difficult for me to draw a complete state diagram right now. That's why I will try to make one step at one time

Timer interrupt is set for 1ms and debounce time is 20 ms. When timer interrupt happen we check button is pressed so if button is pressed we decrement count

So when counter will reach at zero. State will change
 

Attachments

trebla

Joined Jun 29, 2019
542
Debounce timer does not check the button state. It starts for button press when:
a) if debounce state is "button acknowledged"
and
b) if the countdown variable value is above zero (in C: if(a&&b) ).
After starting it changes debounce state to "button press debounce active". It is necessary for avoiding button press acnowledging again constantly.
It checks only timer interrupt flag and countdown variable value.
If countdown value reaches zero then it changes debounce state to "button press debounced" and ends.

For button release debouncing we can use same timer routine but debounce state values are different as descibed in #178.

For this debounce timer you can also draw state diagram, i think there are 4 states at first glance.

In state diagram a circle means system state (for example "button press debounce active") and arrow between states means a condition for changing to another state (for example "countdown_variable == 0").
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
In state diagram a circle means system state (for example "button press debounce active") and arrow between states means a condition for changing to another state (for example "countdown_variable == 0").
Okay I think state diagram should start from ideal state, what happen in ideal state? In ideal state button is not pressed. So when button press and count down is greater then zero we are in button pressed acknowledge state. So when count down reach to zero button press acknowledge state change to button press debounce active state
 

Attachments

trebla

Joined Jun 29, 2019
542
Ideal state for debounce timer is "timer_idle" and it checks for debounce status. When debounce status goes to "button acknowledged" then it moves to another state which is "button press debounce active" and there will be checked the countdown_variable". If the countdown_variable goes down to zero then the last state is "button press debounced" where this timer routine ends.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
My understanding is Interrupt happens at every 1ms interval. When switch button is pressed, count up interrupt and if the count reach upto 40 counts (40ms) it means switch button has stopped its bouncing and then control LED

If switch button is released, count down interrupt and When it reaches zero, it means button is released

My problem is that I am not able to create a state diagram Even after explaining it many times by @trebla

Would this approach be okay if I would look at the sample code and try to make state diagrams for them? Maybe I will get ideas from this how do you decide how many states will be and what will be the present state, what will be the next state

I am thinking this because I think if my current approach is not working I must change my approach
 
Last edited:

trebla

Joined Jun 29, 2019
542
There are two example functions to call frequently in main loop for debouncing:

C:
void ButtonCheck(void) { //check button status

    if(debounce_state == IDLE) {  //not pressed before
        if(BUTTON == PRESSED) {  //button press acknowledge
            debounce_state = BUTTON_PRESS_ACK; //change debounce status           
        }
    }
    else if(debounce_state == PRESS_DEBOUNCED) {  //button press debounce timer ended
        if(BUTTON == NOT_PRESSED) {  //button release acknowledged
            debounce_state = BUTTON_RELEASE_ACK; //change debounce status
            debounce_delay = DELAY_20ms;  //reload debounce timer value
        }
    }
} //void ButtonCheck(void)

void DebounceTimer(void) {  //delay for button debounce, software polling

    static unsigned int debounce_delay;
    
    if(Timer_IF) {  //check timer interrupt flag
        Timer_IF = 0; //clear flag
        if(debounce_state == BUTTON_PRESS_ACK) {  //button press acknowledged
            debounce_state = PRESS_DEBOUNCE_ACT;  //change debounce status to active
            debounce_delay = DELAY_20ms;  //reload debounce timer value
        } //button press acknowledged
        if(debounce_state == PRESS_DEBOUNCE_ACT) {  //we must count down
            if(debounce_delay > 0) {  //until counter is zero
                debounce_delay--;  //variable decrement
            }
            else {
                debounce_state = PRESS_DEBOUNCED;  //change debounce status to debounced
            }
        } //press debounce count down
        if(debounce_state = BUTTON_RELEASE_ACK) {  //button release acknowledged
            debounce_state = RELEASE_DEBOUNCE_ACT;  //change debounce status to active
            debounce_delay = DELAY_20ms;  //reload debounce timer value
        } //button release acknowledged
        if(debounce_state == RELEASE_DEBOUNCE_ACT) {  //we must count down
            if(debounce_delay > 0) {  //until counter is zero
                debounce_delay--;  //variable decrement
            }
            else {
                debounce_state = IDLE;  //change debounce status to idle
            }
        } //release debounce count down
    } //check timer interrupt flag
} //void DebounceTimer(void)
 
Top