CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

General advice - first time programmer
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Wed Aug 07, 2024 1:25 pm     Reply with quote

Yep yep, that's fine, I wasn't really addressing that part as it was already covered in previous discussion. I was just letting the OP know that the statement I highlighted earlier was not fully correct for that family they were using.
reelthymes



Joined: 26 Jul 2024
Posts: 21

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 6:56 am     Reply with quote

Ttelmah wrote:
You are right on this chip. On most chips they are not relocatable.
However using the interrupts, you will have problems with bounce.
Understand they a simple keyboard may well give a dozen or more
makes when a key is pushd. It depends massively. on the quality of
the contacts, and how the user pushes the key


So is bounce not an issue when using an "input change notification" (CN) pin? As for debounce in general, can't that simply be handled in the software, i.e. you sample the input at some interval and consider the signal stable if it's consistent across intervals?

Would this software debounce method work for either pin type (external interrupt or CN input)?
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 11:25 am     Reply with quote

To debounce a switch input you would not use an external interrupt or a change interrupt at all. Just poll the pin input at a regular interval and look for a stable change of state.
An interrupt on a switch would only be useful if you need to wake from sleep on a switch press.
reelthymes



Joined: 26 Jul 2024
Posts: 21

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 12:58 pm     Reply with quote

gaugeguy wrote:
To debounce a switch input you would not use an external interrupt or a change interrupt at all. Just poll the pin input at a regular interval and look for a stable change of state.
An interrupt on a switch would only be useful if you need to wake from sleep on a switch press.


Ok, thanks this is is helpful. So in this case, if I were to simply poll the pin input at regular intervals, doesn't this risk being unresponsive or slow because now it's part of my main program loop? i.e. the polling action may have to wait for many other actions to complete before being reached... whereas a change notification interrupt would be immediate?

I also thought that was the general point and application of interrupts. i.e. they exist to make your program respond immediately to some event (usually some external stimulus).

Or I suppose as Ttlemah previously stated, I could use a timer interrupt?
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 1:25 pm     Reply with quote

Not in a properly written program.
10ms is a long time from a microprocessors view.
200ms is a short time from a human response view.
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 1:43 pm     Reply with quote

reelthymes wrote:

Or I suppose as Ttlemah previously stated, I could use a timer interrupt?


That's also an option. I have a few programs where I have a spare interrupt running that takes a 16 bit variable, shifts it left one bit and OR's in the input of the pin in question. Then in my main code , I look to see if the pin is debounced high (variable = 0xFFFF), debounced low (variable = 0x0000, or in transition (an other value).

Something like (untested, just typed out freehand)

Code:

#define PIN_LOW 0x0000
#define PIN_HIGH 0xFFFF
volatile unsigned int16 g_PIN_B6_debounce = PIN_LOW; 

#INT_TIMER5
void debounce_timer(){
   g_PIN_B6_debounce = (g_PIN_B6_debounce << 1) | input_state(PIN_B6);
}

void main(void){
   static unsigned int16 last_PIN_B6 = PIN_LOW;  // assuming initial state

   // setup timer 5 to some reasonable debounce time

   while(TRUE){
      if(last_PIN_B6 == PIN_LOW && g_PIN_B6_debounce == PIN_HIGH){
         last_PIN_B6 = PIN_HIGH;
         //rising edge processing
      }
      if(last_PIN_B6 == PIN_HIGH && g_PIN_B6_debounce == PIN_LOW){
         last_PIN_B6 = PIN_LOW;
         //falling edge processing
      }
      // ignore other values of B6 until it debounces to a known value
   }

}
reelthymes



Joined: 26 Jul 2024
Posts: 21

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 1:58 pm     Reply with quote

jeremiah wrote:
reelthymes wrote:

Or I suppose as Ttlemah previously stated, I could use a timer interrupt?


That's also an option. I have a few programs where I have a spare interrupt running that takes a 16 bit variable, shifts it left one bit and OR's in the input of the pin in question. Then in my main code , I look to see if the pin is debounced high (variable = 0xFFFF), debounced low (variable = 0x0000, or in transition (an other value).

Something like (untested, just typed out freehand)

Code:

#define PIN_LOW 0x0000
#define PIN_HIGH 0xFFFF
volatile unsigned int16 g_PIN_B6_debounce = PIN_LOW; 

#INT_TIMER5
void debounce_timer(){
   g_PIN_B6_debounce = (g_PIN_B6_debounce << 1) | input_state(PIN_B6);
}

void main(void){
   static unsigned int16 last_PIN_B6 = PIN_LOW;  // assuming initial state

   // setup timer 5 to some reasonable debounce time

   while(TRUE){
      if(last_PIN_B6 == PIN_LOW && g_PIN_B6_debounce == PIN_HIGH){
         last_PIN_B6 = PIN_HIGH;
         //rising edge processing
      }
      if(last_PIN_B6 == PIN_HIGH && g_PIN_B6_debounce == PIN_LOW){
         last_PIN_B6 = PIN_LOW;
         //falling edge processing
      }
      // ignore other values of B6 until it debounces to a known value
   }

}


That looks like a great solution, thanks for sharing.
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Thu Aug 08, 2024 2:03 pm     Reply with quote

reelthymes wrote:

That looks like a great solution, thanks for sharing.


No problem. If you find the interrupt takes too much time you can simplify the generated code at the cost of a less readable solution:

Code:

#INT_TIMER5
void debounce_timer(){

   #BIT B6_BIT = g_PIN_B6_debounce.0;

   g_PIN_B6_debounce = g_PIN_B6_debounce << 1;
   B6_BIT = input_state(PIN_B6);
   
}


That reduces the generated ASM quite a bit. That takes the generated code down to:
Code:

....................    #BIT B6_BIT = g_PIN_B6_debounce.0;
....................
....................    g_PIN_B6_debounce = g_PIN_B6_debounce << 1;
020E:  SL      800
....................    B6_BIT = input_state(PIN_B6);
0210:  BCLR.B  800.0
0212:  BTSC.B  2CA.6
0214:  BSET.B  800.0


You can also change the 16 bit global to an 8 bit global (and the constants) if you think you only need 8 debounce attempts
reelthymes



Joined: 26 Jul 2024
Posts: 21

View user's profile Send private message

PostPosted: Fri Aug 09, 2024 9:26 am     Reply with quote

Quote:

Code:


void main(void){
   static unsigned int16 last_PIN_B6 = PIN_LOW;  // assuming initial state

   // setup timer 5 to some reasonable debounce time

}


regarding setting up the timer period, please see my below reasoning. Can you let me know if I'm in the ballpark or is this totally off-base?

I have the following line in the setup portion of my main() function:
Code:
setup_timer_1(TMR_INTERNAL, 0x0148));


Here is the logic behind this:

1) The PIC24 has an 8 MHz internal clock. That means the period of each clock cycle is 0.125 us.

2) The 16 bit timer has max value of 0xFFFF (65,535), which means that 8*10^6 / 65535 = 122. This is the number of cycle count per bit of the timer.

3) Therefor, each bit of the timer represents (122 * 0.125 us) = about 15 us

4) so, for a (I think reasonable?) period of 5 ms for my interrupt, I should set the period value of ( 5ms / 15 us = 328). In other words, 328 (0x148).

5) so, the interrupt will fire every 5 ms, and we keep going until the g_PIN_doubounce variable is filled up with all 1s (0xFFFF). So this will occur at approx. 75 ms because (5 ms * 16 = 75 ms). i.e. if I understand your algorithm correctly, inside the interrupt we OR the pin HIGH input with that variable and keep shifting left until the whole thing is filled up. So that means 16 passes through the interrupt routine to ensure a stable signal.

Lastly, is there a reason you recommended timer 5 as opposed to one of the others?
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Fri Aug 09, 2024 5:57 pm     Reply with quote

reelthymes wrote:


regarding setting up the timer period, please see my below reasoning. Can you let me know if I'm in the ballpark or is this totally off-base?

I have the following line in the setup portion of my main() function:
Code:
setup_timer_1(TMR_INTERNAL, 0x0148));


Here is the logic behind this:

1) The PIC24 has an 8 MHz internal clock. That means the period of each clock cycle is 0.125 us.

2) The 16 bit timer has max value of 0xFFFF (65,535), which means that 8*10^6 / 65535 = 122. This is the number of cycle count per bit of the timer.

3) Therefor, each bit of the timer represents (122 * 0.125 us) = about 15 us

4) so, for a (I think reasonable?) period of 5 ms for my interrupt, I should set the period value of ( 5ms / 15 us = 328). In other words, 328 (0x148).

5) so, the interrupt will fire every 5 ms, and we keep going until the g_PIN_doubounce variable is filled up with all 1s (0xFFFF). So this will occur at approx. 75 ms because (5 ms * 16 = 75 ms). i.e. if I understand your algorithm correctly, inside the interrupt we OR the pin HIGH input with that variable and keep shifting left until the whole thing is filled up. So that means 16 passes through the interrupt routine to ensure a stable signal.

Lastly, is there a reason you recommended timer 5 as opposed to one of the others?


I wasn't intending to suggest timer 5 specifically. It was more just for example. On most (all???) PIC24FJ chips, timer 1 is the only timer with an asynchronous input, so we reserve that one for our external 32KHz crystal in order to wake our boards up from full sleep using a timer (other timers normally cannot do this). I just picked a timer at random for the example.

In terms of your timing, I would always recommend you toggle an I/O line using the timer interrupt and measure it on a scope to verify the timing and your clock settings. PIC24's divide the incoming clock by 2x so the 8 MHz would be 4 MHz (unless your clock is really 16 MHz, then it would be 8MHz). (SIDE NOTE: PIC18s and below divide the clock by 4x).

You are correct about my algorithm that it takes 16 passes (due to the unsigned int16 type). And my algorithm does wait until all 16 are 1's but also makes sure the last time it was full it was all 0's before (essentially a rising edge). That way the stuff in the IF only triggers once until the logic goes low 16 times and then high 16 times again (so a falling edge followed by a rising edge). Hopefully that makes sense.
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Aug 09, 2024 6:59 pm     Reply with quote

One potential issue with software debounce is that you've got it working perfect with brand x, style 3 switches then.... have to buy brand k, style 1 switches, which of course have a totally different debounce 'action'.
You can lose a lot of time over this head scratcher....really, all switches are the same , right ????

I learned decades ago to spend a few pennies in hardware to get solid,clean signals. Usually 'hard' pullups, 1mfd filter caps, schmitt(sp) buffers. In automotive products ,used 5V regulators as +12 to +5 level converters. Boss said that adds cost but SAVED money as NO defective boards due to 'front end' damage.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sat Aug 10, 2024 1:44 pm     Reply with quote

and (of course), switches that are fine when you build the unit, then
give bounce problems in the future, or when a different person uses the
key.... Sad
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group