Skip to content

Designing the capstone: Guardian, three pillars in one file

Module 8 — Capstone: your own Edge AI app · Slides: slides.md · Module overview · Course page

Design a capstone that’s more than one more demo. The Guardian threads three pillars of the data lifecycle through one loop: DAQ (raw acceleration as context), Processing (EMA-filtered confidence), and Apps (a verdict through a decision layer to an action), with the maths of vector magnitude, EMA, and the three-gate firing rule, and reasoned choices of design values.

By the end of this lesson, you will:

  1. Tell a capstone or product apart from a demo, and show which three pillars the Guardian crosses (DAQ, Processing, Apps), and how Training or Analysis could extend it.
  2. Compute the acceleration vector magnitude and one EMA step of the confidence, and explain why the filter is created outside the loop and reset on Load.
  3. Write the firing rule (top = alert_idx) ∧ (s_n ≥ CONF_FLOOR) ∧ (streak ≥ HITS_NEEDED) with an edge trigger, and say which gate stops which kind of fake peak.
  4. Choose CONF_FLOOR, HITS_NEEDED, EMA_ALPHA, and the loop period for a given product, with reasons about misses versus false alarms, responsiveness, stability, and energy.

You’ve been through modules 1 through 7, and have a logger, a filter, a self-trained model, and an action pipeline in hand. Open s20_capstone_full.py (in lesson 8.2) in BENTO IDE.

  • Hardware: a TESAIoT Dev Kit board already flashed with BENTO’s MicroPython firmware, or the BENTO Emulator inside BENTO IDE — Guardian uses the IMU and edge_ai, both of which the emulator supports (the Motion model with the Shake button). A real-world event such as sound or radar needs the board.
  • Prior lesson: lesson 7.4 — Hands-on: make a new model appear in edge_ai.models()

Run s20_capstone_full.py, select Motion, press Load, then hold a shake until the ! ALERT ! banner pops up with a sound and a counter. Then try a single brief shake, and notice it doesn’t alert. Ask yourself which modules’ work Guardian draws on to be able to do this.

A demo answers “can it be done” under ideal conditions. A capstone answers “is it usable in practice” — it must handle noise, false positives, and cleanup, and its design must be explainable. The requirement is to cross at least three pillars of the data lifecycle. The Guardian threads three pillars through a single while loop: DAQ reads ax, ay, az = sensors.bmi270.acceleration(), then computes $mag = \sqrt{a_x^2 + a_y^2 + a_z^2}$ (about 9.8 m/s² at rest, spiking upward on a shake) as context. Processing filters the confidence with $s_n = \alpha c_n + (1-\alpha) s_{n-1}$ via conf_ema = dsp.EMA(alpha=EMA_ALPHA), created outside the loop because it must remember the past, and reset() when Load is pressed to start a fresh watch cycle. Apps uses the same core — models / select / result / stop with CONF_FLOOR — then adds a decision layer, extendable with a self-trained model (Training) or FFT-derived features (Analysis).

The decision layer stacks three gates: the right class (top == alert_idx, by design convention the last class is the event, such as shaking), confident enough from the filtered value (conf_s >= CONF_FLOOR), and held long enough (streak >= HITS_NEEDED) — that is, $\text{fire} \iff (top = alert_idx) \wedge (s_n \ge \text{CONF_FLOOR}) \wedge (streak \ge \text{HITS_NEEDED})$, then a fired flag fires once per event. Fail any gate, and streak resets to zero. Most false positives only pass one or two gates — requiring all three is exactly why a single brief peak doesn’t trigger an alert.

Every design value has a two-sided cost. A high CONF_FLOOR misses real events; a low one gives false alarms. A high HITS_NEEDED responds slowly; a low one gets fooled by peaks. A high EMA_ALPHA is responsive but jittery; a low one is stable but laggy. And the loop’s time.sleep_ms trades energy against responsiveness. There’s no single correct value — only a value suited to the cost of missing in that job. Detecting a fall for an elderly person, for instance, would rather have a false alarm than a miss, while a hand-waving advertising sign would rather miss than bother passersby. A capstone starts with Design (what to watch, what action, what threshold and why), then Build, then Ship.

This lesson’s slides also reference files in another lesson or in shared/:

The same questions are in quiz.yaml for automated checking.

  1. Which pillars does Guardian touch directly? (single choice · objective 1)

    • a) DAQ, Processing, and Apps
    • b) Training only
    • c) Analysis and Training
    • d) Apps only
    Solution

    a — it reads raw acceleration (DAQ), filters confidence with EMA (Processing), and takes the verdict to an action (Apps). Training and Analysis are ways to extend it.

  2. EMA_ALPHA = 0.4, the previously filtered value is 0.30, and the new raw conf is 0.90. What’s the new value? (single choice · objective 2)

    • a) 0.90
    • b) 0.60
    • c) 0.54
    • d) 0.36
    Solution

    c — 0.4 × 0.90 + 0.6 × 0.30 = 0.36 + 0.18 = 0.54, already past the 0.50 threshold, but it still needs to pass the streak gate too.

  3. What happens if you create a new dsp.EMA every time through the loop? (single choice · objective 2)

    • a) It filters better
    • b) The filter loses its memory every frame, and the output equals the raw value — so nothing gets filtered at all
    • c) The program stops
    • d) The value becomes zero
    Solution

    b — the first call of an EMA returns exactly the input value. Creating a new one every round is the same as having no filter at all, so it must be created once, before the loop.

  4. top = alert_idx, conf_s = 0.62, and streak = 2, while HITS_NEEDED = 3. Does Guardian fire? (single choice · objective 3)

    • a) Yes, because the class is right and it’s confident enough
    • b) Not yet, because the streak gate isn’t satisfied yet
    • c) It fires twice
    • d) It doesn’t fire, because conf is too low
    Solution

    b — all three gates must pass at once. If the next result is still the right class and confident enough, streak reaches 3, and it fires once.

  5. Guardian is detecting falls for elderly people. Which direction should the values be tuned? (single choice · objective 4)

    • a) A high CONF_FLOOR and a large HITS_NEEDED, so it never gives a false alarm
    • b) Accept some false alarms in exchange for not missing real events — for example, lower CONF_FLOOR and lower HITS_NEEDED
    • c) No decision layer is needed
    • d) EMA_ALPHA = 0
    Solution

    b — the cost of missing a fall is far higher than the cost of a false alarm. Tuning should therefore lean toward responsiveness, with that reasoning written into the design.

  • Write out Guardian’s three-pillar diagram in your learning log, with the main command of each pillar named.
  • Spend 15 minutes designing your own Guardian: which model to watch, what the event is, what the action is, and how far apart the costs of a miss and a false alarm are.
  • Choose starting values for CONF_FLOOR, HITS_NEEDED, and EMA_ALPHA, with one line of reasoning per value.

In lesson 8.2, we’ll fill in the five backbone lines of s20_capstone.py, then build, tune, and demo our own Guardian.

Next lesson: lesson 8.2 — Hands-on: building and delivering an Edge AI app

  • Which jobs around you have a real miss that costs more than a false alarm, and which have it the other way around?
  • If you could add a fourth pillar to Guardian, would you choose Training or Analysis, and what would it add?

Review questions

Answer on your own first, then open the answer.

  1. Which pillars does the Guardian touch directly? (Objective 1)

    1. DAQ, Processing และ Apps
    2. Training เท่านั้น
    3. Analysis กับ Training
    4. Apps เท่านั้น
    Show answer

    Answer: A. DAQ, Processing และ Apps

    อ่านความเร่งดิบ (DAQ) กรองความมั่นใจด้วย EMA (Processing) และ verdict สู่ action (Apps) ส่วน Training กับ Analysis เป็นทางต่อยอด

  2. EMA_ALPHA = 0.4, the previous filtered value is 0.30 and the new raw conf is 0.90. What is the new value? (Objective 2)

    1. 0.90
    2. 0.60
    3. 0.54
    4. 0.36
    Show answer

    Answer: C. 0.54

    0.4 × 0.90 + 0.6 × 0.30 = 0.36 + 0.18 = 0.54 ผ่านเกณฑ์ 0.50 แล้ว แต่ยังต้องผ่านด่าน streak ด้วย

  3. What happens if a new dsp.EMA is created on every loop pass? (Objective 2)

    1. กรองได้ดีขึ้น
    2. ตัวกรองเสียความจำทุกเฟรม ค่าออกเท่ากับค่าดิบ จึงไม่ได้กรองอะไรเลย
    3. โปรแกรมหยุด
    4. ค่ากลายเป็นศูนย์
    Show answer

    Answer: B. ตัวกรองเสียความจำทุกเฟรม ค่าออกเท่ากับค่าดิบ จึงไม่ได้กรองอะไรเลย

    EMA ครั้งแรกคืนค่าที่ป้อนเข้าไป ถ้าสร้างใหม่ทุกรอบก็เหมือนไม่มีตัวกรอง จึงต้องสร้างครั้งเดียวก่อนลูป

  4. top = alert_idx, conf_s = 0.62 and streak = 2 while HITS_NEEDED = 3. Does the Guardian fire? (Objective 3)

    1. ยิง เพราะคลาสถูกและมั่นใจพอ
    2. ยังไม่ยิง เพราะด่าน streak ยังไม่ครบ
    3. ยิงสองครั้ง
    4. ไม่ยิงเพราะ conf ต่ำ
    Show answer

    Answer: B. ยังไม่ยิง เพราะด่าน streak ยังไม่ครบ

    ต้องผ่านครบทั้งสามด่านพร้อมกัน ถ้าผลถัดไปยังถูกคลาสและมั่นใจพอ streak จะครบ 3 แล้วยิงครั้งเดียว

  5. For a Guardian that detects falls of elderly people, which way should the values lean? (Objective 4)

    1. CONF_FLOOR สูงและ HITS_NEEDED มาก เพื่อไม่ให้เตือนผิดเลย
    2. ยอมเตือนผิดได้บ้างเพื่อไม่พลาดของจริง เช่น CONF_FLOOR ต่ำลงและ HITS_NEEDED น้อยลง
    3. ไม่ต้องมีชั้นตัดสินใจ
    4. EMA_ALPHA = 0
    Show answer

    Answer: B. ยอมเตือนผิดได้บ้างเพื่อไม่พลาดของจริง เช่น CONF_FLOOR ต่ำลงและ HITS_NEEDED น้อยลง

    ต้นทุนของการพลาดการล้มสูงกว่าการเตือนผิดมาก การจูนจึงต้องเอนไปทางไว แล้วเขียนเหตุผลนี้ไว้ในการออกแบบ

Cite this lesson

If you teach from this lesson or reuse it in slides or documents, credit it with the text below. If you changed it, add (adapted) after the title.

"Designing the capstone: Guardian, three pillars in one file" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0

Thai attribution: "ออกแบบ capstone: Guardian สามเสาในไฟล์เดียว" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0

Lesson link: https://tesaiot.github.io/tesa-qualification-program/en/courses/edge-ai-developer/m08-capstone/l01-capstone-design/

Full guide: how to cite TESA

TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0

Content is licensed CC BY-NC 4.0. Reuse it non-commercially and credit the Thai Embedded Systems Association (TESA) every time. · How to cite TESA