Weird problem; first line (187) executes but second (188) doesn't?

I am working on a project I can use to characterise some bimetallic switches using microcontroller STM32F103C8T6 with the official STM Arduino core. Each usage of the completed project will consist of two phases where the temperature goes one way and then vice versa with the microcontroller recording the temperature when each switch changes state. I want my project to attract my attention when either phase has completed.

My code is posted at the bottom of this post with temperature-measuring parts deleted for the purpose of debugging here. The issue I'm focussed on is in the function starting at line 178 which decides when a phase has completed. It does so without any problems; however, I only seem to be able to set userInterventionRequiredFlag = true; either on completion of phase one or on completion of phase two but not both.

If I have my code as follows

  if (i == NUMBEROFBIMETALLICSWITCHES && phaseOneCompleteFlag == false) {
    phaseOneCompleteFlag = true;
    userInterventionRequiredFlag = true;
    initialBimetallicSwitchState = bimetallicSwitchStates[0];
  } else if (i == NUMBEROFBIMETALLICSWITCHES && phaseOneCompleteFlag == true) {
    phaseTwoCompleteFlag = true;
    userInterventionRequiredFlag = true;
  }
}

the userIntervention flag is set to true as expected when phase one ends. However, when phase two ends, despite the phaseTwo flag being set to true, the userIntervention flag is left as false?! That seems quite maddening to me - one should be executed right after the other. If I remove the line userInterventionRequiredFlag = true; from the if statement (leaving it in the else if statement), then the userIntervention flag gets set to true as expected when phase two completes but of course I then don't get my notification that phase one has completed.

Project code *without parts which aren't required to isolate this problem:

/*
rationale
10 bimetallic switches and three thermistors will be connected to a BluePill to record the temperature at which each bimetallic switch changes state (the project will be placed in a hot or cold place to trigger the switches)
plan
check and store switch states in an array on setup
every second, check each switch state in turn and if different from the value in the array, change the value in the array and record the temperature for each thermistor in separate arrays
when all thermistors have changed state, start speaker
when button is pressed, stop speaker and store temperatures in new array positions for the next stage
every second, check each switch state in turn and if different from the value in the array, change the value in the array and record the temperature for each thermistor in separate arrays
when all thermistors have changed state, start speaker
when button is pressed, stop speaker and begin serial data transfer
*/
#define DEBUG 0   // value is 1 to enable debugging serial printing
#define DEBUG2 1  // value is 1 to enable debugging serial printing

#if DEBUG == 1
#define DEBUG(x) Serial.print(x)
#define DEBUGLN(x) Serial.println(x)
#else
#define DEBUG(x)
#define DEBUGLN(x)
#endif

#if DEBUG2 == 1
#define DEBUG2(x) Serial.print(x)
#define DEBUGLN2(x) Serial.println(x)
#else
#define DEBUG2(x)
#define DEBUGLN2(x)
#endif

// how many bimetallic switches to monitor simultaneously - might not use this, actually
#define NUMBEROFBIMETALLICSWITCHES 10

// which analog pins to use with thermistors
#define THERMISTORPIN1 PA7  //
#define THERMISTORPIN2 PB0  //
#define THERMISTORPIN3 PB1  //

// which digital pins to use for BUTTONPIN to trigger sending contents of matrix to serial
#define BUTTONPIN PB2  //
// buzzer pin
#define PIEZOPIN PA6  //
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 1000-4000)
#define BCOEFFICIENT 3950
// the value of the resistor used to make a potential divider with the thermistor
#define SERIESRESISTOR 10000

// an array is need to store the pins to which each bimetallic switch will be attached
unsigned char bimetallicSwitchMonitoringPins[10] = { PB12, PB13, PB14, PB15, PA8, PA9, PA10, /* PA11, PA12, */ PA15, PB3, PB4, /* PB5, PB6, PB7, PB8, PB9, /* PA13, PA14, PC13, PC14, PC15, PA0, PA1, PA2, PA3, PA4, PA5, PB10, PB11 */ };  // commented out the pins needed for serial and swd programming

bool initialBimetallicSwitchState;

// an array to store the state of each bimetallic switch
bool bimetallicSwitchStates[10];

// places to store temperatures temporarily
int temperature1;
int temperature2;
int temperature3;

// places to store temperatures after detecting change in switch state
int temperatureArray1[60];
int temperatureArray2[60];
int temperatureArray3[60];

// arrays to store thermistor readings prior to conversion to an average temperature
int samples1[NUMSAMPLES];
int samples2[NUMSAMPLES];
int samples3[NUMSAMPLES];

// how frequently to check the bimetallic switch states and act on readings
const unsigned long temperatureMeasurementInterval = 1000;
const unsigned long thermistorReadShortInterval = 10;

// how long button should be pressed
const int SHORT_PRESS_TIME = 1000;  // 1000 milliseconds
const int LONG_PRESS_TIME = 1000;   // 1000 milliseconds

bool bimetallicSwitchStateCheckingFlag = false;
bool thermistorSamplingFlag = false;
bool userInterventionRequiredFlag = false;
bool thermistorSamplingCompleteFlag = false;
bool phaseOneCompleteFlag = false;
bool phaseTwoCompleteFlag = false;

bool lastButtonState;
bool currentButtonState;
bool buttonIsBeingPressed;
bool shortButtonPressDetected;
bool longButtonPressDetected;
unsigned long buttonPressTimeStart;
unsigned long buttonPressTimeEnd;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTONPIN, INPUT);  // have to use INPUT with an external pullup resistor, not INPUT_PULLUP because for some reason, INPUT_PULLUP stops PB2 from detecting when it has been pulled low.
  // pinMode(13, OUTPUT); // what is this for?
  // set each pin in bimetallicSwitch monitoring array to INPUT_PULLUP, then fill each position in the array with the initial state of each pin
  for (unsigned char i = 0; i < 10; i++) {
    pinMode(bimetallicSwitchMonitoringPins[i], INPUT_PULLUP);
    bimetallicSwitchStates[i] = digitalRead(bimetallicSwitchMonitoringPins[i]);
  }
  // check that all of the bimetallic switches are in the same state and if they are not, attract user intervention
  for (unsigned char i = 1; i < 10; i++) {
    if (bimetallicSwitchStates[0] != bimetallicSwitchStates[i]) {
      userInterventionRequiredFlag = true;
      return;
    }
    initialBimetallicSwitchState = bimetallicSwitchStates[0];
  }
}

void loop() {
  buttonPressDetection(BUTTONPIN, lastButtonState, currentButtonState, buttonPressTimeStart, buttonPressTimeEnd, buttonIsBeingPressed, shortButtonPressDetected, longButtonPressDetected);
  userInterventionAttractionTask();
  thermistorSamplingTimerTask();
  thermistorSamplingTask();
  thermistorSampleAveragingTask();
  bimetallicSwitchStateCheckingTask();
  phaseFlagSettingTask();
 }

void userInterventionAttractionTask() {
  if (userInterventionRequiredFlag == false) {
    return;
  }
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1200) {
    previousMillis = currentMillis;
    tone(PIEZOPIN, 800, 600);
  }
  if (shortButtonPressDetected == true) {
    noTone(PIEZOPIN);
    userInterventionRequiredFlag = false;
    return;
  }
}

void thermistorSamplingTimerTask() {
  static unsigned long previousMillis = 0;

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis < temperatureMeasurementInterval) {
    return;
  }
  previousMillis = currentMillis;
  thermistorSamplingFlag = true;
  for (unsigned char i = 0; i < 10; i++) {
    DEBUG2((String)bimetallicSwitchMonitoringPins[i] + "=" + bimetallicSwitchStates[i] + ",");
  }
  DEBUGLN2((String) "initialState:" + initialBimetallicSwitchState + ", phaseOne:" + phaseOneCompleteFlag + ", phaseTwo:" + phaseTwoCompleteFlag + ", intervention:" + userInterventionRequiredFlag + ", buttonState:" + currentButtonState + ", longButton:" + longButtonPressDetected);
  return;
}

void bimetallicSwitchStateCheckingTask() {
  if (bimetallicSwitchStateCheckingFlag == false || userInterventionRequiredFlag == true || phaseTwoCompleteFlag == true) {
    return;
  }
  for (unsigned char i = 0; i < 10; i++) {
    if (digitalRead(bimetallicSwitchMonitoringPins[i]) != bimetallicSwitchStates[i]) {  // check whether the current state of each bitmetallic switch is different from its corresponding state stored in the array
      bimetallicSwitchStates[i] = !bimetallicSwitchStates[i];                           // set the bimetallic switch state to its new state
      temperatureArray1[i + (10 * phaseOneCompleteFlag)] = temperature1;                // fill the relevant arrays with the last-recorded temperatures
      temperatureArray2[i + (10 * phaseOneCompleteFlag)] = temperature2;
      temperatureArray3[i + (10 * phaseOneCompleteFlag)] = temperature3;
    }
  }
}

void phaseFlagSettingTask() {
  unsigned char i = 0;
  while (i++ < 9 && bimetallicSwitchStates[i] == bimetallicSwitchStates[0] && bimetallicSwitchStates[0] != initialBimetallicSwitchState)
    ;
  if (i == 10 && phaseOneCompleteFlag == false) {
    phaseOneCompleteFlag = true;
    userInterventionRequiredFlag = true;
    initialBimetallicSwitchState = bimetallicSwitchStates[0];
  } else if (i == 10 && phaseOneCompleteFlag == true) {
    phaseTwoCompleteFlag = true;
    userInterventionRequiredFlag = true;
  }
}


void thermistorSamplingTask() {
  thermistorSamplingCompleteFlag = true;  // this lets the next stage of the main loop begin
  return;
}


void thermistorSampleAveragingTask() {
  bimetallicSwitchStateCheckingFlag = true;  // this flag lets the bimetallic switch checking start
}

void buttonPressDetection(const unsigned char BUTTON_PIN, bool &lastButtonState, bool &currentButtonState, unsigned long &buttonPressTimeStart, unsigned long &buttonPressTimeEnd, bool &buttonIsBeingPressed, bool &shortButtonPressDetected, bool &longButtonPressDetected) {
  // read the state of the switch/button:
  currentButtonState = digitalRead(BUTTON_PIN);

  if (lastButtonState == HIGH && currentButtonState == LOW) {  // button is pressed
    buttonPressTimeStart = millis();
    buttonIsBeingPressed = true;
    longButtonPressDetected = false;
  } else if (lastButtonState == LOW && currentButtonState == HIGH) {  // button is released
    buttonIsBeingPressed = false;
    buttonPressTimeEnd = millis();

    long pressDuration = buttonPressTimeEnd - buttonPressTimeStart;

    if (10 < pressDuration && pressDuration < SHORT_PRESS_TIME) {
      DEBUGLN2("A short press is detected");
      shortButtonPressDetected = true;
    }
    longButtonPressDetected = false;
  }

  if (buttonIsBeingPressed == true && longButtonPressDetected == false) {
    long pressDuration = millis() - buttonPressTimeStart;

    if (pressDuration > LONG_PRESS_TIME) {
      DEBUG("A long press is detected");
      longButtonPressDetected = true;
    }
  }

  // save the last state
  lastButtonState = currentButtonState;
}

Usually, those parts are where the problem is. Don't post snippets. If you can't post the entire thing, post an MRE demonstrating the problem.

You do realize,

if x then...
if y then...

is not the same as

if x then...
else if y then...

In the second case, if x is true, y is never tested.

They definitely are not where the problem is. I removed those parts and uploaded the shortened code to the microcontroller to check the behaviour. The behaviour is the same so those parts do not contain the problem. If you want the full code anyway, here it is:

/*
rationale
30 bimetallic switches and three thermistors will be connected to a BluePill to record the temperature at which each bimetallic switch changes state (the project will be placed in a hot or cold place to trigger the switches)
plan
check and store switch states in an array on setup
every second, check each switch state in turn and if different from the value in the array, change the value in the array and record the temperature for each thermistor in separate arrays
when all thermistors have changed state, start speaker
when button is pressed, stop speaker and store temperatures in new array positions for the next stage
every second, check each switch state in turn and if different from the value in the array, change the value in the array and record the temperature for each thermistor in separate arrays
when all thermistors have changed state, start speaker
when button is pressed, stop speaker and begin serial data transfer
*/
#define DEBUG 0   // value is 1 to enable debugging serial printing
#define DEBUG2 1  // value is 1 to enable debugging serial printing

#if DEBUG == 1
#define DEBUG(x) Serial.print(x)
#define DEBUGLN(x) Serial.println(x)
#else
#define DEBUG(x)
#define DEBUGLN(x)
#endif

#if DEBUG2 == 1
#define DEBUG2(x) Serial.print(x)
#define DEBUGLN2(x) Serial.println(x)
#else
#define DEBUG2(x)
#define DEBUGLN2(x)
#endif

// how many bimetallic switches to monitor simultaneously - might not use this, actually
#define NUMBEROFBIMETALLICSWITCHES 26

// which analog pins to use with thermistors
#define THERMISTORPIN1 PA7  //
#define THERMISTORPIN2 PB0  //
#define THERMISTORPIN3 PB1  //

// which digital pins to use for BUTTONPIN to trigger sending contents of matrix to serial
#define BUTTONPIN PB2  //
// buzzer pin
#define PIEZOPIN PA6  //
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 1000-4000)
#define BCOEFFICIENT 3950
// the value of the resistor used to make a potential divider with the thermistor
#define SERIESRESISTOR 10000

// an array is need to store the pins to which each bimetallic switch will be attached
unsigned char bimetallicSwitchMonitoringPins[NUMBEROFBIMETALLICSWITCHES] = { PB12, PB13, PB14, PB15, PA8, PA9, PA10, /* PA11, PA12, */ PA15, PB3, PB4, PB5, PB6, PB7, PB8, PB9, /* PA13, PA14, */ PC13, PC14, PC15, PA0, PA1, PA2, PA3, PA4, PA5, PB10, PB11 };  // commented out the pins needed for serial and swd programming

bool initialBimetallicSwitchState;

// an array to store the state of each bimetallic switch
bool bimetallicSwitchStates[NUMBEROFBIMETALLICSWITCHES];

// places to store temperatures temporarily
int temperature1;
int temperature2;
int temperature3;

// places to store temperatures after detecting change in switch state
int temperatureArray1[60];
int temperatureArray2[60];
int temperatureArray3[60];

// arrays to store thermistor readings prior to conversion to an average temperature
int samples1[NUMSAMPLES];
int samples2[NUMSAMPLES];
int samples3[NUMSAMPLES];

// how frequently to check the bimetallic switch states and act on readings
const unsigned long temperatureMeasurementInterval = 1000;
const unsigned long thermistorReadShortInterval = 10;

// how long button should be pressed
const int SHORT_PRESS_TIME = 1000;  // 1000 milliseconds
const int LONG_PRESS_TIME = 1000;   // 1000 milliseconds

bool bimetallicSwitchStateCheckingFlag = false;
bool thermistorSamplingFlag = false;
bool userInterventionRequiredFlag = false;
bool thermistorSamplingCompleteFlag = false;
bool phaseOneCompleteFlag = false;
bool phaseTwoCompleteFlag = false;

bool lastButtonState;
bool currentButtonState;
bool buttonIsBeingPressed;
bool shortButtonPressDetected;
bool longButtonPressDetected;
unsigned long buttonPressTimeStart;
unsigned long buttonPressTimeEnd;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTONPIN, INPUT);  // have to use INPUT with an external pullup resistor, not INPUT_PULLUP because for some reason, INPUT_PULLUP stops PB2 from detecting when it has been pulled low.
  // pinMode(13, OUTPUT); // what is this for?
  // set each pin in bimetallicSwitch monitoring array to INPUT_PULLUP, then fill each position in the array with the initial state of each pin
  for (unsigned char i = 0; i < NUMBEROFBIMETALLICSWITCHES; i++) {
    pinMode(bimetallicSwitchMonitoringPins[i], INPUT_PULLUP);
    bimetallicSwitchStates[i] = digitalRead(bimetallicSwitchMonitoringPins[i]);
  }
  // check that all of the bimetallic switches are in the same state and if they are not, attract user intervention
  for (unsigned char i = 1; i < NUMBEROFBIMETALLICSWITCHES; i++) {
    if (bimetallicSwitchStates[0] != bimetallicSwitchStates[i]) {
      userInterventionRequiredFlag = true;
      return;
    }
    initialBimetallicSwitchState = bimetallicSwitchStates[0];
  }
}

void loop() {
  buttonPressDetection(BUTTONPIN, lastButtonState, currentButtonState, buttonPressTimeStart, buttonPressTimeEnd, buttonIsBeingPressed, shortButtonPressDetected, longButtonPressDetected);
  userInterventionAttractionTask();
  thermistorSamplingTimerTask();
  thermistorSamplingTask();
  thermistorSampleAveragingTask();
  bimetallicSwitchStateCheckingTask();
  phaseFlagSettingTask();
  serialDataTransferTask();
}

void userInterventionAttractionTask() {
  if (userInterventionRequiredFlag == false) {
    return;
  }
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1200) {
    previousMillis = currentMillis;
    tone(PIEZOPIN, 800, 600);
  }
  if (shortButtonPressDetected == true) {
    noTone(PIEZOPIN);
    userInterventionRequiredFlag = false;
    return;
  }
}

void thermistorSamplingTimerTask() {
  static unsigned long previousMillis = 0;

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis < temperatureMeasurementInterval) {
    return;
  }
  previousMillis = currentMillis;
  thermistorSamplingFlag = true;
  for (unsigned char i = 0; i < NUMBEROFBIMETALLICSWITCHES; i++) {
    DEBUG2((String)bimetallicSwitchMonitoringPins[i] + "=" + bimetallicSwitchStates[i] + ",");
  }
  DEBUGLN2((String)phaseOneCompleteFlag + "," + phaseTwoCompleteFlag + "," + userInterventionRequiredFlag + "," + currentButtonState + "," + longButtonPressDetected);
  return;
}

void bimetallicSwitchStateCheckingTask() {
  if (bimetallicSwitchStateCheckingFlag == false || userInterventionRequiredFlag == true || phaseTwoCompleteFlag == true) {
    return;
  }
  for (unsigned char i = 0; i < NUMBEROFBIMETALLICSWITCHES; i++) {
    if (digitalRead(bimetallicSwitchMonitoringPins[i]) != bimetallicSwitchStates[i]) {            // check whether the current state of each bitmetallic switch is different from its corresponding state stored in the array
      bimetallicSwitchStates[i] = !bimetallicSwitchStates[i];                                     // set the bimetallic switch state to its new state
      temperatureArray1[i + (NUMBEROFBIMETALLICSWITCHES * phaseOneCompleteFlag)] = temperature1;  // fill the relevant arrays with the last-recorded temperatures
      temperatureArray2[i + (NUMBEROFBIMETALLICSWITCHES * phaseOneCompleteFlag)] = temperature2;
      temperatureArray3[i + (NUMBEROFBIMETALLICSWITCHES * phaseOneCompleteFlag)] = temperature3;
    }
  }
}

void phaseFlagSettingTask() {
  unsigned char i = 0;
  while (i++ < NUMBEROFBIMETALLICSWITCHES - 1 && bimetallicSwitchStates[i] == bimetallicSwitchStates[0] && bimetallicSwitchStates[0] != initialBimetallicSwitchState)
    ;
  if (i == NUMBEROFBIMETALLICSWITCHES && phaseOneCompleteFlag == false) {
    phaseOneCompleteFlag = true;
    userInterventionRequiredFlag = true;
    initialBimetallicSwitchState = bimetallicSwitchStates[0];
  } else if (i == NUMBEROFBIMETALLICSWITCHES && phaseOneCompleteFlag == true) {
    phaseTwoCompleteFlag = true;
    userInterventionRequiredFlag = true;
  }
}


void thermistorSamplingTask() {
  static unsigned long previousMillis = 0;
  static unsigned char index = 0;

  if (thermistorSamplingFlag == false) {
    return;
  }

  unsigned long currentMillis = millis();
  // at the "thermistorReadInterval
  if (millis() - previousMillis < thermistorReadShortInterval) {
    return;
  }
  previousMillis = millis();

  // take NUMSAMPLES samples
  samples1[index] = analogRead(THERMISTORPIN1);
  samples2[index] = analogRead(THERMISTORPIN2);
  samples3[index] = analogRead(THERMISTORPIN3);
  index = (index + 1) % NUMSAMPLES;  // this resets index to 0 when array contains NUMSAMPLES values

  if (index == 0) {                         // when index is reset to 0, it's because the array is full and complete
    thermistorSamplingFlag = false;         // sampling can now stop for a while
    thermistorSamplingCompleteFlag = true;  // this lets the next stage of the main loop begin
    return;
  }
}

void thermistorSampleAveragingTask() {
  // check whether array is full - this flag is set to true when the array is full
  if (thermistorSamplingCompleteFlag == false) {
    return;
  }
  // do the averaging here
  temperature1 = samplesToTemp(samples1);
  DEBUG(", 1: ");
  DEBUG(temperature1);
  DEBUGLN("°C");
  temperature2 = samplesToTemp(samples2);
  DEBUG(", 2: ");
  DEBUG(temperature2);
  DEBUGLN("°C");
  temperature3 = samplesToTemp(samples3);
  DEBUG(", 3: ");
  DEBUG(temperature3);
  DEBUGLN("°C");

  thermistorSamplingCompleteFlag = false;    // reset this flag so sampling can begin again
  bimetallicSwitchStateCheckingFlag = true;  // this flag lets the bimetallic switch checking start
}

// function for turning list of resistance measurements into temperature reading
unsigned char samplesToTemp(int samplesSensor[]) {
  float average = 0;

  // average all the samples out
  for (unsigned char index = 0; index < NUMSAMPLES; index++) {
    average += samplesSensor[index];
  }
  average /= NUMSAMPLES;

  DEBUG("Average analog reading ");
  DEBUG(average);

  // convert the value to resistance
  average = 4095 / average - 1;  // value 4095 is for 12-bit ADC; 1023 for a 8-bit ADC
  average = SERIESRESISTOR / average;
  DEBUG(", Thermistor resistance ");
  DEBUG(average);

  float steinhart;
  steinhart = average / THERMISTORNOMINAL;           // (R/Ro)
  steinhart = log(steinhart);                        // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                         // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15);  // + (1/To)
  steinhart = 1.0 / steinhart;                       // Invert
  steinhart -= 273.15;                               // convert absolute temp to C

  DEBUG(", Temperature ");
  DEBUG(steinhart);
  DEBUG(" °C");
  return steinhart + 0.5;  // adding 0.5 prevents it always rounding down when turning float to int
}

void serialDataTransferTask() {
  static unsigned char i;
  if (phaseTwoCompleteFlag == true && userInterventionRequiredFlag == false && longButtonPressDetected == true) {
    Serial.println((String) "Switch,Temp1,Temp2,Temp3,Average123,Temp4,Temp5,Temp6,Average456");
    for (i = 0; i < NUMBEROFBIMETALLICSWITCHES; i++) {
      Serial.println((String)(i + 1) + "," + temperatureArray1[i] + "," + temperatureArray2[i] + "," + temperatureArray3[i] + ",=AVERAGE(B" + (i+2) + ":D" + (i+2) + ")," + temperatureArray1[i + NUMBEROFBIMETALLICSWITCHES] + "," + temperatureArray2[i + NUMBEROFBIMETALLICSWITCHES] + "," + temperatureArray3[i + NUMBEROFBIMETALLICSWITCHES] + ",=AVERAGE(F" + (i+2) + ":H" + (i+2) + ")");
    }
    delay(3000);
  }
}

void buttonPressDetection(const unsigned char BUTTON_PIN, bool &lastButtonState, bool &currentButtonState, unsigned long &buttonPressTimeStart, unsigned long &buttonPressTimeEnd, bool &buttonIsBeingPressed, bool &shortButtonPressDetected, bool &longButtonPressDetected) {
  // read the state of the switch/button:
  currentButtonState = digitalRead(BUTTON_PIN);

  if (lastButtonState == HIGH && currentButtonState == LOW) {  // button is pressed
    buttonPressTimeStart = millis();
    buttonIsBeingPressed = true;
    longButtonPressDetected = false;
  } else if (lastButtonState == LOW && currentButtonState == HIGH) {  // button is released
    buttonIsBeingPressed = false;
    buttonPressTimeEnd = millis();

    long pressDuration = buttonPressTimeEnd - buttonPressTimeStart;

    if (10 < pressDuration && pressDuration < SHORT_PRESS_TIME) {
      DEBUG("A short press is detected");
      shortButtonPressDetected = true;
    }
    longButtonPressDetected = false;
  }

  if (buttonIsBeingPressed == true && longButtonPressDetected == false) {
    long pressDuration = millis() - buttonPressTimeStart;

    if (pressDuration > LONG_PRESS_TIME) {
      DEBUG("A long press is detected");
      longButtonPressDetected = true;
    }
  }

  // save the last state
  lastButtonState = currentButtonState;
}

Then the first sketch is already almost an MRE. I didn't realize it was a complete compilable sketch (it is, right?). It isn't an MRE becuase M stands for minimum. Your example has a whole lot of code that still has nothing to do with the problem. Can you cut it down even further?

The first sketch I posted is compilable and demonstrates the problem. I will see what else can be removed.

In post #2, I explained how your problem might be in that section.

The reason I don't think that can be the problem is because I can see that phaseTwoCompleteFlag gets set to true (I have the information on certain flags being sent to serial via line 159). I therefore expect userInterventionRequiredFlag to be set to true like a picosecond after that!

Please post the serial debug output.

16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=1,10=1,7=1,6=1,5=1,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=1,10=1,7=1,6=1,5=1,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=1,11=1,10=1,7=1,6=1,5=1,initialState:0, phaseOne:0, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=1,15=1,14=1,13=1,12=1,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:1, buttonState:1, longButton:0
16=1,15=1,14=1,13=1,12=1,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:1, buttonState:1, longButton:0
16=1,15=1,14=1,13=1,12=1,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:1, buttonState:0, longButton:0
A short press is detected
16=1,15=1,14=1,13=1,12=1,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=1,14=1,13=1,12=1,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=1,12=0,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=1,10=1,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=1,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=1,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=1,6=1,5=1,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=1,5=0,initialState:1, phaseOne:1, phaseTwo:0, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0
16=0,15=0,14=0,13=0,12=0,11=0,10=0,7=0,6=0,5=0,initialState:1, phaseOne:1, phaseTwo:1, intervention:0, buttonState:1, longButton:0


I'm simulating the bimetallic switches with jumper wires which I just plug and unplug into ground.

Maybe because you never reset shortButtonPressDetected to false ?

1 Like

Preposterous!

You seem to be right. Thanks very much!

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