Week 9 — Input devices

This week we shifted from “does it work on the bench?” to what does the signal actually look like on copper and wire — slow ramps, noisy edges, and decoded buses included. For my individual assignment I also brought up a digital humidity / temperature sensor on a microcontroller and printed derived values over serial — interim breadboard setup while my next PCB revision is out for fabrication.

Individual assignment

The academy brief expects the sensor on your fabricated board; mine was still at the fab when I wrote this, so I treated the week as: prove the read path on hardware I trust (XIAO ESP32-S3 + breadboard), keep the wiring diagram honest, and note what will move one-to-one onto the custom PCB. I picked the DHT11 module because it was on hand and slow enough that I could watch serial timing mistakes without guessing; occasional NaN reads reminded me the one-wire timing is brittle if jumpers are loose.

Fab Academy’s Input Devices brief asks you to measure something on a board you designed; the module FAQ also states that the assessed interface should not stay on a breadboard. The paragraphs above are my interim trail; when the custom PCB is assembled I will move the same nets and update the hero photo.

Sensor and dev board

  • Microcontroller: Seeed Studio XIAO ESP32-S3 — compact module with USB‑C, 3.3 V logic, and enough GPIO for quick DHT wiring while the project board is unavailable.
  • Input device: DHT11 module (single-wire “SIG” data pin, onboard pulls / power regulation as provided by the blue breakout). DHT11 returns relative humidity and temperature as a timed digital bitstream; the chip is slow (~1 s class update) but fine for learning the read / parse / print loop.

Wiring (breadboard — interim)

I matched the module pin labels to the XIAO rail: VCC to the XIAO 5 V pin (as marked on this carrier), GND to GND, and SIG to a digital GPIO — here D2 on the silkscreen (use the same constant in code as the physical pin you chose).

Seeed XIAO ESP32-S3 on a breadboard with a DHT11 module and jumper wires
Figure I-1: Provisional bench setup — XIAO ESP32-S3 and DHT11 on a breadboard (to be ported to my fabricated PCB when V2 is assembled).

Firmware: read, derive “feels like”, print

I used the Arduino framework (edited in Cursor, built/flashed with PlatformIO on the classroom Windows bench). The sketch:

  1. Initialises serial at 115200 8N1 and starts the DHT driver for pin D2 / DHT11.
  2. In loop(), reads relative humidity (%) and temperature (°C); skips or retries on NaN reads — DHT11 occasionally fails a timing window if the bus is noisy.
  3. Computes heat index (often labelled 体感温度 in Chinese tutorials): a humidity-adjusted “feels like” temperature derived from the same pair (U.S. NOAA-style heat index, with library helpers returning sensible values in °C when configured that way).
  4. Prints humidity, temperature, and heat index on one line for the serial monitor / logging.

Representative structure (pin and library names follow your actual PlatformIO platformio.ini):

#include <Arduino.h>
#include <DHT.h>

#define DHT_PIN  D2        // Match SIG wire to silkscreen D2
#define DHT_TYPE DHT11

DHT dht(DHT_PIN, DHT_TYPE);

void setup() {
  Serial.begin(115200);
  delay(500);
  dht.begin();
}

void loop() {
  float rh = dht.readHumidity();
  float tc = dht.readTemperature();

  if (isnan(rh) || isnan(tc)) {
    Serial.println(F("DHT read failed, retrying…"));
    delay(2000);
    return;
  }

  // Adafruit-style helper: pass Celsius, request result in Celsius
  float feelsC = dht.computeHeatIndex(tc, rh, false);

  Serial.print(F("湿度: "));  Serial.print(rh);   Serial.print(F(" %\t"));
  Serial.print(F("温度: "));  Serial.print(tc);   Serial.print(F(" °C\t"));
  Serial.print(F("体感: "));  Serial.print(feelsC); Serial.println(F(" °C"));

  delay(2000);
}

If your core does not expose computeHeatIndex, implement the NOAA Rothfusz regression on Fahrenheit and convert back to °C, or call the unified sensor API from the Adafruit DHT / Adafruit Unified Sensor bundle you already pulled into the project.

Serial monitor capture

With pio device monitor (same 115200 baud), the loop prints stable room readings: humidity in the mid‑50s %RH, temperature ~27 °C, and heat index a little above dry-bulb — expected when humidity is factored in.

PlatformIO serial monitor showing humidity, temperature, and heat index in Chinese labels
Figure I-2: PlatformIO serial monitor — humidity (%), temperature (°C), and heat index / “体感” (°C) updating every two seconds.

Problems and fixes

  • Occasional NaN reads: DHT11 timing is picky; longer wire runs or a weak pull-up can corrupt the first byte. Keeping leads short on the breadboard and inserting a small delay after power-up reduced failures.
  • Wrong pin mapping: if the printout freezes or always fails, the first check is that DHT_PIN matches the physical SIG row (XIAO silkscreen D2 in this build).
  • Baud mismatch: monitor must match Serial.begin (115200 here).

Design files and PCB link

Source and project files live in my local PlatformIO workspace (not duplicated in this static site repo). Board design for the eventual surface-mount build remains in the KiCad project documented under Week 6 — electronics design; once V2 is populated, this section will gain a solder-side photo and the repository can host a tagged firmware release if instructors want a direct zip.

Group assignment (Chaihuo Makerspace)

The Fab brief asked us to probe input-device analog levels and digital waveforms — multimeter, oscilloscope, and logic analyzer — and write down what we saw, not to polish a product. Our cohort reused the Seeed Grove ecosystem on the input side and treated every screenshot as lab notebook evidence.

A fuller regional write-up with the same structure lives on the Fab Academy site: Week 9 — Group Assignment: Input Devices (Fab26 Chaihuo). What follows here is our mirror — English notes and media we actually captured in the room.

How we thought about input devices

We kept reminding ourselves that sensors translate physics into voltage or timed bits:

  • Analog inputs land near steady DC when things move slowly (wiper, LDR divider), but still carry noise and settling behaviour worth measuring.
  • Digital inputs can be single wires with bounce, quadrature pairs, or framed packets — scope vs. logic analyzer depends on whether we cared about shape or meaning.

Lab gear we leaned on

  • Digital multimeter (DT-660B) — rails, continuity, slow-moving sensor DC while someone tweaks the knob.
  • Oscilloscope (OWON EDS102 CV) — 100 MHz, 1 GSa/s, two analog channels; we avoided autoset so each knob stayed meaningful.
  • Logic analyzer (Alientek DL16) — sixteen channels, buffer captures ≥50 MSa/ch when decoding UART/I²C.

Rule we drilled until it hurt: tie scope/LA ground to circuit ground before touching signal probes. Floating grounds gave nonsense traces once; almost-short anxiety convinced everyone on the second lap.

Devices we characterised together

Device Principle Signal type Instrument
Grove rotary angle sensor Potentiometer Analog DC (slow) DMM + scope
Grove button Mechanical contact Single-ended digital Scope
Grove rotary encoder Quadrature switches Two square waves Scope (CH1+CH2)
Grove RTC (DS1307) I²C clock IC I²C Logic analyzer
Grove I²C OLED (SSD1306) Display updates I²C traffic reference Logic analyzer
Grove GPS (Air530) NMEA UART Serial @9600 8N1 Logic analyzer + host capture

Grove four-pin harness sanity check

Grove cables bundle GND, VCC, SIG1, SIG2. When we improvised jumper spaghetti we caught classmates swapping power onto signal pins — a quick visual check before powering up beat hours of mystery debugging.

Correct Grove jumper routing with labeled pins
Wiring we powered up happily.
Incorrect Grove jumper routing warning layout
Example mistake layout — we did not energise boards wired like this.

Scope baseline workflow we repeated every bench session

  1. Utility → Factory Setting → confirm cleared ghosts from whoever used the bench last.
  2. Single-channel captures hid CH2; encoder demos toggled CH2 back on for quadrature.
  3. CH1 coupling DC, time-base tuned so one–three cycles (or ramps) filled the display, volts/div avoiding clipping.
  4. Trigger parked inside the swing (~2.5 V for a 0–3.3 V logic-ish waveform) stabilised shots that looked “alive” otherwise.
  5. Optional probe compensation against the front-panel square-wave calibrator — dull tops or ringing overshoot meant tweaking trim caps until corners squared up.
  6. Measure soft-keys dumped automated freq/VPP/duty readouts so we weren’t counting divisions by thumb.

Analog — rotary angle sensor

The Grove module is a 10 kΩ pot wired rail-to-rail with the wiper exposed. At 3.3 V we traced ~0.00 V → ~3.28 V end stops with the handheld meter — smooth motion meant no cracked carbon track surprises.

On the scope we slowed time-base (~500 mV/div vertical, ~200 ms/div horizontal) so knob rotations drew ramps rather than pops. Result: essentially DC plus tens-of-millivolt ripple sitting still — negligible next to a 10-bit ADC LSB (~3.2 mV here). Transitions stayed buttery, so firmware filtering stayed optional for this sensor class.

Scope clip — rotary sweep proving slow ramps stayed quiet aside bread noise.

Analog — faster-changing waveform sanity capture

We also chased an analog output whose voltage visibly danced inside one sweep window so we could practise triggering slightly above idle — resting traces jitter otherwise even when hardware behaved.

Second analog exercise — trigger discipline mattered more than probe fancy-ness.

Digital — button on a pulled-up GPIO

We moved the probe to the microcontroller pin (XIAO ESP32-C3, internal pull-up enabled) so we witnessed exactly what firmware sampled — idle sat ~3.3 V, presses slammed low, and mechanical bounce showed as rapid chatter before settling — textbook reason we debounce in software or with RC networks.

The idle-high rail picked up tiny USB ripple yet stayed confidently above CMOS “recognized-high”; documenting ripple beats pretending rails are textbook flat lines.

Oscilloscope capture of GPIO with switch bounce
Single-channel capture — bounce visible on the falling edge.

Digital — rotary encoder quadrature

Two square waves ~90° apart: whichever channel edges first spells direction. Each detent produced one clean A/B cycle — exactly what interrupt-driven decoders expect.

Dual-trace clip — phase relationship flips when we reversed rotation.

Protocol — I²C (RTC + OLED reference)

DS1307 at address 0x68 shared the bus with an SSD1306 OLED we already trusted. The XIAO master polled once per second; logic analyzer inputs were D0→SCL, D1→SDA with decoder set to I²C.

Clean captures showed clocks bursting ~100 kHz, data toggling only while SCL low per spec, decoder listing address byte, R/W, register pointer, seven time-bytes with ACKs. OLED-heavy segments stretched transactions dramatically — instant illustration why bus capacitance and pull-ups matter: long loose wires without pull-ups rounded edges until decoders threw framing errors; restoring 4.7 kΩ-ish pull-ups at 3.3 V put teeth back on edges.

Buffer-mode capture — decoder overlay while OLED + RTC shared SCL/SDA.
Additional timing slice while we dissected RTC read bursts — handy when correlating to firmware logs.

Protocol — UART GPS (Air530 @9600 baud)

TX idles high, start bit dives low, eight data bits LSB-first, stop bit releases high — classic 10-bit ASCII frames. Indoors we still saw text streaming even when fixes were garbage (empty fields / zeros); outdoors $GPRMC / $GPGGA sentences filled with real coordinates once the antenna saw sky.

We measured narrowest pulse width (~104 µs) as baud sanity — inverse equals ~9600 baud — handy cheat when baudrate stickers peel off mystery UART peripherals.

Indoor host-side capture — sentences present even without trustworthy satellites yet.

What stuck with us

  • Match instrument to question — scopes answer morphology; analyzers answer semantics.
  • Ground first — every “broken probe afternoon” traced to grounding mistakes or swapped Grove legs.
  • Trigger smart — jitter blamed on hardware turned into textbook triggering drills once we level-shifted thresholds inside swing.
  • I²C pull-ups stay mandatory classroom lore — rounding rising edges visually predicts protocol flake before firmware guesses wrong.
  • Log volts/div, time/div, trigger voltage beside screenshots — future-us retracing steps thanks past-us for scribbling metadata on stickers beside HDMI grabs.