Connect with us

Help with debounce code

Discussion in 'Microcontrollers, Programming and IoT' started by chopnhack, Jul 20, 2015.

Scroll to continue with content
  1. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    Hello all, just dabbling with a bit of debounce code. Following along in the book "PIC MCU Programming" by Bert van Dam. I would highly recommend it for anyone who is feeling challenged by the disconnect between programming and the hardware interface of PIC's - this book seemed to break it down relatively well. Common gripe of most of these books remains with this one of having to get the specific chip being used in the book for maximum effectiveness - luckily there was a choice of three chips that were similar enough, so I found one that was reasonably priced and easy enough to source. Enough soapbox.

    My current issue is understanding this bit of code I wrote to solve one of the questions in the book. The goal was to turn on a LED after pressing a momentary switch and on the third press, to turn it off. Essentially ignoring one button press (the second press). The code is JAL (just another language). I wrote the following code, it compiled with no errors, but does not produce the desired result. My first guess is that it is happening too fast to catch, but it is inside a forever loop so I then thought to include the debounce statement for each test of the switch. Still not working as expecting - any hints?

    upload_2015-7-19_19-9-13.png

    upload_2015-7-19_19-11-14.png
     
  2. (*steve*)

    (*steve*) ¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd Moderator

    25,305
    2,738
    Jan 21, 2010
    The basic denounce logic should be to ignore the button until its reading is stable.

    There are multiple ways to do this. One way is to keep reading the button until you get some number of identical sequential results.
     
    chopnhack likes this.
  3. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    Thanks Steve. I am aware of the method you mention, I have read about it in other books and online. I am following the text so that I don't get confused or lost! LOL
    The debounce method listed above does work (I increased it to 40ms), but it still works. The problem I am having is that I am not seeing no action on the second button depress followed by a change in LED status to off on the third depress. That is what I was expecting. Instead, the LED comes on, on first button press, off on second and then after that it can be somewhat random.
     
  4. (*steve*)

    (*steve*) ¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd Moderator

    25,305
    2,738
    Jan 21, 2010
    think about it this way:

    your code should have four (arguably three) states.

    1. Just started
    2. Button pressed once
    3. Button pressed twice
    4. Button pressed thrice

    when the program starts, the state is 1. Each time a button is pressed you move from one state to another.

    Based on the state you're in, you light the led or not.

    so all you need to do after initializing things is to loop around code which:

    1 detect button pressed
    2 change state
    3 turn led on or off based on state
    4 wait for button to be released.

    you can unwrap this into linear code but it rapidly becomes less than trivial (not to mention, repetitive) when you have more states and more complex transitions.
     
    chopnhack likes this.
  5. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    Thanks Steve. I appreciate the time you took to break that down into logical steps. Odd thing is, I thought that is what i accomplished with my if,then statements.

    The entirety is wrapped in an endless loop, which had me thinking that perhaps after the first delay, the next bit of code is only actioned once and not repetitively. This would make the code not work as expected.

    I'm off to work, but the next change I was thinking of was putting an individual forever loop on each if,then statement. Am I on the right course or hopelessly lost?
     
  6. (*steve*)

    (*steve*) ¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd Moderator

    25,305
    2,738
    Jan 21, 2010
    look at your code. If you push the button, but by the time the second read happens the switch has bounced open, it falls through to the next state

    what you might be able to do is change the code so that it only drops through after 25 consecutive reads of 0 ( with the same 4ms spacing)
     
  7. Colin Mitchell

    Colin Mitchell

    1,418
    314
    Aug 31, 2014
    That's why I code in .asm
    Frustration has left me 5 years ago.
    Basically you need a 5mS to 10mS delay loop to eliminate debounce problems.
    The simplest is to create 3 consecutive sub-routines and the micro gets caught in these loops (sub-routines) and will not emerge until the button has been pressed 3 times.
    This is called LINEAR PROGRAMMING and although it is inefficient, all my readers can see what is being done and they can then go and produce a Boolean version or Nested Loops.
     
    hevans1944 likes this.
  8. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    It was the speed of execution. I had to "forever loop" each individual statement to get it to work- thus keep polling the switch for change.

    upload_2015-7-20_22-15-14.png
     
  9. (*steve*)

    (*steve*) ¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd Moderator

    25,305
    2,738
    Jan 21, 2010
    try this

    # wait for press
    n = 0;
    while n < 25 do
    if pin_d2 then inc(n) else n=0;
    delay_ms(4);
    wend;


    # wait for release
    n = 0;
    while n < 25 do
    if not pin_d2 then inc(b) else n=0;
    delay_ms(4);
    wend;

    feel free to tune these as required.
     
  10. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    Thanks Steve. Hopefully as I go through more of the book, this will get clearer and perhaps other methods of approaching this will be seen. There are sections of the book that deal with functions and libraries. I am excited to get to that section!
     
  11. jayanthd

    jayanthd

    43
    10
    Jul 4, 2015
    Try this mikroC PRO PIC code with the mikroC PRO PIC demo version compiler. Set clock to 4MHz and Oscillator type to XT in edit project dialog box.

    Code:
    char counter = 0;
    
    void main()
    {
        cmcon = 7;
        cvrcon = 0;
    
        adcon1 = 0x87;
    
        trisa = 0;
        trisb = 0;
        trisc = 0;
        trisd = 4;
    
        porta = 0;
        portb = 0;
        portc = 0;
        portd = 0;
    
        delay_ms(200);
    
        while(1)
        {
            if(portd.f2)
            {
                delay_ms(50);
                while(portd.f2);
                {
                    counter++;
                }
            }
    
            switch(counter) {
    
                case 1:
                    portd.f1 = 1;
                    break;
                case 3:
                    portd.f1 = 0;
                    counter = 0;
                    break;           
            };       
        }
    }
     
    chopnhack likes this.
  12. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    Thank you Jaya, it is something I can eventually build to. I have not started mikroC yet. I have been tempted, but I want to be able to at least finish one project with mplabs. The syntax seems to change somewhat between compilers and that is what I am having the most trouble with right now - syntax. Well, syntax and addressing registers, LOL.
    Thanks again!
     
  13. jayanthd

    jayanthd

    43
    10
    Jul 4, 2015
    @chopnhack

    So, you need MPLAB X XC8 code ? If yes, please mention the PIC you are using and also the crystal frequency.
     
  14. chopnhack

    chopnhack

    1,573
    352
    Apr 28, 2014
    What I really need is to learn how to call the special function registers in mplabs! Thanks again :)
     
  15. jayanthd

    jayanthd

    43
    10
    Jul 4, 2015
    MPLAB or MPLAB X are IDEs. Mention the Compiler used with MPLAB or MPLAB X.

    You get the register (SFR) names in the device datasheet. For example, if datasheet has CMCON register and it has a bit like CM0 then all you have to do to set CM0 bit is

    CMCONbits.CM0 = 1

    Another example.

    SFR from datasheet is INTCON and bit for enabling global interrupt in INTCON register is GIE. So, you write like this

    INTCONbits.GIE = 1
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-