Entering If Loop despite not meeting requirements

In a project I am working on, I write some data from some sensors to a SD card file when a button is pressed. This works sucessfully, however when I go above the 4 instances (i.e., I hit the button a 5th time) then the system just outputs a long list of numbers. I don't understand this because the value being read out is the progCounter and it is getting incremented only if the button is pressed for 3 cycles. At least this is my intentions. Clearly it isn't working. Below is my code and the Serial Monitor Output associated.

My code looks like this:

void loop(){
  if(runLoop) {
    if(progCounter==1){
      writeFile(SD, "/Button1.txt");
      runLoop = false;
    }
    if(progCounter==2){
      writeFile(SD, "/Button2.txt");
      runLoop = false;
    }
    if(progCounter==3){
      writeFile(SD, "/Button3.txt");
      runLoop = false;
    }
    if(progCounter==4){
      writeFile(SD, "/Button4.txt");
      runLoop = false;
    }
    if(progCounter>4){
      Serial.println(progCounter);
      //while (1);
    }
  }

  buttonState = digitalRead(buttonPin);
  if((buttonState==HIGH) && (prevButtonState==HIGH) && (prevPrevButtonState==HIGH)) {
    runLoop = true;
    progCounter += 1;
  }
  else if((buttonState==LOW) && (prevButtonState==HIGH)) {
    runLoop = false;
  }
  else{
    runLoop = false;
  }
  prevPrevButtonState=prevButtonState;
  prevButtonState=buttonState;
}

The serial monitor looks like this:

Writing file: /Button1.txt
Done w/ file: /Button1.txt
 
Writing file: /Button2.txt
Done w/ file: /Button2.txt
 
Writing file: /Button3.txt
Done w/ file: /Button3.txt
 
Writing file: /Button4.txt
Done w/ file: /Button4.txt
5
6
7
8
9
10
11
12
13
14
15
16

And this continues on until I unplug the controller.

Why is the progCounter incrementing even when the button isn't in the pressed state?

Please edit your post to include ALL the code. To understand the problem, people need to see variable declarations and other vital information.

Sorry here is all of it.

/*
 * Name: Luk Dean
 * Date: 3/30/2023
 * Purpose: on button click write to next file after click
 * Revision: V5
 */

/* GPIO PIN AND ASSOCIATED SENSOR
 * ## - Name  || ## - Name
 * 32 - RH1   || 4  -
 * 33 - RH2   || 12 -
 * 34 - RK1   || 13 -
 * 35 - RK2   || 14 -
 * 36 - RA1   || 25 -
 * 37 -       || 26 -
 * 38 -       || 27 -
 * 39 - RA2   || 
 */
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include "WiFi.h"

const int RA1 = 35; // right ankel 1
const int LA1 = 27; // right ankel 2
const int RK1 = 32; // right knee 1
const int LK1 = 14; // right knee 2
const int RH1 = 33; // right hip 1
const int LH1 = 12; // right hip 2
int T; // variable to be used for time

bool runLoop = false; // set state based loop to write to SD card
const int buttonPin = 22;
int buttonState = LOW;
int prevButtonState = LOW;
int prevPrevButtonState = LOW;
int progCounter = 0;

const float   maxVoltage = 3.3; //ESP32 max voltage on ADC pins
const int     maxDigital = 4095; //max digital pin value
const float adcSlopeConv = maxVoltage / maxDigital; //.000805 V/DigitalValue
const int     staticGain = 300; //static sensitvity is 300mV/g
const float        zeroG = 1.65; //ADXL335 3-axis accel. on GY-61 dev board centers at 1.65V

const int zero = (maxDigital / 2);

void writeFile(fs::FS &fs, const char * path){
    Serial.println(" ");
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }
    // print the headers to the file
    file.println("Time(s), RH1, RK1, RA1, LH1, LK1, LA1");

    // Set reference time
    T = micros() / 1e6;

    // Write 1000 data points to file.
    for (int i = 0; i < 1000; i++) {
      file.print(micros() / 1e6 - T, 6);
      file.print(", ");
      file.print(analogRead(RH1));
      file.print(", ");
      file.print(analogRead(RK1));
      file.print(", ");
      file.print(analogRead(RA1));
      file.print(", ");
      file.print(analogRead(LH1));
      file.print(", ");
      file.print(analogRead(LK1));
      file.print(", ");
      file.println(analogRead(LA1));
      delay(5);
    }

    file.close();
    Serial.printf("Done w/ file: %s\n", path);
}

void setup(){
    Serial.begin(115200);
    if(!SD.begin()){
        Serial.println("Card Mount Failed");
        return;
    }
    uint8_t cardType = SD.cardType();

    if(cardType == CARD_NONE){
        Serial.println("No SD card attached");
        return;
    }

    WiFi.mode(WIFI_OFF); // turn off WiFi so ADC2 can be used
}

void loop(){
  if(runLoop) {
    if(progCounter==1){
      writeFile(SD, "/Button1.txt");
      runLoop = false;
    }
    if(progCounter==2){
      writeFile(SD, "/Button2.txt");
      runLoop = false;
    }
    if(progCounter==3){
      writeFile(SD, "/Button3.txt");
      runLoop = false;
    }
    if(progCounter==4){
      writeFile(SD, "/Button4.txt");
      runLoop = false;
    }
    if(progCounter>4){
      Serial.println(progCounter);
      //while (1);
    }
  }

  buttonState = digitalRead(buttonPin);
  if((buttonState==HIGH) && (prevButtonState==HIGH) && (prevPrevButtonState==HIGH)) {
    runLoop = true;
    progCounter += 1;
  }
  else if((buttonState==LOW) && (prevButtonState==HIGH)) {
    runLoop = false;
  }
  else{
    runLoop = false;
  }
  prevPrevButtonState=prevButtonState;
  prevButtonState=buttonState;
}

Seems like this part would do that.

What was the while(1); for?

a7

@alto777 that should just put it in an infinite loop "stuck" effectively.

However I guess my question isn't quite correct. How is the code incrementing and printing when the conditions are not met by the states? I have two if statements that should prevent both actions.

if(runLoop) {...
if((buttonState==HIGH) && ...

These to lines should limit what the void loop() can even do. Like how is it getting inside the if(runLoop... and how is it getting is side the if((buttonstate==high... loop to increment the counter when the buttons hasn't been pressed?

OIC… sry.

How is your switch wired?

This:

  buttonState = digitalRead(buttonPin);

  if((buttonState==HIGH) && (prevButtonState==HIGH) && (prevPrevButtonState==HIGH)) {
    runLoop = true;
    progCounter += 1;
  }

is the only place that can be increasing progCounter. Therefore we conclude it is being executed.

So there is an error or bad assumption about the logical expression.

I would run your code and do it, but there is too much extra stuff to account for so you should print out the values of those variables that inform the logical choice to execute that code.

BTW Seeing both prevButtonState and prevPrevButtonState in the logic makes me wonder if you are creativley compensating for contacy bounce on the button... did you have some trouble with double or multiple actions with a "single" press?

a7

1 Like

don't see any pinMode()??

~q

This your code stripped of all the distractions and simulated:

Wokwi_badge Switch Problem?

I replaced your button handler with a standard pattern timed debounce algorithm.

Pressing the button stops a running "program". Pressing the button when none is running runs the next "program".

I just guessed that's what you were going for. I did try to understand and identify the problem with your button handling, I could make neither heads nor tails of it in the time alloted.


// https://wokwi.com/projects/360769786667890689
// https://forum.arduino.cc/t/entering-if-loop-despite-not-meeting-requirements/1109505

bool runLoop = false; // set state based loop to write to SD card
const int buttonPin = 7;
int buttonState = LOW;
int prevButtonState = LOW;
int prevPrevButtonState = LOW;
int progCounter = 0;
/*
const float   maxVoltage = 3.3; //ESP32 max voltage on ADC pins
const int     maxDigital = 4095; //max digital pin value
const float adcSlopeConv = maxVoltage / maxDigital; //.000805 V/DigitalValue
const int     staticGain = 300; //static sensitvity is 300mV/g
const float        zeroG = 1.65; //ADXL335 3-axis accel. on GY-61 dev board centers at 1.65V

const int zero = (maxDigital / 2);
*/
# define SD 777

// fake writeFile function
void writeFile(int aNumber, char *msg)
{
  static unsigned int counter;

  Serial.print(counter); counter++;
  Serial.print("  ");  
  Serial.println(msg);
}

void setup(){
    Serial.begin(115200);
    Serial.println("hello there world!\n");

//...
    pinMode(buttonPin, INPUT_PULLUP);
}

void loop(){
  if(runLoop) {
    if(progCounter==1){
      writeFile(SD, "Button1.txt");
      runLoop = false;
    }
    if(progCounter==2){
      writeFile(SD, "Button2.txt"); delay(100);  // so be slow on the pushbutton...
//      runLoop = false;
    }
    if(progCounter==3){
      writeFile(SD, "Button3.txt");
      runLoop = false;
    }
    if(progCounter==4){
      writeFile(SD, "Button4.txt");
      runLoop = false;
    }
    if(progCounter>4){
      Serial.println(progCounter);
      //while (1);
    }
  }

  buttonState = digitalRead(buttonPin);

  static unsigned long lastButtonTime;
  if (millis() - lastButtonTime > 20) {
    lastButtonTime = millis();

    if (buttonState != prevButtonState) {

      if (!buttonState) {

        if (runLoop) {
          runLoop = false;
        }
        else {
          progCounter++;
          runLoop = true;
        } 
      }

      prevButtonState = buttonState; 
    }
  }
}

HTH

a7

Thank you too both @alto777 and @qubits-us for you help.
It seemed to be a combination of your suggestions.

I stripped the code back to a more basic setup, so I could analyze actually results and states. It appears the voltage on the pin connected to the button occasionally triggered a false press so by using the code below. I settled this problem. This made the code work well.

pinMode(buttonPin, INPUT_PULLDOWN);

Thanks again!

Now you get to post the code that works!

I'm not the only one who would like the solution to be part of the record.

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.