Is this a switch bounce problem?

Discussion in 'Embedded Systems and Microcontrollers' started by mwalden824, May 31, 2011.

  1. mwalden824

    Thread Starter Member

    Mar 6, 2011
    51
    2
    I recently ordered the EasyAVR6 and have made a few small things with it. I am having troubles with my current little project. I am trying to just make the menu keypad type whatever on the 2x16 LCD. It starts off just showing an A and if you press up it goes up through the ASCII characters, and down opposite, and left and right moves while cancel resets. The problem is when i press any of the buttons it does what it's suppose to but like 10 times, or something more or less, randomly. And then sometimes it does nothing. I can't press it to fast either, it seems like it freezes or something.

    Anyway, I am new to this so I am probably overlooking something stupid. I hoped someone could point it out for me. In particularly look at the area where I do the debouncing. I got the idea from a post:
    http://forum.allaboutcircuits.com/showthread.php?t=53507&highlight=software+debounce
    Not sure if I implemented it correctly though. I am pretty sure that is the problem, and I just don't understand why. I have tried many different values for the delay, etc. but no luck.

    The push buttons for the keypad are connected to high when the button is pressed and I assume they are pulled down with a resistor while not pressed, yet it doesn't show this in the schematic, but its not full schematic. I dunno, you think they may be open when not pressed? surely they wouldn't have designed this board that way?

    I read this post having similar problem:
    http://forum.allaboutcircuits.com/showthread.php?t=55020
    He said he had to add caps to power rail, but I'm using USB power from the programming cable.


    Thanks for any help,
    Michael Walden

    P.S. Here's the code...
    Code ( (Unknown Language)):
    1.  
    2. #include <mega16.h>
    3. #include <alcd.h>
    4. #include <string.h>
    5. #include <delay.h>
    6.  
    7. #define UP      0b00000001
    8. #define DOWN    0b00001000
    9. #define LEFT    0b00000010
    10. #define RIGHT   0b00000100
    11. #define ENTER   0b00010000
    12. #define CANCEL  0b00100000
    13.  
    14. unsigned char letter = 'A';
    15. unsigned char pad = 0x00;   // To save keypad press
    16. const unsigned char startmsg[] = "A               \n                ";
    17. unsigned char msg[35];
    18. unsigned index = 0;         // Current string (msg) position
    19. unsigned char count = 0;    // To count for Debounce
    20.  
    21. void upf(void);             // Declare Functions
    22. void downf(void);
    23. void leftf(void);
    24. void rightf(void);
    25. void enterf(void);
    26. void cancelf(void);
    27. void move(unsigned char c);
    28.  
    29. void main(void)
    30. {
    31.     DDRA = 0x00;  
    32.    
    33.     strcpy(msg, startmsg);      // Start Message
    34.  
    35.     lcd_init(16);       // Initialize 2x16 LCD
    36.     lcd_clear();
    37.     lcd_gotoxy(0,0);
    38.     lcd_puts(msg);      // Print Start Message
    39.  
    40.     while (1)
    41.     {            
    42.         pad = PINA;
    43.        
    44.         while ((pad > 0x00) && (count < 6))    // Debounce
    45.         {                                  
    46.             delay_ms(1);
    47.             pad = PINA;
    48.             count++;
    49.         }          
    50.        
    51.         if (count >= 5)      // Debounce
    52.         {
    53.             move(pad);      // Only move if 5 successful highs from button
    54.             count = 0;
    55.         }
    56.        
    57.     }
    58. }
    59.  
    60. void upf(void)
    61. {
    62.     letter = msg[index];    
    63.    
    64.     if (letter != 32)    // Lowest Acceptable ASCII range
    65.     {
    66.         letter--;
    67.         msg[index] = letter;    // Change current positions character
    68.         lcd_gotoxy(0,0);        // and reprint string
    69.         lcd_puts(msg);
    70.     }
    71. }
    72.  
    73. void downf(void)
    74. {
    75.     letter = msg[index];        // Basically same as above
    76.    
    77.     if (letter != 126)
    78.     {
    79.         letter++;
    80.         msg[index] = letter;
    81.         lcd_gotoxy(0,0);
    82.         lcd_puts(msg);
    83.     }
    84. }
    85.  
    86. void rightf(void)
    87. {
    88.     if (index == 15)    // If at end of LCD jump of null character
    89.         index = 17;
    90.     else if (index == 32)   // Go back to beginning
    91.         index = 0;
    92.     else
    93.         index++;
    94. }
    95.  
    96. void leftf(void)        // Same as above but in reverse
    97. {
    98.     if (index == 17)
    99.         index = 15;
    100.     else if (index == 0)
    101.         index = 32;
    102.     else
    103.         index--;
    104. }
    105.  
    106. void enterf(void)
    107. {
    108.  // write later
    109. }
    110.  
    111. void cancelf(void)  // Restarts
    112. {
    113.     lcd_clear();
    114.     index = 0;
    115.     lcd_gotoxy(0,0);
    116.     strcpy(msg, startmsg);
    117.     lcd_puts(msg);
    118. }
    119.  
    120. void move(unsigned char c)  // Does action
    121. {
    122.     switch (c)
    123.     {
    124.         case UP:
    125.             upf();
    126.             break;
    127.        
    128.         case DOWN:
    129.             downf();
    130.             break;
    131.        
    132.         case LEFT:
    133.             leftf();
    134.             break;
    135.                
    136.         case RIGHT:
    137.             rightf();
    138.             break;
    139.                
    140.         case ENTER:
    141.             enterf();
    142.             break;
    143.                
    144.         case CANCEL:
    145.             cancelf();
    146.             break;
    147.                    
    148.         default: ;  // Do nothing
    149.     }
    150. }
    151.  
    152.  
     
  2. DumboFixer

    Active Member

    Feb 10, 2009
    219
    34
    The problem you are seeing is that you are going to be calling move(pad) many times.

    When you press a key you wait 1ms and increment count. Once count reaches 6 you exit the while loop and because count is now 6 the next block of code is called which calls move(pad).

    You now go back to start of the first while loop and if the key is still pressed the whole process will start all over again, calling move(pad) for as long as you have your finger on the key.

    A way round this is to checking for a leading edge in pad. By that I mean it changing from 0 to a value (and only a change from 0 to something). Once you have this edge you can then perform your output. you could also put in a delay of, say 25mS after the edge has been detected to ignore the bounce.
     
    mwalden824 likes this.
  3. mwalden824

    Thread Starter Member

    Mar 6, 2011
    51
    2
    Thank you so much man. I am going to do this as soon as I get home today. I'll post when I get it to work.

    Michael Walden
     
  4. mwalden824

    Thread Starter Member

    Mar 6, 2011
    51
    2
    Got it. Thanks again. I used two variables to read input from buttons, one to start of and one was looped until they were not equal then they were compared and if the latest one was greater, then the move function was called with that current value.

    I just could not figure that out for nothing the other night. I guess I'll learn these things as I encounter them.

    Only thing now is that you still can't press the buttons too fast or it will not do anything which I assume is from the delay. So I will play with that value and see what I get now, but the smaller I make it I risk taking in weird data from bouncing.. I usually have to wait about a half second in between presses for a successful call to the right function or it will not do anything. But at least it doesn't jump.

    Here is the fixed code for anyone having this problem and wants to see how I implemented what DumboFixer suggested...

    Code ( (Unknown Language)):
    1.  
    2. #include <mega16.h>
    3. #include <alcd.h>
    4. #include <string.h>
    5. #include <delay.h>
    6.  
    7. #define UP      0b00000001
    8. #define DOWN    0b00001000
    9. #define LEFT    0b00000010
    10. #define RIGHT   0b00000100
    11. #define ENTER   0b00010000
    12. #define CANCEL  0b00100000
    13.  
    14. unsigned char letter = 'A';
    15. const unsigned char startmsg[] = "A               \n                ";
    16. unsigned char msg[35];
    17. unsigned index = 0;         // Current string (msg) position
    18. unsigned char currbut = 0, prevbut = 0;
    19.  
    20. void upf(void);             // Declare Functions
    21. void downf(void);
    22. void leftf(void);
    23. void rightf(void);
    24. void enterf(void);
    25. void cancelf(void);
    26. void move(unsigned char c);
    27.  
    28. void main(void)
    29. {
    30.     DDRA = 0x00;  
    31.    
    32.     strcpy(msg, startmsg);      // Start Message
    33.  
    34.     lcd_init(16);       // Initialize 2x16 LCD
    35.     lcd_clear();
    36.     lcd_gotoxy(0,0);
    37.     lcd_puts(msg);      // Print Start Message
    38.  
    39.     while (1)
    40.     {            
    41.         prevbut = PINA;
    42.        
    43.         do
    44.         {
    45.             currbut = PINA;         // Checks for edge
    46.         } while (prevbut == currbut);
    47.        
    48.         if (currbut > prevbut)      // if rising edge...
    49.         {
    50.             delay_ms(25);
    51.             move(currbut);
    52.         }
    53.     }
    54. }
    55.  
    56. void upf(void)
    57. {
    58.     letter = msg[index];    
    59.    
    60.     if (letter != 32)    // Lowest Acceptable ASCII range
    61.     {
    62.         letter--;
    63.         msg[index] = letter;    // Change current positions character
    64.         lcd_gotoxy(0,0);        // and reprint string
    65.         lcd_puts(msg);
    66.     }
    67. }
    68.  
    69. void downf(void)
    70. {
    71.     letter = msg[index];        // Basically same as above
    72.    
    73.     if (letter != 126)
    74.     {
    75.         letter++;
    76.         msg[index] = letter;
    77.         lcd_gotoxy(0,0);
    78.         lcd_puts(msg);
    79.     }
    80. }
    81.  
    82. void rightf(void)
    83. {
    84.     if (index == 15)    // If at end of LCD jump of null character
    85.         index = 17;
    86.     else if (index == 32)   // Go back to beginning
    87.         index = 0;
    88.     else
    89.         index++;
    90. }
    91.  
    92. void leftf(void)        // Same as above but in reverse
    93. {
    94.     if (index == 17)
    95.         index = 15;
    96.     else if (index == 0)
    97.         index = 32;
    98.     else
    99.         index--;
    100. }
    101.  
    102. void enterf(void)
    103. {
    104.  // write later
    105. }
    106.  
    107. void cancelf(void)  // Restarts
    108. {
    109.     lcd_clear();
    110.     index = 0;
    111.     lcd_gotoxy(0,0);
    112.     strcpy(msg, startmsg);
    113.     lcd_puts(msg);
    114. }
    115.  
    116. void move(unsigned char c)  // Does action
    117. {
    118.      
    119.     switch (c)
    120.     {
    121.         case UP:
    122.             upf();
    123.             break;
    124.        
    125.         case DOWN:
    126.             downf();
    127.             break;
    128.        
    129.         case LEFT:
    130.             leftf();
    131.             break;
    132.                
    133.         case RIGHT:
    134.             rightf();
    135.             break;
    136.                
    137.         case ENTER:
    138.             enterf();
    139.             break;
    140.                
    141.         case CANCEL:
    142.             cancelf();
    143.             break;
    144.                    
    145.         default: ;  // Do nothing
    146.         }
    147. }
    148.  
    149.  
     
Loading...