How to "do something" for a known amount of millis()?

I have been trying to write this sketch for the better part of a month, but my lack of understanding in code, but especially with regard to how to use millis() is preventing me from advancing. I've successfully gathered the values of 2 variables that when multiplied, output the amount of millis() I want the digital pin to be HIGH for. Syntax errors aside, I think my problem is that I really don't know how to reference the millis() clock, and my very best attempts have all produced less than favorable results.

I typed some additional comments on the top of the sketch to outline the circuit, and how Blynk is used (to an extent). I also have my app fitted with a monitor for printing. I want the code to watch for a button press, and when pressed, execute the remainder of the function. Once complete, reset everything back to the default states of 0, LOW and false.

My hope is that someone will assist me in structuring my math correctly. To date, I have learned far more from working code than I have from tutorials or general reading. Kind of like learning how to fix something by first taking it apart.

Oops, I forgot to mention there is one catch, because of the way Blynk is structured, I absolutely cannot use delays or Blynk will crash and my project needs Blynk.

This is to be a sketch to run a peristaltic pump with Arduino and Blynk.  The circuit is an Ethernet Shield on a Mega
with an LED connected to D3\GND.  Somewhere on the internet, Blynk runs an Android\iPhone app.  On my app, I have a button
rendered as a switch (on/off) and a step value incrementer\decrementer.  A value between 0.00-80.00 in 0.25 steps is dialed 
in according to human preference.  Once at desired value, button is pressed and the rest of the sketch can run.

With a seperate sketch, I was able to run each (of 8) pumps till 100ml of koolaid was dispensed while millis was being 
counted.  I did this 3 times and averaged the millis count per each motor, then divided that by 100 to derive the multiplier.
When the multiplier is multiplied with the step value, the total amount of milliseconds to produce the desired amount of 
ml is known.
#include <SPI.h>                           //Used by Blynk
#include <Ethernet.h>                      //Used by Blynk
#include <BlynkSimpleEthernet.h>           //Used by Blynk
#include <SimpleTimer.h>
#define BLYNK_PRINT Serial
char auth[] = "PasteAuthTokenHere";       //Paste code that app emailed you between "quotes"

int buttonState;                           //expecting 0 or 1
float stepValue;                           //expecting 0.00-80.00
#define pump 3                             //Pump connected @ D3
float runCount;                            //Step Widget to determine amount of ml/Output 0-80/Step 0.2                              //
uint32_t startCount;                       //Millis reference used to calculate stopCount
uint32_t stopCount;                        //
uint32_t multiplier = 858;                 //Number of milliseconds for motor to produce 1ml of liquid
SimpleTimer timer;                         // SimpleTimer instance named timer
WidgetTerminal terminal(V2);

void setup()
  while (Blynk.connect() == false) {}
  timer.setInterval(1500L, checkPump);     
  pinMode(pump, OUTPUT);
  analogWrite(pump, 0);

void loop()

BLYNK_WRITE(V1) {                   // button
  buttonState = param.asInt();      // a button press triggers the code into action
  Blynk.syncVirtual(V1);            // trigger V1 function below to set current stepValue from widget

BLYNK_WRITE(V0) {                   // step
  stepValue = param.asFloat();      // 0.00-80,00\0.25 per step.  Once desired value is set, press button on V1

void checkPump()
  boolean Running = false;
  if (buttonState == 1)
    runCount = stepValue * multiplier;             //Step Widget Value times Calibration Multiplier
    startCount = millis() + runCount;              
    stopCount = millis() - runCount;
    terminal.print("stepValue is: ");
    terminal.print("runCount: ");
    terminal.print("startCount is: ");
    terminal.print("stopCount is: ");

  if (startCount < stopCount) Running = true;           
  //for (int x = startCount; x < stopCount; x++)

  if (Running == true)
    analogWrite(pump, 255);
    Blynk.virtualWrite(buttonState, 0);
    Blynk.virtualWrite(stepValue, 0);


    //startCount + runCount > stopCount;
    analogWrite(pump, 0);
    //runCount = 0;
    //startCount = 0;
    //stopCount = 0;


millis gives you a snapshot of elapsed time when it's invoked.
So these two lines:

    startCount = millis() + runCount;              
    stopCount = millis() - runCount;

mean that startCount is almost certainly greater than or equal to StopCount unless runCount is zero and millis ticked over between calls.

Therefore this if:

 if (startCount < stopCount) Running = true;

Will virtually never be true.

Let's say millis returns 5000 and runCount is 10. Substituting, your if is doing this:

 if (5010 < 4090) Running = true;

So although the button was pressed, running does not become true and the pump stays off.

It's more conventional to set the start time and use millis with subtraction. So when your button becomes pressed do this:


and where you're checking to see if it's time to stop:

if(millis()-startTime > RunTime)

I'm not clear whether your button in your blink app stays on. If it does, be sure that you're checking that it became pressed, not that it is pressed.

Have a look at how millis() is used to manage timing in Several things at a time


I'm not clear whether your button in your blink app stays on. If it does, be sure that you're checking that it became pressed, not that it is pressed.

I've had a few runs where the button was defaulted back to 0;, but I've tried so many different approaches, that I'm frequently commenting stuff out, or changing, deleting, rewriting etc trying to broaden my knowledge while in search of the result I seek. Blynk.virtualWrite() is how to send values back to the app. I would also use it to change the stepValue back to 0; once the button is ticked, but having bad code, the value defaults to 0; while I'm trying to dial it up to a higher number.

What you said testing with subtraction makes a lot of sense. I am especially eager to try;

if(millis()-startTime > RunTime)

This appears to be promising.

Can you provide an example of how to check if a button becomes pressed vs a button that is already pressed? My guess is

  boolean Running = false;
  if (buttonState == 1 && !Running)

but perhaps additional booleans may be needed. That aside, once I have functional code to make a pin HIGH for the desired duration, I am confident I can slim down the rest of the code to what is applicable, and the button and step counter will both be reset prior to the pin returning to LOW. That said, would the code even need to know the difference between "became pressed" vs "already pressed"?

Can you provide an example of how to check if a button becomes pressed vs a button that is already pressed?

Why? Can you not use the one that came pre-loaded with the IDE? State Change Example

Here's a short example of "launch if input goes HIGH";

uint32_t startCount; 
uint32_t stopCount;
const byte pump = 3;
bool buttonState = false, oldButtonState = false, running = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(pump, OUTPUT);

void loop() {
  // put your main code here, to run repeatedly:
  stopCount = 5000UL; // example, must be unsigned long integer
  if (running == false && buttonState != oldButtonState
                && buttonState == true) // launch!
    buttonState = oldButtonState;
    startCount = millis();
    running = true; // launched
    analogWrite(pump, 255);
  if (millis() - startCount > stopCount)
    analogWrite(pump, 0);
    running = false; // done