Question about do {} while() loops

I'm modifying this project . (towards the end of the page he has a circuit diagram and full code example).
He uses do {} while() loops which I am not familiar with.
I didn't realize this was happening until I started testing for it, but using the code below, the pin starts low, is triggered high, then never goes low again.

do {
    button = digitalRead(buttonPin);
    mp3_stop();
  } while (button == 0);
do {
  Serial.println("Button Hit");
  mp3_play(1);
  delay(100);
} while (button ==1);

After a lot of messing with the physical board, I tried switching things to if else statements and suddenly button presses register correctly. I want to understand why.

My understanding is that the 'do while loop repeatedly executes code until it's condition is no longer true. I found it strange that he put the digitalRead statement inside the first loop, but duplicating that statement for the button == 1 loop didn't fix things, and moving it out into the voidLoop also didn't fix things.
Does anyone have insight into why this doesn't read the button going low again, after having once gone high?

the pin starts low, is triggered high, then never goes low again.

What should trigger the pin? Why should it go low?

For the second do while loop, the value of button is never updated so the loop will be executed indefinitely.

In the future, please remember to post ALL your code. Snippets are usually useless.

The state is changed by a push button. The pin starts low and goes high when the circuit is closed.

When I add button = digitalRead(buttonPin); to the button == 1 loop, that code still doesn't execute. Same if I move that statement out into the voidLoop.

I'm also just curious why this guy is using a loop for this at all.

As requested:

#include "DFPlayer_Mini_Mp3/DFPlayer_Mini_Mp3.h"
#include "DFPlayer_Mini_Mp3/DFPlayer_Mini_Mp3.cpp"

const int buttonPin = 3;
int buttonState = 0;
const int buusyPin = 10;
int bsy = 0;
const int LEDstripLight = 12;
int max = 0;
int min = 9999;
const int sensorPin = A0;
int sensorValue = 0;
void setup () {
  pinMode(LEDstripLight, OUTPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin (9600);
  mp3_set_serial (Serial);
  mp3_set_volume (30); 
}

void loop () {

  do {
    buttonState = digitalRead(buttonPin);
    Serial.print("button state: ");
    Serial.print(buttonState);
    Serial.println("");
  } while (buttonState == 0);
  do {
buttonState = digitalRead(buttonPin);
    Serial.println("Button Hit");
    Serial.print("button state: ");
    Serial.print(buttonState);
    Serial.println("");
  } while (buttonState == 1);
  do {
    int trigger1 = 900;
    int trigger2 = 900;
    sensorValue = analogRead(sensorPin);
    if (sensorValue> max) max=sensorValue;
    if (sensorValue < min) min=sensorValue;
    
    Serial.print(sensorValue);
   Serial.print(" ");
    if (sensorValue >=trigger1) {  // wsa 750 on amplified out
      Serial.print("+ ");
      digitalWrite(LEDstripLight, HIGH);
    }
    if (sensorValue <= trigger2) { // was  666 on amplified out
      digitalWrite(LEDstripLight, LOW);
       Serial.println("- ");
    }
    bsy = digitalRead(buusyPin);
  } while (bsy == 0); // zero when sound active
  digitalWrite(LEDstripLight, LOW);
}

I didn’t want to post all this code because I’m not asking for code review, this is a general question about checking a button state in a do{} while() loop.

He uses do {} while() loops which I am not familiar with.

Unless you know what the ramifications can be when using ‘do’ and ‘while’ loops don’t use them.

These can be blocking if not used properly.

Extra credit.

delay() stops regular code execution for the delay interval.

You can replace delay() with a technique called Blink Without Delay, BWD.

When using BWD, your sketch can run other code during the delay time.

Read Robin2’s discussion, Demonstration code for several things at the same time:

Yes, I understand that I shouldn't use them if I don't understand them. that's what this question is, asking about the ramifications of his use of do{} while() loops, and why he's using them in his code.

Dr Zee,

Unfortunately I think you are asking an impossible question, you are asking all of us why someone else wrote their code the way they did, something only they can tell you. I don't think using do-while for checking buttons like that makes any sense at all, as it is completely blocking. If you do need to use while, be very sure that it will complete whatever it has to do very quickly, so as not to block anything else. At the point of typing this, the only thing I can think of that I'd use while for is reading all the bytes in a serial receive buffer. As serial data comes in relatively slowly, code that reads every byte in the buffer before moving on isn't going to take much time to empty the buffer. I'm sure that's not the only possible use, but it's all I can think of now.

Oh, and ++Karma; for posting code properly and asking a sensible question on your first visit to the forum :slight_smile:

OP, the while loop in this code seems wrong, it is hard to determine what a developer had in mind when the developer wrote the code.

It is far easier for us to all agree that that code is not logical nor desired in this context.

This is the complete code I see at the linked project

#include <DFPlayer_Mini_Mp3.h>

const int buttonPin = 3;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status
int buusyPin = 10;// buusyPin = 10; // sound player busy
int bsy = 0;
int LEDstripLight = 12; // IRL520 to LED strip light
int max=0;
int min=9999;
int sensorPin = A0;    // Audio level samples
int sensorValue = 0;  // variable to store the value coming from the sensor
int buttn = 0;

void setup () {
  pinMode(buttonPin, INPUT);
  pinMode(LEDstripLight, OUTPUT);
  pinMode(buusyPin, INPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin (9600);
  mp3_set_serial (Serial); //set Serial for DFPlayer-mini mp3 module
  mp3_set_volume (30);          // must remove mp3_reset(); to get this to work
}

void loop () {
  Serial.println("");
  Serial.print(min);  
  Serial.println("");
  Serial.println(max);
  Serial.println("Waiting for Button Push");
  do {
    buttn = digitalRead(buttonPin); // pins closest to power pins
  } while (buttn == 0);
  Serial.println("Button Hit");
  mp3_play(1);
  delay(100);
  do {
    // 900 for both works well when running from a 7+ volt power supply
    int trigger1 = 900;
    int trigger2 = 900;
    sensorValue = analogRead(sensorPin);
    if (sensorValue> max) max=sensorValue;
    if (sensorValue < min) min=sensorValue;
    
    Serial.print(sensorValue);
   Serial.print(" ");
    if (sensorValue >=trigger1) {  // wsa 750 on amplified out
      Serial.print("+ ");
      digitalWrite(LEDstripLight, HIGH);
    }
    if (sensorValue <= trigger2) { // was  666 on amplified out
      digitalWrite(LEDstripLight, LOW);
       Serial.println("- ");
    }
    bsy = digitalRead(buusyPin);
  } while (bsy == 0); // zero when sound active
  digitalWrite(LEDstripLight, LOW);

}

This first do while loop halts the program until the button is pressed. It blocks waiting for input. Buttton is wired with an external pulldown resistor.

Serial.println("Waiting for Button Push");
  do {
    buttn = digitalRead(buttonPin); // pins closest to power pins
  } while (buttn == 0);
  Serial.println("Button Hit");
  mp3_play(1);

The second do while loop is linked to an external input (buusyPin) pulled low by the DF mini player and animates the lights, while the track is playing, based on signal level.

do {
    // 900 for both works well when running from a 7+ volt power supply
    int trigger1 = 900;
    int trigger2 = 900;
    sensorValue = analogRead(sensorPin);
    if (sensorValue> max) max=sensorValue;
    if (sensorValue < min) min=sensorValue;
    
    Serial.print(sensorValue);
   Serial.print(" ");
    if (sensorValue >=trigger1) {  // wsa 750 on amplified out
      Serial.print("+ ");
      digitalWrite(LEDstripLight, HIGH);
    }
    if (sensorValue <= trigger2) { // was  666 on amplified out
      digitalWrite(LEDstripLight, LOW);
       Serial.println("- ");
    }
    bsy = digitalRead(buusyPin);
  } while (bsy == 0); // zero when sound active

So I likely broke his simple code by adding the second button check.
Okay. Thank you very much.

PerryBebbington:
Dr Zee,

Unfortunately I think you are asking an impossible question, you are asking all of us why someone else wrote their code the way they did, something only they can tell you. I don't think using do-while for checking buttons like that makes any sense at all, as it is completely blocking. If you do need to use while, be very sure that it will complete whatever it has to do very quickly, so as not to block anything else. At the point of typing this, the only thing I can think of that I'd use while for is reading all the bytes in a serial receive buffer. As serial data comes in relatively slowly, code that reads every byte in the buffer before moving on isn't going to take much time to empty the buffer. I'm sure that's not the only possible use, but it's all I can think of now.

Oh, and ++Karma; for posting code properly and asking a sensible question on your first visit to the forum :slight_smile:

Understood. Thank you very much, Perry.

I didn't want to post all this code because I'm not asking for code review

We generally don't do "code reviews".

Most of the time it is important to see ALL the code in order to determine how certain critical variables are typed, whether they are global or local, or both, etc. because those details are required to diagnose very common errors.

In the future, avoid posting snippets. You will likely be criticized every time you do.

  do
  {
    buttn = digitalRead(buttonPin); // pins closest to power pins
  }
  while (buttn == 0);

The difference between 'while' and 'do-while' is that in a 'do-while' the body gets executed at least once.

It is roughly the same as saying:

  buttn = 0;
  while (buttn == 0)
  {
    buttn = digitalRead(buttonPin); // pins closest to power pins
  }

or saying:

  while ((buttn = digitalRead(buttonPin)) == 0)
  {/* DO NOTHING*/}

or saying:

  while (digitalRead(buttonPin) == 0)
  {/* DO NOTHING*/}
  buttn = 1;

All of them say "sit in a loop doing nothing but reading the button pin until it reads HIGH, then continue with 'buttn' set to HIGH.