How to count millis?

I built an 8 head peristaltic pump controlled with a TIP120 circuit (times eight). I am now trying locate some code that counts the duration a digital pin is HIGH and print that to the serial monitor. I need to know how many seconds/milliseconds it takes for a pump to produce 100 ml. This will give me the base numbers I need to generate code for each of the pumps for later use. I admit I am near clueless regarding the use of millis() and have been spending many hours for the last few days trying to find the best word combo to type into the search engine, but little to no luck. I've read a few writings by Nick Gammon, but most of it is way over my head and as best I can tell, does not cover using millis() this way.

Here is the sketch I wrote that does not count properly. The serial monitor was printing numbers every fraction of second, too fast for me to comprehend, but all in single digit per line. I was hoping to generate a one line number sequence that would tell me how long the button held the pin HIGH for. Can someone please help?


int button = 30;                    // Button connected to digital 30 with a 10k pulldown resistor to GND
int pump = 9;                       // pump on digital pin 9
unsigned long currentMillis = 0;    //  
unsigned long previousMillis = 0;   // 
unsigned long totalMillis = 0;

//========== THE SETUP ==============================

void setup() {

  pinMode(button, INPUT);
  pinMode(pump, OUTPUT);

//========== THE LOOP ==============================

void loop() {
  if (digitalRead(button) == HIGH)
    previousMillis = millis();   // capture the beginning value of millis()
    analogWrite(pump, 255);

  else if (digitalRead(button) == LOW)
    currentMillis = millis();   // capture the ending value of millis()
    analogWrite(pump, 0);
  totalMillis = currentMillis - previousMillis;

P.S. I added a 2 second delay to slow the output, still no good.

You need a state change detection. You need to set previousMillis when the button state goes from low to high (becomes pressed) and need to set currentMillis when the button goes from high to low (is released). You need a variable to remember the previous state of the button when the state changes. You probably also need to debounce your button.

And if you want to display the duration that the button was pressed, only print on the change from high to low.

Try this:

uint32_t start, eTime, dbStart;
const byte btn = 30, pumpPin = 9, dbTime = 20;
bool pinState = true,
        btnState = true,
        timing = false;
void setup()
  pinMode(btn, INPUT_PULLUP);
  pinMode(pumpPin, OUTPUT);

void loop()
  // debounce button ++++++++++++++++
  if (digitalRead(btn) != pinState) // get state of pin 30
    dbStart = millis(); // reset db timer
    pinState ^= 1;      // now they are equal, won't enter
  }                     // here again unless pin state changes
  if (millis() - dbStart > dbTime) // db timer has elapsed
    btnState = pinState;           // button state is valid
  if (btnState == LOW && !timing)
    start = millis(); // start timing
    analogWrite(pumpPin, 255);
    timing = true;
    Serial.println(F("  Timing"));
  if(btnState == HIGH && timing)
    analogWrite(pumpPin, 0);
    eTime = (millis() - start);
    Serial.print(F("  Elapsed millis = "));
    timing = false;


EDIT: Changed pin # to 30.

Thank you both! @756E6C, to use INPUT_PULLUP, how should the button circuit be wired? In the TIP120 example, the diagram calls for a 10k pull down resistor to GND. I presume I should remove it, but would the remainder of the circuit regarding the botton be correct? Leg to 5V and leg to D30? Or would the sketch still work if I changed the mode from INPUT_PULLUP to just INPUT, and left the 10k pull down resistor in the circuit?

Using a pullup (internal or external) vs a pulldown (external) just means the logic is reversed.

  • With a pulldown, the resistor holds the pin low so when pressed it's high.

  • With a pullup, the resistor holds the pin high and the connection through the switch is now wired to ground, so when pressed it's low.

So you need to account for that in your code. If you wanted say to switch a led on when the button is pressed, with pulldown your "if" will test for high (it's low normally) but with a pullup you test for low (it's high normally)

The wiring is different: with a pulldown the switch goes to 5V, with a pullup it goes to ground.

Here's what Wikipedia says.

Thank you manor_royal for clearing up my confusion and thank you 756E6C for the sketch, it does exactly what I was looking to do.