How to run code only one time when conditions for code to run are constanly valid

I have a small code:

int press_q=16;
int press_w=5;
int press_e=4;
void setup() {
  Serial.begin(9600);
  pinMode(press_q,INPUT_PULLUP);
  pinMode(press_w,INPUT_PULLUP);
  pinMode(press_e,INPUT_PULLUP);
}

void loop() {
  if(digitalRead(press_w)==0)
  {
    Serial.print('w');
  }
  if(digitalRead(press_e)==0)
  {
    Serial.print('e');
  }

}

The purpose of the code is to print letters on serial when pins 16,5, or 4 (I will call pins for short) are connected to GND. When pins are connected to GND, the serial will continually print letters in serial until I disconnect the pins from GND. However, I want it to print one letter per connect-disconnect cycle. Can anyone have suggestions please help me.

You are printing when the button is pressed rather than when it becomes pressed.

This is solved by "state change detection".

See the example in the IDE: File/Examples/02.Digital/StateChangeDetection

See how it works and bend it to your will.

HTH

a7

Hi @pepernamek1

welcome to the arduino-forum.

well done posting code as a code-section

How to run code only one time when conditions for code to run are constanly valid

by addding a boolean variable for each part of your code that shall run only once.

These boolean variables are set to true / false to have a condition that is only one time valid

int press_q = 16;
int press_w = 5;
int press_e = 4;

// constants with self-explaining names to make
// your code easier to read
const byte pressed  = LOW;
const byte released = HIGH;

boolean w_pressed = false;
boolean e_pressed = false;

void setup() {
  Serial.begin(9600);
  pinMode(press_q, INPUT_PULLUP);
  pinMode(press_w, INPUT_PULLUP);
  pinMode(press_e, INPUT_PULLUP);
}

void loop() {
  // check if button is pressed and the w not yet printed
  if (digitalRead(press_w) == pressed && w_pressed == false)
  {
    w_pressed = true; // set flag-variable to true to indicate w got printed
    Serial.print('w');
  }

  // if button is released and variable is still true 
  if (digitalRead(press_w) == released && w_pressed == true) 
  {
    w_pressed = false; // set flag-variable to false
  }


  // check if button is pressed and the e not yet printed
  if (digitalRead(press_e) == pressed && e_pressed == false)
  {
    e_pressed = true; // set flag-variable to true to indicate e got printed
    Serial.print('e');
  }

  if (digitalRead(press_e) == released && e_pressed == true)
  {
    e_pressed = false; // set flag-variable to false
  }  
}

best regards Stefan

Hello pepernamek1

Do you have experience with programming in C++?

The task can easily be realised with an object.
A structured array contains all the information, such as the pin addresses for the I/O devices, as well as the information for the timing.
A single service takes care of this information and initiates the intended action.
The structured array makes the sketch scalable until all I/O pins are used up without having to adapt the code for the service.
It is cool stuff, isn´t it?

Have a nice day and enjoy coding in C++.

Simple, you change the conditions for the code to run such that they can't be constantly valid :wink:

For example, instead of a condition if "if button is pressed", a condition of "if button was pressed, and it wasn't pressed last time it was checked (though you may also need to do debouncing for something like that, which can range from the crudest of crude measures, really sleek sophisticated methods.

Terse reply because others have explained the specifics, I'm just describing the general case "you don't want it to run continually? Then why did you pick a condition that can be continually true?"

Ideoms like

int16_t sensorreading=analogRead(pin);
int16_t diff = lastsensorreading -sensorreading;
if (diff > 50) {
  SCRAM();
  while(1) {
    flashRedLights();
  }
} else if (diff > -10) {
  adjustControlRod(diff);
} else {
  notifyOperator("Reactor unexpectedly shutting down require operator intervention");
}

that sort of thing....

(Though, not that specific example of course. using an arduino for that is grossly negligent)

const byte PinButs [] = { 4, 5, 16 };
const unsigned Nbuts = sizeof(PinButs);

const char Letters [Nbuts] = { 'e', 'w', 'q' };
byte butLst [Nbuts];

void loop ()
{
    for (unsigned n = 0; n < Nbuts; n++)  {
        byte but = digitalRead (PinButs [n]);
        if (butLst [n] != but)  {
            butLst [n] = but;
            delay (20);         // debounce

            if (LOW == but)
                Serial.print (Letters [n]);
        }
    }
}

void setup(){
    Serial.begin (9600);

    for (unsigned n = 0; n < Nbuts; n++)  {
        pinMode (PinButs [n], INPUT_PULLUP);
        butLst [n] = digitalRead (PinButs [n]);
    }
}