|
SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
|
MicroPython examples are mtb-mpy only; the C-side reduction and the on-screen observables apply to both variants. All C excerpts are lifted from archived sources (see the note in E1 — Select, confirm, start: REQUESTED versus ACTIVE).
Run several models at once as a set, read a verdict from the set without losing detections, and recognise the settle gate that withholds verdicts while the audio windows fill. The single most important sentence: ai_engine_snapshot() is not valid inside a parallel set.
Set constants (ai_engine.h:97-113): MIC = 255, ROOM = 254, INTRUDER = 253, ALL = 252, AI_PARALLEL_FIRST = ALL. The legacy 13/14/15 aliases resolve to 253/254/255 (Chapter E1). An archive that predates ALL rejects 252 on hardware (ai_engine.h:109-113). Engine acceptance of any set index requires EDGE_AI_HAS_MIC (ai_engine.c:1850-1859).
Entering a set rebuilds membership on every entry (set_resolve(), ai_engine.c:1166-1189): explicit membership from set_define wins outright, otherwise the compiled name-match (set_wants(), ai_engine.c:1092-1127). Nothing is cached, so a model whose init() failed once is not exiled for the boot. Explicit-wins precedence is at ai_engine.c:1146-1149.
Custom membership — edge_ai.set_define(set, [i, j, ...]) (modedgeai.c:867-921): resolve the legacy index (:876), SET_BEGIN (:886), one SET_ADD per member paced at 5 ms (:895-902), SET_COMMIT (:904), 40 ms settle (:907), then a Q_SET read-back (:910) — the read-back is the only thing that catches a dropped ADD. CM55 applies the three-command build whole:
The read-back that serves as the only acknowledgement:
Result reduction inside a set — the loudest positive member, via ai_engine_set_members() + ai_engine_snapshot_model() + ai_result_top_positive():
Scores are converted to 0..100 at deepcraft_task.c:478-483; class_count == 0 means "no verdict yet" and the CM33 side returns None (:487).
Sensor-rate side effect. dc_desired_sensor_rate() (deepcraft_task.c:259-269) walks the set and raises the accelerometer to 50 Hz if any member is AI_SENSOR_IMU — :250-254 records that Intruder Watch's Motion member was being fed at 10 Hz and its row never moved. ai_engine_model() returns NULL for a set pseudo-index, so branch on idx >= AI_PARALLEL_FIRST first:
On screen, open the model dropdown on the Edge AI page. Rows for sets are added only when the set has at least two members and a name:
What you should observe. Set rows (Sound Watch, Room Presence, Intruder Watch, All Models) appear after the compiled single models. A set with fewer than two resolvable members is simply absent — that is a build-content fact, not a fault.
What you should observe. For the first seconds result() returns None — class_count == 0 — while the audio windows fill. On screen the verdict label reads filling windows lu%% with the percentage climbing (page_edge_ai.c:698-699), and the badge shows CHIP_LOADING. The gate is ai_engine_mic_settling() / ai_engine_mic_settle_pct():
Note the rule recorded at page_edge_ai.c:702-705: the stats line keeps updating during settle, otherwise an NPU stall inside the window is invisible. mic_settle_pct() is meaningful only inside a set; it returns 100 otherwise.
What you should observe. Once settled, a result whose fields come from the loudest positive member. Each member row on screen carries its own silence timer, derived from seq staleness (page_edge_ai.c:728-739):
ai_engine_snapshot_model() returning false means "never published", which is not the same as "silent"; the index must be a real registry index, never a set pseudo-index.
What you should observe. set_define returns after the Q_SET read-back confirms every member; a dropped ADD shows up as a shorter list, and the whole definition is refused if any index is invalid (all-or-nothing, ai_engine.c:1060-1064). Membership is 1..8 entries. set_define(252, ...) always fails — AI_PARALLEL_ALL has no slot (set_slot(), ai_engine.c:1040-1048).
What you should observe. Nothing visible — this is the discipline that keeps the layout tag and the row count from disagreeing when the deepcraft task starts or stops the engine from another task mid-render.
| mtb-mpy | mtb-only | |
|---|---|---|
| Select a set | edge_ai.select(252..255) | Dropdown row + Load |
| Define membership | edge_ai.set_define() | Only via your own CM55 code calling ai_engine_set_define() from a task; read back with ai_engine_set_members_defined() |
| Settle observable | result() is None; screen filling windows lu%% | Screen filling windows lu%% |
| Verdict | edge_ai.result() dict | Verdict label + per-row silence timers |