Tracking (1-channel)

🎮 READ · The Verdict and the Magic Knob
Module Goal: the most famous robot sensor of all time. It fires invisible infrared light at a surface and measures what bounces back: white paper reflects a lot, black tape swallows it. Every line-following robot in every competition on Earth is built on this trick and today yours begins.
Build your test track now: white paper + black electrical tape lines, 1 cm wide, with 2 cm white gaps between them.
Goal:
read the module's binary verdict over white and black then discover that the knob can flip the verdict for the SAME surface.
Concepts:
Digital Input · Hardware Threshold · Prediction · Component Personality
import machine # Controls the board's pins
import time # Controls pauses and timing
# Sets up pin26 as an input for the digital surface sensor
# pin26 corresponds to D2 on the Sensor Shield V5.0
pin26 = machine.Pin(26, machine.Pin.IN)
while True: # Read forever
state = pin26.value() # Read the module's verdict: 1 or 0
print("Surface verdict:", state) # Send the verdict to the PC
time.sleep_ms(300) # Pause so the screen stays readableSerial Monitor (hold over white, then over black):
Surface verdict: 1 ← over WHITE paper
Surface verdict: 1
Surface verdict: 0 ← over BLACK paper
Surface verdict: 1 ← back to white
💡 Note: verify your polarity (this module: 1 = light, 0 = dark if yours runs inverted, swap the 0s and 1s everywhere below). Now the real experiment: hold the sensor over cardboard and slowly turn the blue knob until the verdict flips. You just watched a hardware threshold move the fence between light and dark is physical, and YOU relocated it. Module 14 let you move fences in code; Module 17's fences live on a screwdriver. Remember both choosing which fence to move is an engineering decision.
🎮 INTERPRET · The Two Families
Goal:
translate the binary verdict into the judge's language every material belongs to the LIGHT family or the DARK family.
Concepts:
Binary Classification · Translation Layer · Two-Category World
import machine # Controls the board's pins
import time # Controls pauses and timing
# Sets up pin26 as an input for the digital surface sensor
# pin26 corresponds to D2 on the Sensor Shield V5.0
pin26 = machine.Pin(26, machine.Pin.IN)
while True: # Judge forever
state = pin26.value() # Read the module's verdict
if state == 0: # Inverted family: 1 = dark surface detected
print("Verdict: DARK FAMILY") # The translation
else: # 0 = light surface
print("Verdict: LIGHT FAMILY") # The translation
time.sleep_ms(300) # Pause between verdictsSerial Monitor (test paper, then black paper, then... your sleeve):
Verdict: LIGHT FAMILY
Verdict: DARK FAMILY
Verdict: LIGHT FAMILY ← your sleeve is in the light family!
💡 Note: feel the difference from Module 14's interpreter there, YOU compared raw values against YOUR calibrated midpoint; here the module hands you a pre-judged verdict and you only translate it. Fewer lines, less control. And test the gray zone: hold cardboard over the sensor with the knob in different positions the same material can be judged into EITHER family. In the binary world, the fence decides; where the fence stands is everything (the mission will prove it dramatically).
🎮 COMPARE · The Quiet Judge
Goal:
report only when the verdict CHANGES a dark surface arriving, or light returning. Silence in between.
Concepts:
Both-Edge Detection · Quiet Monitoring · State Memory
import machine # Controls the board's pins
import time # Controls pauses and timing
# Sets up pin26 as an input for the digital surface sensor
# pin26 corresponds to D2 on the Sensor Shield V5.0
pin26 = machine.Pin(26, machine.Pin.IN)
prev = 1 # Memory of the previous verdict (start over a light surface)
while True: # Watch forever
now = pin26.value() # Fresh verdict
if now != prev: # The verdict CHANGED (either direction!)
if now == 0: # It just became DARK
print(">>> A DARK surface arrived") # Report the arrival
else: # It just became LIGHT again
print(">>> Back to LIGHT") # Report the departure
prev = now # Save this verdict for the next comparison
time.sleep_ms(50) # Fast checking so quick slides are caughtSerial Monitor (slide a black card in, hold, slide out):
>>> A DARK surface arrived
(holding — silence)
>>> Back to LIGHT
💡 Note: the both-edge pattern so well-worn by now (tilt, guardian, radar, lines) that writing it should take you under two minutes. What's new is what cannot be done here: in Module 14 you could report HOW dark a surface was; the digital verdict has no "how much" only which side. Binary sensors trade richness for simplicity, and today simplicity is exactly what the mission needs.
🎮 MEASURE · The Darkness Timer
Goal:
measure how long each dark verdict HOLDS from the moment a dark surface arrives until light returns.
Concepts:
Event-Driven Timing · Waiting Loops · Duration Analysis
import machine # Controls the board's pins
import time # Controls pauses and timing
# Sets up pin26 as an input for the digital surface sensor
# pin26 corresponds to D2 on the Sensor Shield V5.0
pin26 = machine.Pin(26, machine.Pin.IN)
while True: # Watch forever
if pin26.value() == 0: # A dark verdict just arrived!
start = time.ticks_ms() # Freeze the ms the darkness began
print("Dark surface detected...") # Announce the event
while pin26.value() == 0: # Wait WHILE the verdict stays dark...
time.sleep_ms(10) # ...checking patiently
duration = time.ticks_diff(time.ticks_ms(), start) # End minus start = hold time
print("The dark verdict held for:", duration, "ms") # Report the duration
if duration < 1000: # Under one second?
print("A quick slide-by") # Short event
else: # One second or more
print("A long, deliberate cover") # Long event
time.sleep_ms(200) # Calm checking between episodesSerial Monitor (a quick slide, then a slow hover):
Dark surface detected...
The dark verdict held for: 320 ms
A quick slide-by
Dark surface detected...
The dark verdict held for: 2400 ms
A long, deliberate cover
💡 Note: the event-driven watch (tilt 8.4, guardian 11.4, shadows 13.5) fourth family member measured this way. Notice the timing precision available even from a "dumb" binary sensor: the dark/light edges are razor-sharp (the comparator snaps, no gradual zones), so durations here are actually crisper than the analog shadow timing of Module 13. Binary isn't worse it's sharper at the edges.
🎮 The Material Court of Appeals
Goal:
the courtroom drama. Three materials are judged and their verdicts recorded. Then you turn the knob the fence moves and the SAME materials are judged AGAIN. Did justice change? The two records will testify.
Concepts:
Measurement Protocol · String Records · Threshold Consequences · The Knob on Trial
Your materials: white paper, cardboard, black paper the courtroom's three suspects.
import machine # Controls the board's pins
import time # Controls pauses and timing
# Sets up pin26 as an input for the digital surface sensor
# pin26 corresponds to D2 on the Sensor Shield V5.0
pin26 = machine.Pin(26, machine.Pin.IN)
print("=== THE MATERIAL COURT ===") # The mission title
print("3 materials, 2 rounds. The knob will be on trial!") # The rules
# ---- ROUND 1: the first judgment ----
print("--- ROUND 1: the first judgment ---") # Round banner
record1 = "" # Round 1's verdict record starts EMPTY
for material in range(1, 4, 1): # Three materials take the stand
material = input('Place material ' + ' and press Enter... ') # The handshake: judge only when ready
if pin26.value() == 0: # Dark verdict from the module
record1 += "D" # D enters the record
print("Verdict: DARK FAMILY") # Announce
else: # Light verdict
record1 += "L" # L enters the record
print("Verdict: LIGHT FAMILY") # Announce
print("Round 1 record:", record1) # The full verdict string
# ---- ROUND 2: turn the knob, judge again ----
print("--- ROUND 2: turn the knob, judge again! ---") # The twist
x = input('Turn the sensitivity knob a little, then press Enter... ') # THE KNOB MOMENT
record2 = "" # Round 2's record starts empty
for material in range(1, 4, 1): # The SAME three materials return
input("Place material " + str(material) + " and press Enter... ") # The handshake again
if pin26.value() == 0: # Dark verdict
record2 += "D" # D enters
print("Verdict: DARK FAMILY") # Announce
else: # Light verdict
record2 += "L" # L enters
print("Verdict: LIGHT FAMILY") # Announce
print("Round 2 record:", record2) # The second verdict string
# ---- The verdict on the verdicts ----
if record1 == record2: # Identical records?
print("The knob changed nothing... this time.") # The calm ending
else: # Different records!
print(">>> THE KNOB CHANGED JUSTICE!") # The revelation
print("Before:", record1, "| After:", record2) # The evidence, side by sideSerial Monitor (a cardboard that flips from LIGHT to DARK when the knob turns):
=== THE MATERIAL COURT ===
3 materials, 2 rounds. The knob will be on trial!
--- ROUND 1: the first judgment ---
Place material 1 and press Enter...
Verdict: LIGHT FAMILY
Place material 2 and press Enter...
Verdict: LIGHT FAMILY
Place material 3 and press Enter...
Verdict: DARK FAMILY
Round 1 record: LLD
--- ROUND 2: turn the knob, judge again! ---
Turn the sensitivity knob a little, then press Enter...
Place material 1 and press Enter...
Verdict: LIGHT FAMILY
Place material 2 and press Enter...
Verdict: DARK FAMILY
Place material 3 and press Enter...
Verdict: DARK FAMILY
Round 2 record: LDD
>>> THE KNOB CHANGED JUSTICE!
Before: LLD | After: LDD
💡 Note the deepest lesson of the digital pair: the cardboard didn't change the fence did. Every sensor system in the world has a fence somewhere: in software (Module 14's midpoint), in hardware (today's knob), or baked into the factory design. Wherever it stands, it decides who is "in" and who is "out" and moving it changes verdicts without changing reality. When a smoke alarm is too sensitive, when a spam filter eats good mail, when a grading curve shifts someone moved a fence. Now you know fences are made, and you have moved one yourself.
