Graded timer and interrupt labs that run your sketch: two blink rates with millis(), count pulses in an interrupt, set Timer1 to 1 kHz, measure a period.
On the syllabus
Non-blocking timing with millis()
External interrupts, ISRs and volatile
Hardware timers: CTC mode, prescaler and compare value
Measuring pulse width and period with pulseIn
You will be able to
Run several timed tasks at once without delay().
Count fast events in an interrupt, and read the count safely.
Set a hardware timer for an exact frequency from the datasheet formula.
Measure a signal’s period, and tell it from its pulse width.
The first challenge is free. The rest, the viva and the certificate are part of Pro, and everything is here to read.
Graded challenges
Values like 4.7k, 100n or 2.2u are fine. Readings are the number only, in the unit shown. Every check measures the simulation, not a bench: ideal parts within their models, no noise.
1. Two blink rates without delay()
delay() stops everything. To run two tasks at once, let loop() spin freely and have each task check the clock: if its interval has passed, act and note the time.
Formulaif (now − last ≥ interval) { last += interval; act }
Worked exampleAn LED that toggles every 250 ms makes one cycle every 500 ms: 2 Hz. A second task at 100 ms toggles in between without waiting for it.
On the scope or meterTwo LEDs blinking at their own rates. The scope on each pin shows a steady square wave.
Your task
Pin 13 should make one cycle every second (500 ms on, 500 ms off) and pin 12 one every 400 ms (200 ms on, 200 ms off), independently.
The starter uses delay(), so each LED waits for the other and neither keeps its time. Rewrite it with millis().
2. Count pulses in an interrupt
Polling only sees an input when the code gets round to it. An interrupt runs a short function, the ISR, the moment an edge arrives, whatever loop() is doing.
Formulacounts a second = pulse frequency, with one count per rising edge
Worked exampleA 250 Hz signal into an ISR on RISING gives 250 counts each second. Polled with a delay(5) in the loop, it would miss most of them.
On the scope or meterThe serial monitor prints count= once a second. A missed pulse shows as a number a little short.
Your task
A 1 kHz pulse train arrives on pin 2. The sketch should print count= and the number of pulses each second: 1000.
The starter polls pin 2 with a delay(1) in loop(), so it misses pulses. Count them in an interrupt service routine instead.
3. Set Timer1 to 1 kHz
In CTC mode Timer1 counts up from 0 to OCR1A, then starts again. With the toggle setting, the pin flips at every match, so one full cycle takes two matches.
Formulaf = 16 MHz / (2 × N × (OCR1A + 1))
Worked exampleFor 2 kHz with prescaler N = 8: OCR1A + 1 = 16 000 000 / (2 × 8 × 2000) = 500, so OCR1A = 499.
On the scope or meterA clean square wave on pin 9 at 50% duty. Its period is set only by OCR1A and the prescaler, with no code running.
Your task
Timer1 runs in CTC mode with a prescaler of 8, so it counts at 16 MHz / 8 = 2 MHz, and toggles pin 9 every time it reaches OCR1A. Two toggles make one cycle.
The starter gives 500 Hz. Change OCR1A so pin 9 runs at 1 kHz: a 1.000 ms period, within 1%.
4. Measure a period with pulseIn
The period is one whole cycle: the high time plus the low time. The pulse width is the high time alone. They are equal only at 50% duty.
FormulaT = t_high + t_low = 1 / f
Worked exampleA 1 kHz wave at 25% duty is high for 250 µs and low for 750 µs: a 1000 µs period.
On the scope or meterOn the scope, the high part is narrower than the low part. The printed number from the starter is only the high part.
Your task
A signal generator puts a 2 kHz square wave with a 30% duty cycle on pin 2. The sketch should print us= and its period in microseconds.
The starter prints only how long the pulse is high. Fix it so it prints the whole period, within 2%.
Viva questions
The questions an examiner asks at the bench. 75% passes; every answer comes with why.