Short-to-ground type button help

I've managed to fry a pin using my short-to-ground type button improperly (it is an adafruit joystick). I intend to use it in a fashion that when pressed, changes a state. I am looking to find a correct tutorial on the use of this type of button, so I can understand why this may of happened and use it properly.

Cheers

Basically, wire the switch from GND to whatever pin you want, then use pinMode(pin_number, INPUT_PULLUP); so that the pin is pulled up to +5V when the switch is not pressed.

See Nick Gammon's excellent switch tutorial at Gammon Forum : Electronics : Microprocessors : Switches tutorial.

You didn't say how you fried the pin, but there's really only one way to do that with a switch connected between GND and a pin, with no external resistor, and that is to set the pin to output and write a 1 (HIGH ) to it.

Thanks for that. I re-checked the pin (D3) I thought I damaged and it is functioning as it should. Following Gamons' tutorial I now understand how to get the switch on D3 working to turn the D13 LED on and off.

My next progression is to attach an interrupt to the switch. I have tried various code, below is the simplest example I have used, and it is still not working for me. I understand interrupts can be tricky, but this seems straight forward, so I am obviously missing something.

const int ledPin = 13;
const int buttonPin = 3;

volatile int state = LOW;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(buttonPin, blink, LOW);
}

void loop()
{
  digitalWrite(ledPin, state);
}

void blink()
{
  state = !state;
}

lazaah:
My next progression is to attach an interrupt to the switch. I have tried various code, below is the simplest example I have used, and it is still not working for me. I understand interrupts can be tricky, but this seems straight forward, so I am obviously missing something.

const int ledPin = 13;

const int buttonPin = 3;

volatile int state = LOW;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(buttonPin, blink, LOW);
}

void loop()
{
  digitalWrite(ledPin, state);
}

void blink()
{
  state = !state;
}

attachInterrupt() takes an int number, not a pin number as its first argument. pin 3 is INT1. See the Reference section at Arduino - Home for the attachInterrupt() documentation.

attachInterrupt() takes an int number, not a pin number

At least on most boards. Which Arduino do you have ?

The advice to read Arduino - AttachInterrupt is sound. Read it and use the information pertinent to your board.

Even when you get the attach interrupt right and wire the button to the correct pin the code will not work like you think. Change the interrupt trigger from low to change. You will still have trouble with contact bounce though.

Thanks. I had been referencing that page, but got mixed up thinking I was mean't to specify the pin for the first parameter. I assume a software de-bounce is sufficient, and will use RISING rather than low. Will rewrite in the morning.

Is setting the internal pull-up necessary?

I assume a software de-bounce is sufficient

The debounce will have to be inside the ISR.

The internal pull up setting depends on how you wire the switch. If it is to ground with no external resistor then yes you need it.

would a 0.1uF capacitor on my GND (possibly) negate the need for the software de-bounce inside the ISR, or do I have the wrong idea of what capacitors and hardware de-bouncing?

A capacitor can provide some form of debouncing it depends on yor specific type of switch. Basically try it and see if you run into trouble.

Grumpy_Mike:

I assume a software de-bounce is sufficient

The debounce will have to be inside the ISR.

Actually, it could be done outside the ISR, by using a global variable holding a millis() value, assigned within the ISR, but read/tested in loop(). The idea would be the same as a debounce within loop(), and without interrupts; just that it would be done 'second hand', using (mostRecentInterruptTime - millis) >= debounceDuration, and of course, checking to ensure the switch is still in the appropriate state.

assigned within the ISR

So in what way is that outside the ISR?

Grumpy_Mike:

assigned within the ISR

So in what way is that outside the ISR?

In the way that you just set a variable for the last millis() value and return. Within loop() you decide when the switch is sufficiently debounced. This is as opposed to doing the duration calculation and making the decision within the ISR.

Read the bit where it says that millis() won't work inside your interrupt service function, because millis() itself depends on interrupts and you can only have one interrupt at a time.

michinyon:
Read the bit where it says that millis() won't work inside your interrupt service function, because millis() itself depends on interrupts and you can only have one interrupt at a time.

Read the bit where it says that millis() cannot have a value inside an ISR. Can't find it? What a shame.

It does have a value. It just doesn't increment. You can ALWAYS read the current value of millis() and micros(), inside or outside an interrupt.