How to toggle pin state only once

Hello, recently i wrote this code which every time you press the button, the pin state will be ON or OF, here's the code:

if ( Fstat == LOW ) //If F key pressed
{
  digitalWrite(Fan, !digitalRead(Fan)); //Invert the Fan relay State
}

The problem is when you press the button, if you keep pushing it, it will toggle the pin state as fast as Arduino can read the code, I cant describe it good but you know what I mean.
What I want is to toggle the pin state only once after I pressed the button and then toggle again when I released the button, and pressed it again.

How should I do it?

(sorry I still feel I didn't said what I wanted good, but ask me where you didn't understand)

You need to detect when a button becomes pressed, not when it is pressed.

In the Arduino IDE there is an example of this, look for state change detection:
File/examples/02.Digital/StateChangeDetection.

Is that the only way? I mean... about 40 lines of code for this will make the sketch very big and complicated and now I have 5 buttons in my project so I'll need 15 variables just for button,
Is there a way to put all these in a function? or anyway to reduce the amount of code.

Its ok for small sketches but right now I already used 75% of Micro controller program storage and if I want to do this method I should add about 200/250 more lines to it...

If you only want something to hapen once, just use a variable to keep track.

compiles, untested - just the idea here:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

bool justOnce = false;

void loop() {

  if (!justOnce) {
    doThisOneThing();	// whatever

    justOnce = true;	// did it!
  }
}

void doThisOneThing()
{
    Serial.println("I did it!");
}

Your problem then becomes one of when and whether to reset justOnce to flase, which will allow the if statement to be true again and do the thing again.

HTH

a7

Is that the only way? I mean... about 40 lines of code for this will make the sketch very big and complicated and now I have 5 buttons in my project...

No, there's as many ways are there are programmers inventing new ways. Here is another way, this code is for 4 buttons but could be adapted for more if required. It's not the only way, it's unlikely to be the best way, but it works.

/* Simple button debounce for 4 buttons. Increments a count and sends the updated count to the serial monitor once per button press */
/* Tested on an Uno */
/* Connect simple push to make buttons between 0V and pin 2, 0V and pin 3, 0V and pin 4 and between 0V and pin 5 */

#define noOfButtons 4     //Exactly what it says; must be the same as the number of elements in buttonPins
#define bounceDelay 20    //Minimum delay before regarding a button as being pressed and debounced
#define minButtonPress 3  //Number of times the button has to be detected as pressed before the press is considered to be valid

const int buttonPins[] = {2, 3, 4, 5};      // Input pins to use, connect buttons between these pins and 0V
uint32_t previousMillis[noOfButtons];       // Timers to time out bounce duration for each button
uint8_t pressCount[noOfButtons];            // Counts the number of times the button is detected as pressed, when this count reaches minButtonPress button is regared as debounced 
uint8_t testCount[noOfButtons];             //Test count, incremented once per button press

void setup() {
  uint8_t i;
  uint32_t baudrate = 115200;
  Serial.begin(baudrate);
  Serial.println("");
  Serial.print("Serial port connected: ");
  Serial.println(baudrate);
  for (i = 0; i < noOfButtons; ++i) {
    pinMode(buttonPins[i], INPUT_PULLUP);
    Serial.print("Testcount ");
    Serial.print(i);
    Serial.print(" = ");
    Serial.println(testCount[i]);
  }
}

void loop() {
  debounce();
  delay(10);     //Your other code goes here instead of this delay. DO NOT leave this delay here, it's ONLY for demonstration.
}

void debounce() {
  uint8_t i;
  uint32_t currentMillis = millis();
  for (i = 0; i < noOfButtons; ++i) {
    if (digitalRead(buttonPins[i])) {             //Input is high, button not pressed or in the middle of bouncing and happens to be high
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        pressCount[i] = 0;                        //Set the number of times the button has been detected as pressed to 0
      } else {
      if (currentMillis - previousMillis[i] > bounceDelay) {
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        ++pressCount[i];
        if (pressCount[i] == minButtonPress) {
          doStuff(i);                             //Button has been debounced. Call function to do whatever you want done.
        }
      }
    }
  }
}

// Function to do whatever you want done once the button has been debounced.
// In this example it increments a counter and send the count to the serial monitor.
// Put your own functions here to do whatever you like.
void doStuff(uint8_t buttonNumber) {
  ++testCount[buttonNumber];
  Serial.print("Button ");
  Serial.print(buttonNumber);
  Serial.print(" testcount = ");
  Serial.println (testCount[buttonNumber]);
}

Setrik_aZ:
I mean... about 40 lines of code for this will make the sketch very big and complicated and now I have 5 buttons in my project so I'll need 15 variables just for button,
Is there a way to put all these in a function? or anyway to reduce the amount of code.

Yes, the answer is to make a button class. It's already been done many times in the many available button libraries.

Regarding your 75% memory, maybe there are ways that you aren't aware of, to make it smaller. If you post your entire sketch, you can get help with that.

Setrik_aZ:
Is that the only way? I mean... about 40 lines of code for this will make the sketch very big and complicated and now I have 5 buttons in my project so I'll need 15 variables just for button,
Is there a way to put all these in a function? or anyway to reduce the amount of code.

The only code you need is

  if ((buttonState = digitalRead (buttonPin)) != lastButtonState) 
  {
    if (buttonState)
      toggle (...) ;
    delay(50);
  lastButtonState = buttonState;
  }

And just change the variables to arrays of 5 if you have 5 buttons.
[/quote]

This could help with the program size issue.

Maybe this is interesting for you?

Once I had the same problems / questions and after a while I found this, which could save you some time developing something that already exists.

I have done it with 16 buttons just using a few arrays

uint8_t buttonPin[16]  = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};//array of button pins
uint8_t buttonState[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};     //array of button states
uint8_t previousButtonState[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};//array of button states
unsigned long buttonPressStart [16];                          //array of press start times for each button
unsigned long buttonPressTime [16];                          //array of press times for each button

MarkT:
The only code you need is

...

delay(50);
...

Some peripherals need to be serviced more often than every 50ms., this will work for most but not all sketches unless it's modified to use millis() for timing.

This thread may be helpful for you: Issue with the Control Surface Library and 3pdt switches - #3 by grapher456 - Audio - Arduino Forum

aarg:
Some peripherals need to be serviced more often than every 50ms., this will work for most but not all sketches unless it's modified to use millis() for timing.

I'm actually using the same method and the problem is not only that it'll mess with some other things like 7 segments (hopefully I don't have them in my project they're such a cancer to work with!) but it will just add a denouncing effect to the button, and like if there is a total 300ms delay in your sketch, the output will toggle every 300ms if you hold the button.

If you post your entire sketch, you can get help with that.

yes i need help with that, but guess i should do it in another topic... its not related to this one

Well actually the first method that is very easy to use I dont know why i thought it may make the code complicated.
I changed it a bit, removed unnecessary parts and variables and wrote this:

const int  buttonPin = 7;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
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_PULLUP);
  // 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 == LOW) {
      // if the current state is HIGH then the button went from off to on:
      digitalWrite(ledPin, !digitalRead(ledPin)); //toggle the led state!
    }
    // 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;


}

the actual part that you should use instead of if(button == LOW){} is this:

if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == LOW) {
      // if the current state is HIGH then the button went from off to on:
      digitalWrite(ledPin, !digitalRead(ledPin)); //toggle the led state!
    }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;

Thanks for all the answers! my problem is solved