Assessment Practice: Tasks A & B
Rehearse the two assessed practicals in the simulator: a two-button speed selector that reports every change, and a sensor alarm with hysteresis that fails safe when the sensor breaks.
What this chapter is for
Two of the practical assessments are built and marked on the bench, with real buttons, a real sensor and a scope. This chapter rehearses the part that catches most people out: not the wiring, but the logic.
- Task A: Extractor Fan Speed Selector - one button, three speeds, one Serial line per change
- Task B: Cabinet Over-Temperature Alarm - a sensor, two thresholds, and an alarm that must never fail quiet
Work through the exercises here until they pass first time. Then you can spend the assessment sessions on the build, the measurements and the evidence, instead of debugging the logic.
Read this first. Passing the tests here is *not* the assessment and it is not evidence. The tasks are marked on your plan, your wiring, your measurements, your test table and your explanation. The simulator has no transistor, no oscilloscope and no thermistor - it only checks that your code decides the right thing.
Task A: one state variable runs everything
The fan has three speeds: OFF, LOW and HIGH. The temptation is to scatter analogWrite() calls all over the sketch. Don't. Keep one variable that says which state you are in, and one function that makes the outputs match it:
- the buttons only ever change
state showState()sets the fan, sets the running LED and prints one line
That is why the brief asks for exactly one Serial line per change: if showState() is only called when the state actually changed, you get that for free. Printing in loop() instead floods the monitor and fails the criterion.
The duty values come straight from the brief: OFF is 0, LOW is 40% which is 102, and HIGH is 100% which is 255. Give them names - DUTY_OFF, DUTY_LOW and DUTY_HIGH - because the names make the sketch much easier to explain to the assessor.
| State | Fan D6 (PWM) | Running LED D5 | Serial line |
|---|---|---|---|
| OFF | 0 | off | Fan: OFF (0%) |
| LOW | 102 (40%) | on | Fan: LOW (40%) |
| HIGH | 255 (100%) | on | Fan: HIGH (100%) |
The three states, stepped by a timer
No buttons yet - this just walks through the three states so you can watch the two LEDs and read the Serial Monitor. The named constants are worth copying: SPEED_LOW says far more than 1.
Fan: OFF (0%) Fan: LOW (40%) Fan: HIGH (100%) Fan: OFF (0%)
- The fan LED is on a
~pin so it can dim. The running LED is only ever on or off. showState()is called once insetup()so the outputs are right before anything is pressed.delay(1000)is only here so the demo steps on its own. Your bench sketch steps on the buttons, using the debounce code given on the Task A brief.
Make the outputs match the state
Before the buttons, get the outputs right. state is already declared; the tests set it to each of the three values in turn and check both LEDs.
In loop(), drive the fan on D6 and the running LED on D5 from state:
SPEED_OFF- fanDUTY_OFF, running LED offSPEED_LOW- fanDUTY_LOW, running LED onSPEED_HIGH- fanDUTY_HIGH, running LED on
To try it yourself, change int state = SPEED_OFF; to SPEED_LOW (or SPEED_HIGH) and press Run.
Button A steps through the speeds
showState() is written for you at the bottom, and setup() already calls it once so the outputs are right at start-up - that prints the first Fan: OFF (0%) line. All you have to write is the bit that changes state.
On each new press of Button A on D2, step OFF → LOW → HIGH → OFF and call showState() once. Nothing must be printed while the button is simply held down.
Fan: OFF (0%) Fan: LOW (40%) Fan: HIGH (100%) Fan: OFF (0%)
Button B stops the fan
Extra practice - Task A only needs Button A. Add Button B on D3. A new press returns the fan to SPEED_OFF from any speed.
One catch: the sketch prints one line per change. Pressing B when the fan is already off changes nothing, so it must print nothing.
Fan: OFF (0%) Fan: LOW (40%) Fan: HIGH (100%) Fan: OFF (0%) Fan: LOW (40%)
Twenty presses, twenty steps
Extra practice - not needed for Task A. This is the millis() way to debounce two buttons, for sketches that must keep doing other things while they wait. Real contacts chatter, and the test below now feeds your sketch that chatter: without debounce, two presses arrive as six steps.
The debounce timers are already written, with the same names as the Buttons & Debounce chapter - one per button. When a raw reading moves, that button's 20 ms clock starts again. Your job is the two blocks inside them: act on a button only when its trusted reading (stableA) is still HIGH and its settled reading (lastReadingA) is LOW.
Fan: OFF (0%) Fan: LOW (40%) Fan: HIGH (100%)
Task B: two thresholds, and never fail quiet
Task B watches a cabinet and sounds an alarm when it overheats. On the bench the sensor is a thermistor and you convert its reading to °C with the Beta equation. Here we work in raw ADC counts so the exercise is about the two decisions that are actually marked - hysteresis and the fail-safe. Drag the slider to change the reading; higher means hotter.
Hysteresis means using two thresholds instead of one. With a single threshold at 700, a reading that wobbles 699, 701, 699, 701 switches the alarm on and off several times a second. So: switch on at 700 or above, and only switch off again at 600 or below. Between 601 and 699 nothing changes - whatever the alarm is doing, it keeps doing.
Fail-safe means deciding what a broken sensor should do. An unplugged thermistor reads either 0 or 1023, and neither is a real temperature. An alarm that stays quiet because its sensor fell off is worse than useless, so a fault must switch the alarm on.
| Reading | Alarm off now | Alarm on now |
|---|---|---|
| 0 or 1023 | fault - switch on | fault - stay on |
| 601-699 | stay off | stay on |
| 700 and above | switch on | stay on |
| 600 and below | stay off | switch off |
What the sensor is doing
Run this, then drag the slider. It prints the reading twice a second so you can see the range the thresholds sit in. The alarm LED is not wired up yet - that is the next exercise.
Sensor: 300 Sensor: 300 Sensor: 300
- Dragging the slider while the sketch runs is the simulator's version of warming the thermistor with your hand.
- 0 and 1023 are the ends of the slider - use them later to pretend the sensor has fallen off.
One threshold
Start with the naive version, so you can see what is wrong with it.
Read A0 and switch the alarm LED on D8 on when the reading is 700 or more, and off when it is below 700.
Add the hysteresis
Now the real requirement. Keep a variable that remembers whether the alarm is on, and use two thresholds:
- alarm off and the reading reaches 700 or more - switch on
- alarm on and the reading falls to 600 or less - switch off
- anywhere in between - leave it alone
The test walks the reading up to exactly 700, back down to 650, and only then down to exactly 600. The alarm must still be on at 650 on the way down, and off at 650 on the way up.
Fail safe, and report every change
The last two requirements together. There are now three states, and the constants and the reporting code are already written - you write the decision.
- reading is
0or1023- the sensor is broken: stateFAULT - coming back from
FAULTwith a sensible reading - back toNORMAL NORMALand 700 or more -ALARMALARMand 600 or less -NORMAL
The alarm output is on in ALARM and in FAULT. That one line is the difference between a Competent and a Not Yet Competent on the fail-safe criterion.
NORMAL ALARM NORMAL SENSOR FAULT NORMAL
The state on the LCD
Task B is marked on the display too: *both LCD rows are clean in every state, with no leftover or overlapping characters*. SENSOR FAULT is 12 characters and ALARM is 5, so printing ALARM over SENSOR FAULT leaves ALARMR FAULT on the screen.
Finish showState() so row 2 (setCursor(0, 1)) always shows the state padded to 12 characters. Row 1 is already done for you.
Taking it to the bench
What you have written here is the middle of each task. The marks are in what surrounds it, so plan for those too:
- Task A - exercises 16.1 to 16.3 are the whole of Task A's logic. On the bench add the plan sheet (pins and speeds) before you wire anything, the scope reading of D6 at LOW (about 980 Hz, 40% duty) and the test table on the brief. Real buttons bounce, so add the 50 ms button code from the brief - the assessor will press ten times quickly and count.
- Task B - the plan sheet with the transistor stage drawn, the calibration table, and the transistor stage itself. The buzzer never goes straight onto a pin. The assessor will unplug your thermistor mid-demonstration. Do the 0 / 1023 fault check on the raw ADC reading, before you call
readCelsius()from the brief - a broken sensor gives a nonsense temperature, not a clear fault.
Two differences to watch for when you move this code to real hardware. First, the readings here are raw ADC counts; on the bench you convert to °C first and compare against 30.0 and 28.0, using float for the temperature. Second, an NTC thermistor reading gets smaller as it gets hotter, so once you have wired yours, check which way your divider goes before you decide which comparison is >=.
The full briefs, the evidence lists and the marking grids are on the Practical Assessments page.