Graded Arduino digital I/O labs that run your own sketch: blink at a set period and duty, read and debounce a button, set a PWM duty, time a loop in assembly.
On the syllabus
Digital output, pinMode and timing with delay()
Digital input, floating pins and the internal pull-up
Switch bounce and debouncing in software
PWM output with analogWrite: frequency and duty cycle
Instruction cycles, and a delay loop written in AVR assembly
You will be able to
Drive an output at a set period and duty cycle.
Read a switch reliably with INPUT_PULLUP, and explain why a floating input fails.
Count presses of a bouncing switch correctly.
Set a PWM duty cycle and measure it on a scope.
Design a delay from instruction cycles and the clock frequency.
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. Blink at 2 Hz with a 25% duty cycle
A blink loop is a square wave you write by hand. The time the pin is high plus the time it is low is the period. The share of the period it is high is the duty cycle.
FormulaPeriod = t on + t off, duty = t on / period
Worked exampleFor 4 Hz at 50%: the period is 1 / 4 = 250 ms, so 125 ms on and 125 ms off. For 1 Hz at 10%: 100 ms on and 900 ms off.
On the scope or meterThe LED flashes. On the scope pin 13 is a square wave with the period and duty you chose.
Your task
The starter sketch blinks the LED on pin 13 once a second, half on and half off.
Change it so the LED flashes twice a second, on for a quarter of each cycle: a 500 ms period at 25% duty.
Build and run it in the simulator, then paste your sketch here and check it.
2. Read a button with INPUT_PULLUP
An input pin joined to nothing floats: it reads whatever noise it picks up. A pull-up resistor holds it at 5 V until a button pulls it to ground. The Uno has one built in, about 35 kΩ, that you switch on with the INPUT_PULLUP mode.
Worked exampleWith a 10 kΩ external pull-up on 5 V, a pressed button to ground takes 0.5 mA and the pin reads LOW. Released, the pin reads HIGH through the resistor.
On the scope or meterThe LED stays off until the press at 0.5 s, lights while held, and goes off after the release at 0.9 s.
Your task
A push button joins pin 2 to GND. There is no resistor in the circuit. The LED on pin 13 should light while the button is held.
The starter sets pin 2 as a plain INPUT and looks for HIGH. With the button up the pin is joined to nothing, so it floats.
Fix the sketch. The check presses the button from 0.5 s to 0.9 s.
3. Count presses of a bouncing switch
Switch contacts bounce for a few milliseconds when they close or open. Each bounce is an edge, so one press can look like five. Debouncing means only believing a new state once it has held still longer than the bounce.
FormulaAccept a change only after it is stable for t > bounce time (about 10 to 20 ms)
Worked exampleIf the contacts chatter for 5 ms, waiting until the pin has held one level for 10 ms is enough. A button that reads LOW at 0, 1, 3 and 4 ms and HIGH between them counts once, not three times.
On the scope or meterThe serial monitor prints count= after each counted press. Without debouncing the numbers jump by more than one a press.
Your task
A real switch bounces: for a few milliseconds after it closes or opens, its contacts make and break many times. This button bounces the way a typical one does.
The starter counts every falling edge and prints count= after each. The check presses the button three times; fix the sketch so the last line printed is count=3.
4. Set a PWM duty cycle
analogWrite does not make a voltage. It makes PWM: the pin switches between 0 V and 5 V at a fixed rate, about 490 Hz on pin 9, and the value sets how long it stays high in each cycle.
FormulaDuty = value / 255
Worked exampleanalogWrite(9, 191) gives 191 / 255 = 75% duty. analogWrite(9, 26) gives about 10%.
On the scope or meterA square wave at about 2 ms per cycle on the scope. The LED looks dimmer as the duty falls.
Your task
analogWrite(pin, value) on an Uno makes PWM: a square wave at about 490 Hz on pin 9, high for value/255 of each cycle.
Change the starter so pin 9 is high for 25% of each cycle, within 2 percentage points.
5. AVR assembly: count the cycles
Every AVR instruction costs a fixed number of clock cycles, printed in the data sheet. So a delay written in assembly is not a guess: you count the cycles one turn of the loop spends, and divide the time you want by it. The Uno runs at 16 MHz, so one cycle is 62.5 ns.
FormulaCycles = time × clock, turns = cycles / cycles per turn
Worked exampleFor 100 ms at 16 MHz: 0.1 × 16,000,000 = 1,600,000 cycles. At 4 cycles a turn that is 400,000 turns, which does not fit in a 16-bit counter, so it is split into an outer and an inner loop.
On the scope or meterOn the scope pin 13 is a square wave. Too few cycles and the period is milliseconds instead of half a second.
Your task
There is no delay() in this sketch. The delay is a counted loop written in AVR assembly, inside the C function with asm volatile, and the only thing that decides how long it lasts is how many clock cycles it spends.
One turn of the loop is 4 cycles: SBIW takes 2 and a taken BRNE takes 2. The starter runs 25,000 turns, which is 100,000 cycles, or 6.25 ms at 16 MHz, so the LED flickers instead of blinking.
Work out how many cycles 250 ms is, then wrap the loop so the delay spends that many. The check measures the blink on pin 13 and wants one whole cycle every 500 ms, within 2 percent.
Viva questions
The questions an examiner asks at the bench. 75% passes; every answer comes with why.