Run code once per button press

Hi,

I am stuck trying to get certain pieces of code code to run only once per button press (digitalRead).

void setup() {
  // Set up and init all outputs to off
  pinMode(2, INPUT);
  pinMode(7, INPUT);
  
  Serial.begin(9600);
  while (!Serial);
  Serial.println("Test");
  
  for(byte i = 0; i<OutputCount; i++){
    pinMode( outputs[i][OutputPin], OUTPUT);
    digitalWrite( outputs[i][OutputPin], LOW );

    // Set up an event fuse for this output.
    eventFuse.newFuse( i, outputs[i][OffTime], INF_REPEAT, OutputHandler );
  }
  
  // Set MsTimer2 for one second per tick.
  MsTimer2::set(100, timerTick );
  MsTimer2::start();
}

void loop(){
    if (digitalRead(2) == HIGH) {
      while (i < 1){
        switchPos = 2;
        MsTimer2::start();
      i++;
      }
    }
    else if (digitalRead(7) == HIGH) {
      while (i < 1){
        switchPos = 7;
        MsTimer2::stop();
      }
    }
    else {
      switchPos = 0;
      i = 0;
    }
}

The above code uses the box-standard Lamp Timer example that comes with MsTimer2 and EventFuse.

In the loop section there are some while loops which seam to be infinite loops. All I need is a war to run the code you see inside the while loops only once. Any ideas?

Any help would be much appreciated!

Thanks

Hello and welcome,

You have to use a debouncing method, or, look for a button library. I like this one: https://github.com/JChristensen/Button

IF you want to do something once then a while loop, or loop of any kind is a pretty bad idea right? Just put it in an if statement and run it once.

If you want to react only once to a button being pushed then you need to look for changes in state. The State Change example that comes with the IDE should give you some inspiration.

An, perhaps useful, example of a push button object that is able to count and report programmable state transitions.

class push_button_t
{
    const uint16_t   pin              : 7;  // 0 - 127
    const uint16_t   transition_level : 1;
    const uint16_t   transitions_max  : 3;  // MAX 7

    uint16_t         transition_count : 3;  // MAX 7
    uint16_t         state_before     : 1;
    uint16_t         transitioned     : 1;

public:
    push_button_t(uint8_t pin, uint8_t transition_level = LOW, uint8_t number_of_states = 2)
        : pin(pin)
        , transition_level(transition_level)
        , transitions_max(number_of_states)
        
        , transition_count(0)
        , state_before(0)
        , transitioned(false)
    {}

    void begin() const      { pinMode(pin, INPUT); }

    uint8_t count() const   { return transition_count; }
    void reset()            { state_before = transition_count = 0; }

    bool has_changed()
    {
      transitioned = false;
      
        uint8_t state_now = digitalRead(pin);
        if ( state_now != state_before )
        {
            if ( state_now == transition_level )
            {
                transition_count++;
                transition_count %= transitions_max;

                transitioned = true;
            }
        }
        
       state_before = state_now;

       return transitioned;
    }
};

// HARDWARE PIN CONSTANTS
const uint8_t   pinBUTTON   =  4;   // chipKIT Basic I/O Shield BN1

// GLOBAL VARIABLE AND OBJECT INSTANCE(S)
push_button_t   button(pinBUTTON, LOW, 4);


void loop()
{
    if ( button.has_changed() )
    {
        switch ( button.count() )
        {
            // CONSIDER INITIAL, OF FOUR STATES, OFF
            case 0:
                Serial.println("Button toggled: OFF");
                break;

            case 1:
            case 2:
            case 3:
                Serial.print("Button toggled, count now: ");
                Serial.print(button.count(), DEC);
                Serial.println();

                break;
        }
    }
}

void setup()
{
    button.begin();

    Serial.begin(9600);
    Serial.print("Button initialized, count now: ");
    Serial.print(button.count(), DEC);
    Serial.println();
}