Digital Input & Timing — Day 1 of 2
'F' → Fullscreen
Keep Activity 2.6's five-LED array wired exactly as it is. Create a new MicroPython script named 2-7-reaction-timer.
3V3 pin and GPIO 33.GPIO 33 is the last pin in the block you have been using — immediately to the left of 32:
No extra resistor is needed. The board already contains one, and Pin.PULL_DOWN is how you switch it on:
from machine import Pin
leds = [ Pin(28, Pin.OUT), Pin(29, Pin.OUT), Pin(30, Pin.OUT), Pin(31, Pin.OUT), Pin(32, Pin.OUT),]button = Pin(33, Pin.IN, Pin.PULL_DOWN)
def all_on(leds): for led in leds: led.value(1)
def all_off(leds): for led in leds: led.value(0)
while True: if button.value() == 1: all_on(leds) else: all_off(leds)time.The inner while loop does nothing at all on purpose — pass just means "keep checking." The program sits there until the button comes back up.
from machine import Pinimport time
leds = [ Pin(28, Pin.OUT), Pin(29, Pin.OUT), Pin(30, Pin.OUT), Pin(31, Pin.OUT), Pin(32, Pin.OUT),]button = Pin(33, Pin.IN, Pin.PULL_DOWN)
def all_on(leds): for led in leds: led.value(1)
def all_off(leds): for led in leds: led.value(0)
while True: if button.value() == 1: start = time.ticks_ms() all_on(leds) while button.value() == 1: pass stop = time.ticks_ms() all_off(leds) print("You held it for", time.ticks_diff(stop, start), "ms")random.The delay has to be random. A fixed pause lets you anticipate the GO, and then you are measuring your counting, not your reflexes.
from machine import Pinimport timeimport random
leds = [ Pin(28, Pin.OUT), Pin(29, Pin.OUT), Pin(30, Pin.OUT), Pin(31, Pin.OUT), Pin(32, Pin.OUT),]button = Pin(33, Pin.IN, Pin.PULL_DOWN)
def all_on(leds): for led in leds: led.value(1)
def all_off(leds): for led in leds: led.value(0)
all_off(leds)print("Get ready...")time.sleep(random.uniform(2, 5))
all_on(leds)start = time.ticks_ms()while button.value() == 0: passstop = time.ticks_ms()all_off(leds)
print("Reaction time:", time.ticks_diff(stop, start), "ms")measure_reaction(leds, button).return the measured time so the caller decides what to do with it.wait_for_release(button) at the start, so a still-held button from the last go does not ruin the next one.from machine import Pinimport timeimport random
leds = [ Pin(28, Pin.OUT), Pin(29, Pin.OUT), Pin(30, Pin.OUT), Pin(31, Pin.OUT), Pin(32, Pin.OUT),]button = Pin(33, Pin.IN, Pin.PULL_DOWN)
def all_on(leds): for led in leds: led.value(1)
def all_off(leds): for led in leds: led.value(0)
def wait_for_release(button): while button.value() == 1: pass
def measure_reaction(leds, button): all_off(leds) wait_for_release(button) print("Get ready...") time.sleep(random.uniform(2, 5)) all_on(leds) start = time.ticks_ms() while button.value() == 0: pass stop = time.ticks_ms() all_off(leds) return time.ticks_diff(stop, start)
print("Reaction time:", measure_reaction(leds, button), "ms")This is the accumulator pattern from Activity 1.21, with one addition: tracking the smallest value you have seen so far.
from machine import Pinimport timeimport random
leds = [ Pin(28, Pin.OUT), Pin(29, Pin.OUT), Pin(30, Pin.OUT), Pin(31, Pin.OUT), Pin(32, Pin.OUT),]button = Pin(33, Pin.IN, Pin.PULL_DOWN)
def all_on(leds): for led in leds: led.value(1)
def all_off(leds): for led in leds: led.value(0)
def wait_for_release(button): while button.value() == 1: pass
def measure_reaction(leds, button): all_off(leds) wait_for_release(button) print("Get ready...") time.sleep(random.uniform(2, 5)) all_on(leds) start = time.ticks_ms() while button.value() == 0: pass stop = time.ticks_ms() all_off(leds) return time.ticks_diff(stop, start)
times = []attempt = 1while attempt <= 5: print() print("Attempt", attempt) result = measure_reaction(leds, button) print("Reaction time:", result, "ms") times.append(result) attempt = attempt + 1
print()best = times[0]total = 0for t in times: total = total + t if t < best: best = tprint("Best:", best, "ms")print("Average:", total // len(times), "ms")pressed_early(button, seconds) that waits the given time but reports back immediately if the button is pressed during it.-1 instead of a time, print a warning, and make them redo that attempt.Notice why this has to be a while loop and not a for loop: a false start must not use up one of the five attempts, so the counter only moves forward on a real result.
from machine import Pinimport timeimport random
leds = [ Pin(28, Pin.OUT), Pin(29, Pin.OUT), Pin(30, Pin.OUT), Pin(31, Pin.OUT), Pin(32, Pin.OUT),]button = Pin(33, Pin.IN, Pin.PULL_DOWN)
def all_on(leds): for led in leds: led.value(1)
def all_off(leds): for led in leds: led.value(0)
def wait_for_release(button): while button.value() == 1: pass
def pressed_early(button, seconds): steps = int(seconds * 100) for i in range(steps): if button.value() == 1: return True time.sleep(0.01) return False
def measure_reaction(leds, button): all_off(leds) wait_for_release(button) print("Get ready...") if pressed_early(button, random.uniform(2, 5)): return -1 all_on(leds) start = time.ticks_ms() while button.value() == 0: pass stop = time.ticks_ms() all_off(leds) return time.ticks_diff(stop, start)
times = []attempt = 1while attempt <= 5: print() print("Attempt", attempt) result = measure_reaction(leds, button) if result == -1: print("Too early! That one does not count.") else: print("Reaction time:", result, "ms") times.append(result) attempt = attempt + 1
print()best = times[0]total = 0for t in times: total = total + t if t < best: best = tprint("Best:", best, "ms")print("Average:", total // len(times), "ms")Your finished program should behave like this:
Attempt 1Get ready...Reaction time: 210 ms
Attempt 2Get ready...Too early! That one does not count.
Attempt 2Get ready...Reaction time: 260 ms
Best: 210 msAverage: 235 msAnswer the following questions before submitting your work.
Pin.PULL_DOWN do, and what would an unpressed input pin read without it?return. Why did measure_reaction() need one?while loop makes that possible, and why a for loop would have made it harder.Submit the required files to the appropriate dropbox.