Question re debouncing a momentary switch

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am experimenting with a servo and I want to use a momentary switch to select whether the servo turns CCW, turns to center, turns CW or is off. The momentary switch will be connected to an input pin for which the internal pull-up will be enabled; and when the momentary switch is pressed, the pin will be pulled low; when the pin is released the pin will go high again (as a result of the internal pull-up). Each time the momentary switch is pressed the code executed will change as follows:

  • off -> CCW -> center -> CW -> off
I understand that I need to debounce the momentary switch - part of my purpose in this experiment is to learn about debouncing.

I have been looking at the danni's Efficient key debounce code as well as pop_gheorghe's Debouncing buttons code.

If I am understanding danni's code correctly, as written it is not intended to operate with a momentary switch, but instead with an "on/off" switch. Specifically, danni's code "remembers" whether a pin is high or low. So if a high pin is pressed and pulled down, after the requisite debounce interval the LED is toggled and the low state will be "remembered" as the new current state. If that pin subsequently pulled high, after the requisite debounce interval the LED is toggled again and the high state will be "remembered" as the new current state.

In the case of the momentary switch, I want the debounce routine to confirm only a high -> low change in state, not a low -> high change instate. On other words, I want high to always be the current state. So, it seems to me that in order adapt danni's code for a momentary switch, I should clear "key-state" after the debounce routine confirms that the button has been pressed; so that as a default "key-state" is high. If I read and understand pop_gheorghe's code (which seems to be based on the danni's code) correctly, I think that that is what his code is intended to do.

Does my understanding seem correct? Thanks.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

IIRC, Danni's code will always report the debounced state. It remembers the current state so it can debounce the transition to the other state. There is no difference between a momentary switch and a toggle switch. The both go from (for example) high to low to high. In your case, it will report low as long as the switch is pressed and will erturn high once it is released.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Momentary" switches will still bounce, and chances are in both directions.

Generic debouncing code such as mine or danni's are agnostic to the type of switch or input that is being processed. (Well, pretty much agnostic--a read through Ganssle indicates some switches that might bounce for a long long time and the intervals may need to be stretched.) The point is that you run the engine periodically. After each run (normally a few seconds apart) you check for confirmed states or state changes that are pertinent to >>your<< app.

I normally have the current state and one set of "edges" come out of my engine. For some apps I have both sets of "edges". Often I invert the "raw" samples as needed to make all "makes" "active high".

Below are excerpts from an app where the engine makes both rising (key_edge) and falling (key_falling) masks for action.

... debounce engine ...
	key_edge = work & key_current;		// only want "on" transitions
									// Note that edges are NOT saved from one
									// call of this routine to the next --
									// "Use it or lose it."  [Change "=" to "|="
									// to save the edges until explicitly cleared.]
    service_needed_key = (key_edge != 0);	// set the new keypress flag

// Calculate the falling edges.  These will be bits that changed to 0 from the "prev"
//	pass of affirmed 1 bits in key_current, to the current pass.
	key_falling = (key_current ^ prev) & prev;

	return (key_edge);			// new debounced rising edges are 1 bits
...

...mainline check for "falling"
			if ((key_current & INP_CAUSTIC_MASK) == 0)
				{
				// End of cycle
				state = STATE_IDLE;

				// Supress logging for short cycle
				cycling = 0;
				break;
				}

			if ((key_falling & SW_CAUSTIC_MASK) &&
				(tocks_caustic_held < TOCKS_TO_PUMP))
				{
				// Cancel cycle
				cycle_type |= CYCLE_ABORT;	// mark as cancelled
				state = STATE_IDLE;
				break;
				}

...
                else if (key_edge & SW_CAUSTIC_MASK)
                	{
                	// Manual caustic cycle
                	state = STATE_C_TIME;
                		// Start count-down of charge timer
					sec_run_left = reg_caustic_charge_time;
					if (sec_run_left == 0) sec_run_left = 1;
					flg_sec_run_left = 0;
                	}

From the fragments above, you can see that I take actions on the same button on rising, falling, and maintaining a "hold" on the button for time period(s).

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks.

theusch wrote:
The point is that you run the engine periodically. After each run (normally a few seconds apart) you check for confirmed states or state changes that are pertinent to >>your<< app.

Okay. So the debounce code detects both hi->low and low->high changes. If I am only interested in a high->low change, I write my code accordingly, and "ignore the high->low change. Am I understanding this correctly?

Also, with respect to your nomenclature, are:

  • edge ->change of state of key?
  • "rising edge" low->high?
  • "falling edge" high->low?
Thanks, again.

Russ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code is also taking a lot of shortcuts. Like for example you can't push both buttons at the same time. Most likely you don't need that feature either.

But what really bothers me is that when you push a button down, and keep it there, the code runs in an infinite loop, only increasing a variable, and thus can't do anything else. Maybe it does not need to, so that is fine by me. But, it may happen that you press the button just about the right length, and the counter overflows (65535->0) and when you release it, it is again less than the threshold. No push detected.