# nodeMCU - Millis() - Simple Counter - How long is LED on?

PROGRESS, now I have this (WITH GREAT HELP):

``````void setup() {
Serial.begin(9600);
// initialize digital pin 13 as an output.
}
uint32_t timer_start = 0;
int timer_running = false;

void loop()
{
// Get LDR information
int sensorValue = analogRead(A0);         // read the input on analog pin 0
float voltage = sensorValue * (5.0 / 1023.0);     // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V)
float lux = voltage * 100;

if (lux>150) {
if (!timer_running) {
// Timer is not already running, so capture the start time
timer_start = millis();
timer_running = true;
}
} else {
if (timer_running) {
// The timer is currently running; stop it calculate/print the run time
timer_running = false;
Serial.println((millis()-timer_start) / 1000.0, 3); // format however you like here

}
}

}
``````

This now tells me how many millis the gymnast is in the air, divided by 1000.0 with 3 decimals. If I start the Serial Monitor when the gymnast is in the trampoline bed, then I can get the seconds of air_time the gymnast has. Is there a way to have this script running ONLY for 10 loops?

• You test if the lux is above 150 and always execute that code as long as the lux is above 150. You need to know the moment that the lux is above 150 for the first time. Have a look at this example: arduino.cc/en/Tutorial/StateChangeDetection Turning millis into minutes and seconds can be done with /60 and %60 after the elapsed millis is divided by 1000.
– Jot
Oct 8 '18 at 15:18
• I think you need to maintain a `static unsigned long last_off = 0;` state variable in `loop{}`, resetting at the end of the else clause: `last_off = millis();` and also report at the beginning of the else clause if some `on_time=millis()-last_off` is greater than some threshhold. Are you having problems with the formatting? Or with calculating the on time? Oct 8 '18 at 15:20
• With your updated code, you did not maintain the same code structure as in the given example. In your updated code, the `if (lux>150) {...}` block has the timer start and stop code, where instead, the `if (lux>150) {...}` block should have the timer starting code, and the `else {...}` block (meaning, where `lux<=150`) should have the timer stopping code. Oct 10 '18 at 1:20

Declare a global (or static) boolean variable to keep track of whether the timer is running or not, as well as a variable to hold the start `millis()` value. When the lux drops below your threshold, subtract the current `millis()` from the start value, and you have the duration in milliseconds, which is trivial to convert to mm:ss.sss format.

Example code (not a complete sketch)

``````uint32_t timer_start = 0;
uint8_t timer_running = false;

void loop() {
if (lux>150) {
if (!timer_running) {
// Timer is not already running, so capture the start time
timer_start = millis();
timer_running = true;
}
} else {
if (timer_running) {
// The timer is currently running; stop it calculate/print the run time
timer_running = false;
Serial.print(millis()-timer_start); // format however you like here
}
}
}
``````

This now tells me how many millis the gymnast is in the air, divided by 1000.0 with 3 decimals. If I start the Serial Monitor when the gymnast is in the trampoline bed, then I can get the seconds of air_time the gymnast has. Is there a way to have this script running ONLY for 10 loops?

Certainly. If it is assumed that you want a cumulative total air-time, then you need to declare another global or static variable to hold the cumulative air-time, and you need to have another variable to keep track of how many cycles have passed.

``````void setup() {
Serial.begin(9600);
// initialize digital pin 13 as an output.
}
uint32_t timer_start = 0;
int timer_running = false;
uint32_t total_time = 0;
uint8_t jump_count = 0;

void loop()
{
// Get LDR information
int sensorValue = analogRead(A0);         // read the input on analog pin 0
float voltage = sensorValue * (5.0 / 1023.0);     // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V)
float lux = voltage * 100;

if (jump_count<10) {
if (lux>150) {
if (!timer_running) {
// Timer is not already running, so capture the start time
timer_start = millis();
timer_running = true;
}
} else {
if (timer_running) {
// The timer is currently running; stop it calculate/print the run time
timer_running = false;
// Add this-jump air time to the cumulative total:
total_time += millis()-timer_start;
// Increment jump_count
jump_count++;

Serial.println((millis()-timer_start) / 1000.0, 3); // format however you like here
}
}
} else {
// Print the total air-time for 10 jumps;
Serial.println((total_time)) / 1000.0, 3);
}
}
``````
• Why uint16_t and uint8_t? Why not just int? Oct 9 '18 at 15:55
• Those types are not critical. On Arduino, memory is tight, so it's simply a preference to use the smallest necessary variable type. `timer_running` can fit in the smallest type, `uint8_t`, while any result from `millis()` is an `unsigned long`, equivalent to `uint32_t` (fixed in the example code; should not have been `uint16_t`) Oct 9 '18 at 15:57
• Alright, thx. Now for the timer_running, what is the reason for the "!" exclamation mark? And does the timer go in the void setup, in the void loop or in between? Oct 9 '18 at 16:08
• `!` is the negation operator. So you are checking if NOT(timer_running) then do whatever. So if the timer is already running, you do not save the current millis() because you're already counting time. Oct 9 '18 at 16:10
• What it is counting? All I see are 1 and 0's? Oct 9 '18 at 20:08