I could use help testing an example, I lack a jumper at present!

The code works except for testing when a jumper is grounded or pulled from ground. Or if a button is pressed or not.

The jumper is used to switch code modes between delay and millis mode, the sketch shows how they behave differently. It uses Serial Monitor and sending Enter key works to pause and unpause printing so that data can be stopped and examined.

It's a demo and at present I lack a jumper to finish testing.
IMO it's at least half decently commented and should not be beyond most beginners, but I know there's nits to pick.

// DualActionDelayMillis v1.1 by GoForSmoke 11/18/24 -- made for Uno R3
// expect: ground pin 7 to run delay mode, not grounded runs millis mode
// expect: enter key in Serial Monitor to pause action, unpause action

// note that Arduino millis is +/-1 and that printing takes time as well!

const byte blinkPin = 13; // Uno board LED pin13

const byte jumperPin = 7; // a jumper from pin 7 to GND or pin 7 unterminated

byte jumperStateNow, jumperStatePrev; // to compare what is to what was
const word debounce = 20; // ms delay while the contacts settle, dirty signal

byte blinkState;  // led13 0=OFF, not-0=ON

const unsigned long interval1 = 5000;
unsigned long start1;
byte started1 = 0;
const unsigned long interval2 = 1000;
unsigned long start2;
byte started2 = 0;

void usage()
{
  Serial.println( F( "\n    Dual Action Delay Millis \n" ));
  Serial.println( F( "    ground pin 7 to run delay mode, not grounded runs millis mode" ));
  Serial.println( F( "    Send enter key in Serial Monitor to pause action, unpause action \n\n" ));
}

void setup()
{
  Serial.begin( 115200 ); // run serial fast to clear the output buffer fast
  // set Serial Monitor to match

  pinMode( blinkPin, OUTPUT ); // LOW by default
  // blinkState is 0 by default
  pinMode( jumperPin, INPUT_PULLUP );
  jumperStateNow = jumperStatePrev = digitalRead( jumperPin );
}

void loop()
{
  //  ============================ change mode with jumper =======
  jumperStateNow = digitalRead( jumperPin );    // check for mode change
  if ( jumperStateNow != jumperStatePrev )      // if jumperPin changes state, stop and debounce then re-init
  {
    while ( jumperStateNow != jumperStatePrev )
    {
      jumperStatePrev = jumperStateNow;
      delay( debounce );
      jumperStateNow = digitalRead( jumperPin );
    } // finished debounce

    started1 = started2 = 0; // init for millis mode
  }
  //  ============================ end change mode with jumper =======

  //  ============================ millis mode ===================
  if ( jumperStateNow > 0 ) // run millis mode
  {
    if ( started1 == 0 )
    {
      started1 = 1;
      Serial.print( F( "Millis Wait " ));
      Serial.print( interval1 );
      Serial.print( F( " time " ));
      Serial.println( millis());
      start1 = millis();
    }

    if ( started2 == 0 )
    {
      started2 = 1;
      Serial.print( F( "Millis Wait " ));
      Serial.print( interval2 );
      Serial.print( F( " time " ));
      Serial.println( millis());
      start2 = millis();
    }

    if ( millis() - start1 >= interval1 )
    {
      started1 = 0;
      Serial.print( F( "Finished Millis Wait " ));
      Serial.print( interval1 );
      Serial.print( F( " time " ));
      Serial.println( millis());
    }

    if ( millis() - start2 >= interval2 )
    {
      started2 = 0;
      Serial.print( F( "Finished Millis Wait " ));
      Serial.print( interval2 );
      Serial.print( F( " time " ));
      Serial.println( millis());
    }
  }
  //  ============================ end millis mode ===================

  //  ============================ delay mode ===================
  else // run delay mode
  {
    Serial.print( F( "Delay " ));
    Serial.print( interval1 );
    Serial.print( F( " time " ));
    Serial.println( millis());
    delay( interval1 );
    Serial.print( F( "Finished Delay " ));
    Serial.print( interval1 );
    Serial.print( F( " time " ));
    Serial.println( millis());

    Serial.print( F( "Delay " ));
    Serial.print( interval2 );
    Serial.print( F( " time " ));
    Serial.println( millis());
    delay( interval2 );
    Serial.print( F( "Finished Delay " ));
    Serial.print( interval2 );
    Serial.print( F( " time " ));
    Serial.println( millis());
  }
  //  ============================ end delay mode ===================

  //  ============================ pause from serial monitor=====
  if ( Serial.available())  // enter serial to pause
  {
    usage();

    while ( Serial.available())
    {
      Serial.read(); // empty the buffer
    }

    while ( !Serial.available());  // wait for unpause

    while ( Serial.available())
    {
      Serial.read(); // empty the buffer
    }

    started1 = started2 = 0; // re-init millis mode
  }
  //  ============================ end pause from serial monitor=====
}
1 Like

GoForSmoke,

Here are the results, tested using an Arduino Uno R3.

With a Jumper fitted:

Delay 5000 time 0
Finished Delay 5000 time 5000
Delay 1000 time 5001
Finished Delay 1000 time 6001
Delay 5000 time 6001
Finished Delay 5000 time 11002
Delay 1000 time 11002
Finished Delay 1000 time 12003
Delay 5000 time 12004
Finished Delay 5000 time 17004
Delay 1000 time 17005
Finished Delay 1000 time 18006
Delay 5000 time 18007
Finished Delay 5000 time 23007
Delay 1000 time 23008
Finished Delay 1000 time 24008
Delay 5000 time 24008
Finished Delay 5000 time 29009
Delay 1000 time 29009
Finished Delay 1000 time 30011
Delay 5000 time 30011
Finished Delay 5000 time 35012
Delay 1000 time 35012
Finished Delay 1000 time 36013
Delay 5000 time 36014

And without the Jumper:

Millis Wait 5000 time 0
Millis Wait 1000 time 0
Finished Millis Wait 1000 time 1000
Millis Wait 1000 time 1000
Finished Millis Wait 1000 time 2001
Millis Wait 1000 time 2001
Finished Millis Wait 1000 time 3002
Millis Wait 1000 time 3002
Finished Millis Wait 1000 time 4003
Millis Wait 1000 time 4003
Finished Millis Wait 5000 time 5000
Millis Wait 5000 time 5000
Finished Millis Wait 1000 time 5004
Millis Wait 1000 time 5004
Finished Millis Wait 1000 time 6005
Millis Wait 1000 time 6005
Finished Millis Wait 1000 time 7006
Millis Wait 1000 time 7006
Finished Millis Wait 1000 time 8007
Millis Wait 1000 time 8007
Finished Millis Wait 1000 time 9008
Millis Wait 1000 time 9008
Finished Millis Wait 5000 time 10001
Millis Wait 5000 time 10001
Finished Millis Wait 1000 time 10009
Millis Wait 1000 time 10009
Finished Millis Wait 1000 time 11010
Millis Wait 1000 time 11010

you can test in wokwi. I just added a button on the jumperPin

I was concerned about when changing modes during operation if there was any unexpected behavior.

I don't expect any problem but without testing I'll stick with Murphy.

I was able to check the action and think that maybe interval2 = 1100 would provide a better millis mode demo, or a value where interval2 sometimes starts and finishes across start or end of interval1.

Do note the creep of a milli here and there.

Do Wokwi buttons bounce? I want to know if I got the debounce right. I expect I did but some buttons IRL are very dirty.

Here's the answer from docs.wokwi.com/parts/wokwi-pushbutton:

Wokwi simulates button bouncing by default. You can disable bouncing simulation by setting the "bounce" attr to "0":

{ "bounce": "0" }

The bouncing simulation follows the behaviour described in "The Art of electronics" by Horowitz & Hill:

When the switch is closed, the two contacts actually separate and reconnect, typically 10 to 100 times over a period of about 1ms.

I am guessing then that the attribute can be set for very dirty buttons indeed. I used a delay of 20ms since change from millis mode means go into delay mode and change from delay mode... it's already using delay so wth?

I will change interval2 when I use this to show the difference between blocking and non-blocking code. It may be the best demo I've come up with on the subject.

A button has to be held down. A jumper can be placed in GND to run delay mode and in any IO pin hole (default INPUT LOW not being read is Zero State) to run millis mode.

In wokwi, if you want the button to stay pressed until the next click, you can ⌘ cmdclick it on Mac or ctrlclick it with windows.

I am no fan of Wokwi simply because it's not real.
Maybe I should anyway since the hardware is so well known and they do put effort into simulating it right.

When I was in my first years of programming there was the 99 year bug adage that "all software has bugs". I liked it because it made my work look good.

I find wokwi pretty accurate for a 328P

I try and aim examples and demos at Uno R3.