0
\$\begingroup\$

I have been trying to do the following: When a toggle switch is flipped down, the pic I'm using (16F1503) sends a pulse and turns on a led, when it is flipped up sends the same pulse and turns off the led. I managed to cobble some code together and works great. The problem is that I need to manage another toggle switch which it does exactly the same thing, but it sends a pulse on a different port and turns on/off a different led. Any suggestion? I'm having trouble mostly on debouncing multiple switches.

Here the code I'm using:

void main() 
{
uint8_t db_cnt;
PORTA=0;
PORTC=0;
ADCON0=0;
TRISA=0b001000;
TRISC=0b010000;


for(;;)
{
                //Wait for button press, debounce by counting:
                for (db_cnt=0; db_cnt <= 10; db_cnt++)
                {
                    __delay_ms(1);      //Sample every 1ms
                    if (TOGGLELEFT==0)  //If toggle off (RA3 low)
                        db_cnt=0;       //Restart count
                }                       //Until button on for 10 successive reads

                PORTA=0b100000;         //Turn OFF toggle LED, turn ON transistor
                __delay_ms(10);
                PORTA=0b000000;         //Turn OFF transistor

                //Wait for button release, debounce by counting:
                for (db_cnt=0; db_cnt <=10; db_cnt++)
                {
                    __delay_ms(1);      //Sample every 1ms
                    if (TOGGLELEFT==1)         //If toggle on (RA3 high)
                        db_cnt=0;       //Restart count 
                }                       //Until button off for 10 successive reads

                PORTA=0b110000;         //Turn ON toggle LED and transistor
                __delay_ms(10);
                PORTA=0b010000;         //Turn OFF transistor 
}
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Most of your trouble is probably caused by using delay functions. These aren't a good idea because they completely occupy the micro at the expense of all other activity except, perhaps, interrupts. There will be thousands of web examples of how to do this properly. The basic strategy is to start counting up if an input is pressed and register a "high" if it exceeds a threshold. If the input goes low then reset the counter. The trick is then to detect changes in state of your debounce output rather than the switch input itself. You'll need a counter per switch. \$\endgroup\$
    – Transistor
    Commented Mar 27, 2016 at 20:52

1 Answer 1

1
\$\begingroup\$

Your main problem in expanding this from one switch and one LED to two is that you need to keep track of the state of each pair separately but at the same time. So I would use two state machines, and two counters. Something like this:

state1 = 0;
state2 = 0;

while (1)
{
    switch(state1)
    {
       case 0:
           if (TOGGLELEFT==1)
               state1 = 1;      // go debounce next
               counter1 = 0;
           break;
       case 1:
           if (TOGGLELEFT==1)
               counter1++;
           else
               state1 = 0;      // start over
           if (counter1 > 10)   // after 10 ms,
           {
              PORTA=0b100000;   // turn OFF toggle LED, turn ON transistor
              state1 = 2;
           }
           break;
       case 2:
           counter1++;
           if (counter1 > 10)    // after 10 ms
           {
              PORTA=0b000000;    // turn OFF transistor
              state1 = 3;
           }
           break;
       case 3:
           if (TOGGLELEFT==0)
               state1 = 5;       // go debounce next
               counter1 = 0;
           break;
       case 3:
           if (TOGGLELEFT==0)
               counter1++;
           else
               state1 = 3;       // start over
           if (counter1 > 10)    // after 10 ms
           {
              PORTA=0b110000;    // turn ON toggle LED and transistor
              counter1 = 0;
              state1 = 5;
            }
           break;
       case 5:
           counter1++;
           if (counter1 > 10)     // after 10 ms,
           {
              PORTA=0b010000;    // turn OFF transistor
              state1 = 0;
           }
           break;
     }

     switch (state2)
     {
         // repeat with another switch statement for TOGGLERIGHT using state2 and counter2 etc.
     }

     __delay_ms(1);
}

So you can see how this allows you to keep track of both switches and LED's essentially in parallel.

I left the debounce timers the same as yours (10 ms) but I suggest making them considerably longer, say 50 ms.

\$\endgroup\$
2
  • \$\begingroup\$ I'm having some troubles trying to implement your code, I was wondering if you are available to write it down like I can use it directly on MPLAB. Thanks! \$\endgroup\$
    – Mssc
    Commented Apr 16, 2016 at 13:45
  • \$\begingroup\$ @Mssc Sorry, I'm right in the middle of finishing up a PCB layout project this weekend (I'm not usually at work at 7 am on a Saturday morning). Instead of trying to implement my code directly, take away the concepts from it -- using a state machine, looking for the change of state of the input in one state, then wait while that input says the same for a given number of counts in another state, etc. Depending on how noisy your inputs are, you may need to wait for 50 ms instead of 10 for example. \$\endgroup\$
    – tcrosley
    Commented Apr 16, 2016 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.