const unsigned long BLINK_MS = 500;
unsigned long lastBlink = 0;
bool ledOn = false;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
unsigned long now = millis();
if (now - lastBlink >= BLINK_MS) {
lastBlink = now;
ledOn = !ledOn;
digitalWrite(LED_BUILTIN, ledOn);
}
// other jobs can run here every pass, for example reading a button
}Doing many jobs at once: millis() and state machines
Imagine you are cooking soup and also watching a pot of rice. If you stand still and stare at the soup for ten minutes, the rice burns. A good cook glances at the clock, does a bit of each job, and keeps moving. A good program does the same: it checks the clock instead of freezing.
- An embedded system is a small computer built into a device to do one set of jobs, usually with sensors in and actuators out. A microcontroller board is the usual starting point.
delay(1000)stops your code for a second. Nothing else (reading a button, updating a display) can run during it.millis()returns the milliseconds passed since the program began. Its data type is unsigned long, and it overflows (goes back to zero) after about 50 days.- Non-blocking timing pattern: save the time of the last action, and each pass through
loop()check whether enough time has gone by. Compare with subtraction:now - last >= interval. With unsigned numbers, subtraction keeps working even when the counter wraps back to zero. - A state machine is a program that is always in exactly one named state (for example IDLE, MEASURING, ALARM) and has rules for moving to the next state. It keeps long programs organised and easy to test.
| State | What it does | Moves to |
|---|---|---|
| IDLE | Waits | MEASURING every 2 seconds |
| MEASURING | Reads the sensor | ALARM if the value is too high, otherwise IDLE |
| ALARM | Flashes an LED | IDLE when a button is pressed |
- Open the Arduino IDE and start a new sketch.
- Type the non-blocking blink from the lesson and upload it.
- Add a second job in
loop()that printsmillis()once per second using its ownlastvariable and the same subtraction pattern. - Watch the LED blink and the Serial Monitor print at the same time.
- Replace one
delay()in an old sketch of yours with the millis() pattern. - Draw the state table for a project idea: states, what each does, and what moves it to the next state.
- Check: two jobs run at different rhythms and neither one freezes the other.
Videos by other creators on YouTube, for reference. They are not made by or affiliated with The Future Market.
Read the video script
[Host] "Delay is a trap. While your code sleeps, it cannot see a button or a sensor."
[Screen: timeline with two blinking LEDs at different speeds] "Instead, ask the clock: how long since I last did this?"
[Text on screen: now - last >= interval] "Subtract, compare, and update the time you last acted."
[Screen: three boxes IDLE, MEASURING, ALARM with arrows] "Then give your program named states. It is always in exactly one."
[Host] "Small tasks, a clock and states: that is how real devices multitask."
Write a sketch that blinks one LED every 300 ms and prints a counter every 2 seconds, with no delay() anywhere. Then draw its state table on paper. If you have no board, use a free simulator and print messages instead of lighting an LED.
ClaudeStuck? Copy a ready-made prompt for Claude
Copy this, open Claude, paste it, and Claude will walk you through the lesson step by step.
For a grown-up: Claude is for adults (18+). Copy this, paste it into Claude, and use the answer to explain the lesson to your child.
I'm learning "Embedded Systems: microcontrollers and sensors" on The Future Market. Lesson 1: "Doing many jobs at once: millis() and state machines". What the lesson teaches: - An embedded system is a small computer built into a device to do one set of jobs, usually with sensors in and actuators out. A microcontroller board is the usual starting point. - delay(1000) stops your code for a second. Nothing else (reading a button, updating a display) can run during it. - millis() returns the milliseconds passed since the program began. Its data type is unsigned long, and it overflows (goes back to zero) after about 50 days. - Non-blocking timing pattern: save the time of the last action, and each pass through loop() check whether enough time has gone by. Compare with subtraction: now - last >= interval. With unsigned numbers, subtraction keeps working even when the counter wraps back to zero. - A state machine is a program that is always in exactly one named state (for example IDLE, MEASURING, ALARM) and has rules for moving to the next state. It keeps long programs organised and easy to test. The exercise I'm working on: Write a sketch that blinks one LED every 300 ms and prints a counter every 2 seconds, with no delay() anywhere. Then draw its state table on paper. If you have no board, use a free simulator and print messages instead of lighting an LED. I'm stuck. Please: 1. Explain the main idea in plain, simple words with one everyday example. 2. Walk me through the exercise one small step at a time. Ask me what I've done so far before giving the next step. 3. Don't just give me the final answer. Help me do it myself, and check my work when I share it.
I'm a parent helping my child (about 8 years old) with a lesson called "Doing many jobs at once: millis() and state machines" from the course "Embedded Systems: microcontrollers and sensors". Here's what the lesson says: Imagine you are cooking soup and also watching a pot of rice. If you stand still and stare at the soup for ten minutes, the rice burns. A good cook glances at the clock, does a bit of each job, and keeps moving. A good program does the same: it checks the clock instead of freezing. The activity: Write a sketch that blinks one LED every 300 ms and prints a counter every 2 seconds, with no delay() anywhere. Then draw its state table on paper. If you have no board, use a free simulator and print messages instead of lighting an LED. Please explain this so an 8-year-old understands: short sentences, a fun everyday example, and no hard words. Then give me 3 simple questions I can ask my child to check they understood, and a way to do the activity together, one tiny step at a time.
Sources
- Arduino reference, millis() (unsigned long, overflows after about 50 days): github.com/arduino/reference-en/blob/master/Language/Functions/Time/mi
- Arduino reference, Language Reference: docs.arduino.cc/language-reference/
Reliable inputs: pull-ups and debouncing
This lesson is part of full access: every course and every level for one payment.
Interrupts: reacting right now
This lesson is part of full access: every course and every level for one payment.
From voltage to real units: ADCs, dividers and calibration
This lesson is part of full access: every course and every level for one payment.
Talking to chips: UART, I2C and SPI
This lesson is part of full access: every course and every level for one payment.
Power, voltage levels and battery life
This lesson is part of full access: every course and every level for one payment.
Testing, debugging and a graded project plan
This lesson is part of full access: every course and every level for one payment.
Final project
This lesson is part of full access: every course and every level for one payment.
Quiz
Why avoid
delay()in a multitasking program?It stops everything else, including reading inputs.
What does
millis()return, and when does it overflow?Milliseconds since the program started, as an unsigned long; it wraps to zero after about 50 days.
Why does
now - last >= intervalstill work after millis() wraps?Unsigned subtraction still gives the right elapsed time.
What does
INPUT_PULLUPdo, and how does a button read?It turns on an internal pull-up (about 20 kohm); a button to ground reads HIGH when open and LOW when pressed.
What is switch bounce?
The contacts open and close several times for a few milliseconds, so one press can look like many.
Which pins support interrupts on an Uno Rev3?
Pins 2 and 3.
What should you not do inside an ISR?
Use delay() or rely on millis(); keep it short and do the main work in loop().
Why mark shared ISR variables volatile?
They can change at any time, so the compiler must not assume they stay the same.
How big is one step of the Uno's ADC with a 5 V reference?
About 4.9 mV (5 V / 1024, 10-bit, 0 to 1023).
In a divider with Vin = 5 V and R1 = R2, what is Vout?
2.5 V.
Which Uno pins are I2C SDA and SCL?
A4 (SDA) and A5 (SCL).
What does SPI use to choose which device talks?
A chip-select (CS) pin, pulled LOW for the chosen device.
A battery holds 1,000 mAh and the project averages 5 mA. About how long does it last?
About 200 hours (a rough estimate).
Final exam
This lesson is part of full access: every course and every level for one payment.
Certificate
This lesson is part of full access: every course and every level for one payment.