AnalogDebounce: New Library for debouncing Analog Keypads

I have a fairly complex project I am working on and I wanted to clean up the code and make some of it re-usable in the form of libraries. One of those libraries is AnalogDebounce, a library for debouncing button keypads that utilize voltage division and analog input for single pin operation. I could not find a single library or example for it so I made my own!

You can get the library at GitHub - MatCat/AnalogDebounce: Arduino Debounce Library for voltage divided keypads.

It will work out of the box for shields such as Cytron LCD and Keypad shield, or the SainsSmart (Which I think is identical? to the Cytron one).

As I work on the library I will keep the GIT repo up to date and announce changes here.

I updated the library today with the following:

int minPressTime - Miliseconds to consider before calling it a press
int repeatDelay - Miliseconds to wait before firing a button press again while still being held down.

Also added relevant keywords context as well.

Thanks for sharing your library!

in your code you hard code the inner array.

    adc_key_val[0] = 30;
    adc_key_val[1] = 160;
    adc_key_val[2] = 360;
    adc_key_val[3] = 550;
    adc_key_val[4] = 780;

It would be nice if I could give an array of the resistor values and that the constructor calculated the internal key_values.

something like this ...

AnalogDebounce::AnalogDebounce(byte pin,button_callback f, int count, int * resistorArray) // assuming all values in same unit KOhm
{
  uint16_t sum = 0;
  for( int i=0; i< count; i++) 
  {
    sum += resistorArray[i];
  }
  uint16_t partial = 0;
  for(int i=0; i< count; i++)
  {
    partial += resistorArray[i];
    adc_key_val[i] = (partial * 1024) / sum;  // partial might need an initial correction factor
  }
   etc...

It is a bit more code but the user only has to fill in the resistors used. No magic numbers :slight_smile:

What do you think of this idea?

minPressTime = 70;
repeatDelay = 150;

These magic numbers should appear in the constructor interface too, with above mentionaed as default.
Or be a property of the class imho.

just thinking out loud ..

The minPressTime and repeatDelay are properties of the class.

As far as specifying the resistors that is interesting... I will have to experiment around with the idea and see if it would work well. I do want to make it easier to specify buttons and values beyond the standard set now.

I do appreciate the feedback!

I want to share a thought but, I will have to use an example to do it.

I have a Olimex STM 32 (LeafLabs Maple clone) and the counts are different when using analog buttons in comparison to the Arduino Uno. To use the DFRobot sketches, I had to adjust the values by testing each button with the serial monitor showing the analogRead results. This is because of the higher bit resolution of the analogRead.

That being said, to be able to port the library to other boards such as the Due, you may need a way to work with a spread of analogRead results.

Indeed you are correct, the current defaults are based on a 10bit ADC, though really once you set it up you could do button.adc_key_val[0-4] = whatever.

I am going to figure out a much better way to handle the number of buttons and different resistor values.

using the resitor values will work

Quick python sketch shows it can be done quite easily (C++ will need array size parameter)

def analogValues(resistors):
	"""
	builds a list of values for analogRead() based upon resistor values
	"""
	sum = 0
	for val in resistors:
		sum += val
	partial = 0
	av = [0]
	for val in resistors:
		partial += val
		# print partial, (partial * 1023) / sum
		av.append( (partial * 1023) / sum)
	return av

def findClosestIndex(val, values):
	"""
	finds the index in values that matches val best
	"""
	min = val
	idx = 0
	for i in range(len(values)):
		dist = abs(val-values[i])
		if (dist < min):
			min = dist
			idx = i
		# print dist
	return idx

#
# prog starts here
#
resistors = [100,400,100,200,400,300,400,100,200,400,300,100]
av = analogValues(resistors)
print av

for i in range(103):
	val = i * 10
	idx = findClosestIndex(val, av)
	print val, idx, av[idx], abs(val-av[idx])

findClosestIndex() can be optimized by stopping the search when the distance rises again (~ factor 2)

1023 in the code is a hard coded max value of the ADC; could be a parametrized.

I hate to ask a stupid question, but can you give me a schematic or wiring diagram for how to hook up the wires to uses your library. I have seen a couple of different ways to do it online, and have not gotten one to work. I feel like a reference would be handy to go along with the library. Thanks in advance.

Are you asking for the schematic for the button/voltage divider such as that found on an LCD arduino shield like sainsmart?
How about this: 1602schem.1

Mark S.

Hi MatCat, I want to try your solution, but get stuck in your "Basic use" example, with error:

Arduino:1.8.5 (Windows 10), Tarjeta:"Arduino/Genuino Uno"

BasicUse:3: error: 'ButtonPush' was not declared in this scope

AnalogDebounce Buttons(A0,ButtonPush); // Analog Input 0,

^

exit status 1
'ButtonPush' was not declared in this scope

Any sugestion will be appreciated.

Thanks for your work and time.