A novice, I'm testing some simple scripts as I learn Arduino C basics. The following works after a fashion but is obviously unreliable due to noise (contact bounce) when I touch the wire to ground. What is the simplest way to fix that please?
And is my basic code OK or is there a better way of 'toggling' a pin?
// 'TOGGLE' is intended to toggle an LED On/Off by taking pin 7 low
// That's done manually by briefly touching a connecting wire from pin 7 to ground
// It works unreliably due to contact bounce. How best to fix that?
const int triggerPin = 7;
const int buzzPin = 8;
const int delayPeriod = 250;
void setup()
{
pinMode(triggerPin, INPUT_PULLUP); // So normally H
pinMode(buzzPin, OUTPUT); // LED not a buzzer
}
void loop()
{
if (digitalRead(triggerPin) == LOW)
{
// That manual momentary LOW activates the LED
digitalWrite(buzzPin, HIGH);
// LED should now remain ON until toggled off manually
}
// Pin 7 will quickly return HIGH after momentary HIGH
// Now want to toggle it OFF by again taking pin 7 LOW
if (digitalRead(triggerPin) == LOW)
{
// A momentary LOW triggers the following
digitalWrite(buzzPin, LOW); // Stop buzzer
}
}
I think the problem there isn't really debounce, it's that loop() repeats many hundreds of times a second.
Imagine what happens when you press the button: triggerPin will stay low for many many iterations of loop, turning the buzzer on and off so fast you might not notice.
The state of the buzzer when you lift your finger from the button will then seem pretty random 50:50 split of on or off.
The solution is, instead of checking for triggerPin being LOW, you check for changes in the state of trigger pin. Use a variable to remember the state, then check the current state against the remembered state. If it moves from HIGH to LOW (or vice versa) you know something important has happened and you can make your sketch do whatever needs doing.
Luckily, the built in de-bounce tutorial shows you how to do this (and debouncing too).
Thanks GypsumFantastic. I'll try that debouncing method using state checking.
However, meanwhile I have succeeded in getting what seems to be reliable operation of the actual more complex sketch. I simplified the sketch in my post but now realise it had no delays in it. Hence the downside you described.
I've shown the working version below, and welcome suggestions for further improvement. By way of background: I've been trying to find a way to use my tiny Polaroid CUBE automatically. It has only a single button and its port for a USB cable serves only for recharging and download of photos and videos to PC. No way to operate it except by its very firm button. So I'm trying a heavy duty solenoid!
// 'CUBE-03-Auto' On PC. Simulates solenoid presses
// to record a video of fixed duration, triggered by taking pin 7 briefly low.
// During testing it also activates LED while video is recording.
const int triggerPin = 7;
const int drivePin = 13; // Built - in LED
const int delayPeriod = 250; // Orig 250
const int videoDuration = 5000; // Orig 5000
const int buzzPin = 8; //Buzzer or LED indicates video recording
void setup()
{
pinMode(triggerPin, INPUT_PULLUP); // So normally H, goes L
pinMode(drivePin, OUTPUT);
pinMode(buzzPin, OUTPUT);
}
void loop()
{
if (digitalRead(triggerPin) == LOW)
{
// A momentary LOW triggers all the following
// Power up by pressing CUBE button for 3 s, say 3100 ms
digitalWrite(drivePin, HIGH);
delay(3100);
digitalWrite(drivePin, LOW); // Release button
delay(delayPeriod); // Brief delay before starting video
// Start video with 2 presses
// Press 1 of 2
digitalWrite(drivePin, HIGH);
delay(delayPeriod);
digitalWrite(drivePin, LOW); // Release button
delay(delayPeriod);
// Press 2 of 2 of 2 presses
digitalWrite(drivePin, HIGH);
delay(delayPeriod);
digitalWrite(drivePin, LOW); // Release button
// After that second press, video starts
// It will record for specified duration and stop
// when button is pressed briefly once and released
// Also want to turn on LED or buzzer indicator
digitalWrite(buzzPin, HIGH);
delay(videoDuration);
digitalWrite(drivePin, HIGH);
delay(delayPeriod);
digitalWrite(drivePin, LOW); // Release button
// Video recording should now have stopped
digitalWrite(buzzPin, LOW); // Stop buzzer
//That stops buzzer/LED
}
// Waiting for another cycle to be triggered
}
I had a similar problem debouncing a button and the JC_Button library saved the day. See Button debouncing questions - Programming Questions - Arduino Forum for the solution I got from some helpful folks.
Thanks Arduino_15. In my case bounce is not the problem and the code I included in post #2 works OK.
you are simply looking to turn a pin on and off when a button is pressed?
there are many different methods to prevent bounce depending on reliability of the button and what you are trying to achieve.
in your case i would just use a timer that wouldn't allow a second press until after it has expired.
this should make your scetch igrore presses that happen microseconds apart.
and give the user time to lift a finger off the button.
i added a very small delay in your loop function so your sketch has some sense of time.
here is one way to insert a timer:
const int triggerPin = 7;
const int buzzPin = 8;
const int delayPeriod = 10;
bool state;
int timer;
void setup()
{
pinMode(triggerPin, INPUT_PULLUP); // So normally H
pinMode(buzzPin, OUTPUT); // LED not a buzzer
}
void loop()
{
if(timer>0){timer--;}
if (digitalRead(triggerPin) == LOW)
{
if(timer==0){
timer=30;//adjust this number
// buttton detected here
// switch the pin to opposite of what is was before
state=!state;
digitalWrite(buzzPin, state);
}}
delay(2);}