Push button, hold it down, but only send message once

Hi!

Im trying to make a push button send only one message, even if it is held down for a long time. So i need to detect the pushbutton changes state, and then not send the message that it is HIGH for more than one time. Right now, it sends contious 1:s when i hold down the button, and i want it to send one and then stop, and only send one more if the button is released and pushed down again.

Best
//Maria

Post your code in code tags.

Have a look at the state change detection example that comes with the IDE.

1 Like

I have tried to figure out how to use state change detection but i dont want it to turn anything on, but rather to only send one impulse and then no more even if the button is stll pressed. I am creating a musical instrument where a button is supposed to work as a kind of drum, so the sound should only play once even if the player still holds down the button.

int count = 0;

const int buttonPin1 = 2; // the number of the pushbutton pin
const int buttonPin2 = 3;

// variables will change:
  int buttonState1 = 0; 
  int buttonState2 = 0;         // variable for reading the pushbutton status


void setup() {
   Udp.begin(8080);

  //Initialize serial and wait for port to open:
  Serial.begin(9600);

// initialize the pushbutton pin as an input:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);

}




void loop() {



   // read the state of the pushbutton value:
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
 

Where is your attempt to add in the only send once code?

The code won't compile as posted.

1 Like

Take a look at the aptly named StateChangeDetection example in the IDE

1 Like

Hello. I just did something like that for a solenoid project I want to do. I hope this code helps.

define Switch 0
#define Led 1
unsigned long TimerLed;
int estado;
int estadoAnterior=LOW;

void setup() 
{
  pinMode(Switch, INPUT);
  pinMode(Led, OUTPUT);
}

void loop()
{
 estado=digitalRead(Switch);
 delay(50);

 if (estado==HIGH && estadoAnterior==LOW)
 {
  TimerLed=millis();
  digitalWrite(Led,HIGH);
  while (millis()<TimerLed+50) {delay(1);}
  estadoAnterior=HIGH;
  digitalWrite(Led,LOW);
 }

 if (estado==LOW && estadoAnterior==HIGH) { estadoAnterior=LOW; }

}

It's Portuguese but "estado" is state and estadoAnterior is PreviousState. Hope it will make sense to you.

1 Like

led lights one time at button push

#define Switch 9
#define Led 3
unsigned long TimerLed;
int estado;
bool estadoAnterior = LOW;
bool triggeredOnce = HIGH;
void setup() 
{
  pinMode(Switch, INPUT);
  pinMode(Led, OUTPUT);
}

void loop()
{
 estado=digitalRead(Switch);
if(estado && triggeredOnce)
 {
  TimerLed=millis();
  digitalWrite(Led,HIGH);
  delay(1000);
  digitalWrite(Led,LOW);
  triggeredOnce=LOW;
 }

}

Your defined switch and led pins are the wrong ones to use.

Use the File/Examples/StateChangeDetection example. Your message action will work in the same way, but since it's a one-time thing itself, you could think of it as turning itself off. It sounds like your task is almost identical to the task of reporting on the button press like this section in the below:

      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
      //sendMiaSvanMessage("button pressed");

Put your message sending code into a void sendMiaSvanMessage(const char * msg){...} function, or replace it with your code and it should work.

/*
  State change detection (edge detection)

  Often, you don't need to know the state of a digital input all the time, but
  you just need to know when the input changes from one state to another.
  For example, you want to know when a button goes from OFF to ON. This is called
  state change detection, or edge detection.

  This example shows how to detect when a button or button changes from off to on
  and on to off.

  The circuit:
  - pushbutton attached to pin 2 from +5V
  - 10 kilohm resistor attached to pin 2 from ground
  - LED attached from pin 13 to ground through 220 ohm resistor (or use the
    built-in LED on most Arduino boards)

  created  27 Sep 2005
  modified 30 Aug 2011
  by Tom Igoe

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/StateChangeDetection
*/

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
      //sendMiaSvanMessage("button pressed");
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by checking the modulo of the
  // button push counter. the modulo function gives you the remainder of the
  // division of two numbers:
  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

Use the attachInterrupt function: attachInterrupt() - Arduino Reference

Assuming your button is pull-down and it will raise the logic to high when pressed, just use

attachInterrupt(digitalPinToInterrupt(buttonPin), your_function, RISING);

This will always call the function named "your_function", just once, every time you push the button and no matter how long you are keeping the button pushed.

You must try to understand the idea behind it, not follow it literally. The important part is

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // do YOUR stuff here

I've added the additional comment agter the last if.

1 Like

Or don't. There is absolutely no reason to add interrupt service routines to the problem @miasvahn is trying to solve.

a7

Thank you Robert, the interrupt did the trick!

it worked though! :smiley:

It's hard to argue with success!

I'm sure everything you "learned" here today will stand you in good stead as you go forward!

a7

1 Like

It did for now.

Do you propose to use the same Arduino to do anything else in addition in the future?

In the spirit of cooperation @miasvahn please post your solution for others to benefit.

2 Likes

@alto777 using interrupts for buttons is the best way to do it. If you don't, then you must do some more reading.

Yet, the prevailing sentiment on this forum is that polling and state change detection are better. I personally have no significant leaning either way, but am keen to hear the arguments for and against each method.

It simply depends on what needs to be done.