Questions/comments about Between Delay and State Machine - Commutable Delay Tutorial

Please post questions and comments about this tutorial here

Hi
When I run the code with the print lines I get this error:

C:\Users\lisac\AppData\Local\Temp\.arduinoIDE-unsaved20221030-24184-ljs85p.8sw1\sketch_nov30a\sketch_nov30a.ino: In function 'void commutableCatchPin(uint8_t, bool)':
C:\Users\lisac\AppData\Local\Temp\.arduinoIDE-unsaved20221030-24184-ljs85p.8sw1\sketch_nov30a\sketch_nov30a.ino:87:56: error: 'count' was not declared in this scope; did you mean 'std::count'?
In file included from c:\users\lisac\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\algorithm:74,
                 from C:\Users\lisac\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:225,
                 from C:\Users\lisac\AppData\Local\Temp\arduino-sketch-79AFF914588FF42E1764CD5A065AF844\sketch\sketch_nov30a.ino.cpp:1:
c:\users\lisac\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\include\c++\10.3.0\pstl\glue_algorithm_defs.h:101:1: note: 'std::count' declared here
  101 | count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value);
      | ^~~~~

exit status 1

Compilation error: 'count' was not declared in this scope; did you mean 'std::count'?

Thank you. I have now correct this error.

Some remarks (not criticism):

  • You may want to check the indentation and spacing in the examples.
  • You may want to use the early return pattern.
  • changePin and patternCountLimit could be made constants.
  • changePin is global but it is also passed to some functions.
  • Maybe a demo would be nice.

I am trying the code you did the tutorial on. I find that both cases now run simultaneously. Please see the code I modified to work with my D1 mini, breadboard and LED. It flashes flash1 (LED) and flash 2(builtin LED) both at the same time, not one then the other.
Thanks

/* commutableDelay with change state detection example by Grumpy_Mike Nov 2022
  example assumes change button is wired correctly - that is between input pin and ground
  note - remove the // to enable printing so you can see what is happening
  to extend this to more options alter the variable "patternCountLimit" 
  and add extra  cases to the switch statement

  This example code is in the public domain.
*/

uint8_t changePin = 16;          // or any other pin you want
uint8_t LED1 = 0;
uint8_t patternCount = 0;       // initial pattern value
uint8_t patternCountLimit = 2;  // how many patterns are they
bool commuted = false;

void setup() {
  Serial.begin(9600);                // for debug only
  pinMode(changePin, INPUT_PULLUP);  // for change pin wired between input and ground
  pinMode(LED1, OUTPUT);      // LED to flash
  Serial.println("code starting");
}

void loop() {
  Serial.println("start of loop");
  commutableCatchPin(changePin, LOW);
  // now see what function we want to call depending on the value in count
   Serial.println("Pattern number "); Serial.println(patternCount);
  switch (patternCount) {
    case 0:
      flash1();
      break;
    case 1:
      flash2();
      break;

    default:
      Serial.print("no such pattern as ");
      Serial.println(patternCount);
      break;
  }
}

// flash functions - these are just oversimplified examples to flash LED_BUILTIN
void flash1() {  // slow one second on & off
  for (int i = 0; i < 20; i++) {
    digitalWrite(LED1, HIGH);           // turn LED on
    commutableDelayPin(1000, changePin, LOW);  // one second delay
    digitalWrite(LED1, LOW);            // turn LED off
    commutableDelayPin(1000, changePin, LOW);  // one second delay
  }
}

void flash2() {
  for (int i = 0; i < 20; i++) {               //fast 200mS on & one second off
    digitalWrite(LED_BUILTIN, HIGH);           // turn LED on
    commutableDelayPin(3000, changePin, LOW);   // delay
    digitalWrite(LED_BUILTIN, LOW);            // turn LED off
    commutableDelayPin(1000, changePin, LOW);  // delay
  }
}

void commutableDelayPin(uint32_t delayTime, uint8_t changePin, bool commuteState) {  // this will return when the delay time has expired or the change button is pushed.
  uint32_t startTime = millis();                                                     // the millis count when we start;
  // now hold until either time is up or commute pin is pressed
  while ((millis() - startTime < delayTime) && (commuted != true)) {  // keep the loop going until time is up or delay is commutated
    if (digitalRead(changePin) == commuteState) {                     // if you see the button being held down abandon the delay
      commuted = true;
    }
  }
}

void commutableCatchPin(uint8_t changePin, bool commuteState) {  // check to see if the delay has been commuted and take action if it has been
  if (commuted) {                                                // we have had a commute state deal with it
    commuted = false;                                            // reset the global flag
    Serial.println("button pressed");
    while (digitalRead(changePin) == commuteState) {
      delay(50);  // do nothing until button is released
    }
    Serial.println("button released");
    delay(200);  // allow any button bouncing to stop
    // now take action for when a delay has been commutated
    // this could be to wipe an addressable LED string or to turn off the LED
    digitalWrite(LED_BUILTIN, LOW);  // turn LED off
    // move on the pattern to produce
    patternCount += 1;  // move onto next pattern
    if (patternCount >= patternCountLimit) {
      patternCount = 0;  // wrap round patternCount
    }
    Serial.print("count on button ");
    Serial.println(patternCount);
  }  // end of dealing with a commute
}

I'm not sure if I have gone wrong somewhere?
Thanks

Your debounce ... could be better.

When the buttons are a tiny part of something else that's busy, they should not hold up execution for even a single millisecond. Why? Because the non-delay parts of your code may run a few hundred cycles, there are 16000 cycles in 1 milli.

I've posted many examples that watched a button while flashing led13 and counting how many times loop runs each second and printing that at over 67000 Hz average.

Lately I read a button pin and update a variable with status so other code in loop() just reads that and the button handler just always runs.

No, that can't happen because it is the same LED that is flashing for both patterns. I think you are misunderstanding what you are seeing.

Yes but in the specific application this type of delay is designed to be used in, then this is not an issue.

Also I would profoundly disagree with this way of thinking. The use of a blocking delay has become almost a taboo on these pages. It has its uses in the correct circumstances, and the application I am describing it does not matter.

This tutorial is an intermediate step between fully blocking code and a complete state machine.

This single sentence seems rather dense - to me.

also might help to explain the reasoning why this is a bad thing. What would happen if I did that?

Could you include a picture of an arduino set up for this, or a schematic, to help me set it up to run through myself?
Thanks

There is nothing to set up apart from a push button on pin 8, wired between input and ground. This is explained in the writing.

If this needs any clarification then you do not know enough about electronics to be using this purely software feature.

You would destroy your Arduino.

How can I upload a video and show you? So someone can explain to me what I'm seeing?

I never said I didn't understand. I said it might help to add to your tutorial

So to follow up my previous post.. it works on my Uno, but does strange things on my D1 mini V4 so I'll have to play around and see whats going on

Never come across one of them. Do they need to address the pins with D8 and not just 8?

Upload it to YouTube and then post the link to the video.

Yes, otherwise it is pin of the chip that you are controlling rather than pin 8 of the board

D1 mini built in led Flash

I had no problem with doing the blink and blink without delay examples with the board. But with this sketch it speeds up briefly then slows down again. And has a double blink every other blink.

Thanks

That is because there was no push button in the circuit.

You don't wire up a push button on solderles bread board like this.

You wire it so that the switch straddles the middle of the bread board and then wire across either of the two diagonals of the switch.

Switch on bread board

Ok I think I’ve fixed it.

Try #2

Thanks