Free Button Lib w/Example with BUTTON ARRAY UPDATE below.

There are 3 files to put in the project folder you will need to make in your Sketchbook attached below. — update, get the newer versions posted farther down and you can make button arrays.

The library takes care of contact debouncing and tracking changes of state. It runs the button and your sketch can get non-blocking meaningful status replies to read calls. If all you care about is when a switch was just thrown then you just if() for just ON and just OFF and ignore the rest.

Here’s the example set for pin 2 and a long 20ms debounce, my switch is a jumper touching flat
metal. The contact is ‘dirty’. If the pin slides, it falses badly. Otherwise you can see how fast you
tap, serial monitor shows last stable state and time as millis. Subtract millis() to get interval.
I can tap pressed to released in under 100ms with a jumper pin on the USB connector box.

/* buttonclass example -- by GoForSmoke 2015 for public domain use

  This uses a button or switch or jumper from pin 2 to GND.
  Depending on switch, debounce value may need tuning.

  Button output is a state value for use in the main sketch code.
  -1, Undecided, pin state changed at least debounce-time ago.
  0, button currently still not pressed.
  1, button currently still pressed.
  2, button released since last checked by sketch.
  3, button pressed since last checked by sketch.

  The main sketch may need to track previous output state for real dirty
  switches. A clean switch can work with 3 ms debounce. I use 20 here.
*/

#include "Arduino.h"
#include "buttonlib.h"

//   THIS IS WHERE YOU SET SWITCH PIN NUMBER AND DEBOUNCE MILLIS
buttonclass  user( 2, 20U ); // pin # and debounce ms get compiled to flash, U is unsigned.

const byte ledpin = 13;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( F( "\n  Startup\n" ));

  pinMode( ledpin, OUTPUT ); // default is INPUT LOW, now is OUTPUT LOW
}

void loop()
{
  static byte buttonRead; // allocated once, used often

  user.runButton(); // turns the crank once per loop(), make sure it runs often!

  // now using button data to change blink rate
  buttonRead = user.readOutput();

  if ( buttonRead == 3 ) // 1st read since pressed
  {
    digitalWrite( ledpin, HIGH );
    Serial.print( F( "button pressed millis() == " ));
    Serial.println( millis());
  }
  else if ( buttonRead == 2 )
  {
    digitalWrite( ledpin, LOW );
    Serial.print( F( "button released millis() == " ));
    Serial.println( millis());
    Serial.println( );
  }
}

buttonexample.ino (1.84 KB)

buttonlib.h (1.22 KB)

buttonlib.cpp (1.52 KB)

Thanks GoForSmoke, i will try it out.

You really should give up smoking.

LarryD: Thanks GoForSmoke, i will try it out.

You really should give up smoking.

This is the smoke of hairline traces on reject boards under a few Amps of 12V.

It's also for wiring something up when I'm not so sure and give it power anyway.

I've done an IR led and a 4x20 LCD in the last 4 years. The led made a strange smelling smoke.

I try not to smoke parts, only flux.

Note that you can make multiple button objects, each with pin and debounce. I need to run a test about button arrays, might need to add to the lib.

Now with button arrays.
Example shows how to process only ONE button per loop().
That keeps large numbers of buttons from geometrically slowing loop() down.
This example is ready to incorporate more tasks.

Make sure you get the attached new class files

/* buttonarrayclass example -- by GoForSmoke 2015 for public domain use

  This uses 2 buttons or switches or jumpers for pins 2 & 3 to GND.
  Depending on switch, debounce value may need tuning.

  Button class object output is a state value for the main sketch code.
  -1, Undecided, pin state changed at least debounce-time ago.
  0, button currently still not pressed.
  1, button currently still pressed.
  2, button released since last checked by sketch.
  3, button pressed since last checked by sketch.

  The main sketch may need to track previous output state for real dirty
  switches. A clean switch can work with 3 ms debounce. I use 20 here.
*/

#include "Arduino.h"
#include "buttonlib.h" // check for newest

const byte howManyButtons = 2;
byte buttonIdx;
buttonclass user[ howManyButtons ];

const byte ledpin = 13;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( F( "\n  Startup\n" ));

  pinMode( ledpin, OUTPUT ); // default is INPUT LOW, now is OUTPUT LOW
  
  for ( buttonIdx = 0; buttonIdx < howManyButtons; buttonIdx++ )
  {
    user[ buttonIdx ].setButton( 2 + buttonIdx, 20UL );
  }
  buttonIdx = 0;
}

void loop()
{
  static byte buttonRead; // allocated once, used often

  user[ buttonIdx ].runButton(); // turns the crank once, make sure it runs often!

  buttonRead = user[ buttonIdx ].readOutput();

  if ( buttonRead == 3 ) // 1st read since pressed
  {
    digitalWrite( ledpin, HIGH );
    Serial.print( F( "button " ));
    Serial.print( buttonIdx );
    Serial.print( F( " pressed millis() == " ));
    Serial.println( millis());
  }
  else if ( buttonRead == 2 )
  {
    digitalWrite( ledpin, LOW );
    Serial.print( F( "button " ));
    Serial.print( buttonIdx );
    Serial.print( F( " released millis() == " ));
    Serial.println( millis());
    Serial.println( );
  }
  
  buttonIdx ^= 1;
}

buttonarrayexample.ino (1.8 KB)

buttonlib.h (1.33 KB)

buttonlib.cpp (1.84 KB)