ช่องเติมที่ 1: เขียน "ใจความ" ของโมเดลก่อน — นี่คือ field เดียวกับที่จะไปอยู่ใน C ROW:
NAME_UI = "Fall Detection"
PREFIX = "FALL"
SPEC = {
"name": NAME_UI,
# เติม: ใส่เซนเซอร์ + คลาสของโมเดลนี้
"sensor": None, # เติม: edge_ai.SENSOR_IMU
"labels": [], # เติม: ["normal", "fall"]
"period_ms": 200,
}
sensor ใช้ค่าคงที่จากเฟิร์มแวร์: edge_ai.SENSOR_IMU (=0) / SENSOR_RADAR (=1) / SENSOR_MIC (=2)SENSOR_IMU แปลว่ายืม feed_imu เดิม ไม่ต้องเขียน feed ใหม่labels = คลาสที่โมเดลตอบได้ ตรงกับ .class_labels ใน ROWเขียนสเปกที่ Python ก่อนมีข้อดี: เห็นภาพชัด แก้ง่าย แล้วค่อยให้
make_row()แปลเป็น C ให้ — ลดโอกาสพิมพ์ ROW ผิดมือ
ช่องเติมที่ 2: ผูก "สัญญา 4 ฟังก์ชัน" เข้ากับ ROW ด้วยคำนำหน้า AIM_<PREFIX>_:
def make_row(spec, prefix):
...
init_fn = "AIM_%s_init" % prefix # AIM_FALL_init
enq_fn = "AIM_%s_enqueue" % prefix # AIM_FALL_enqueue
# เติม: เติมชื่อ dequeue ให้ครบตามแบบ init/enqueue
deq_fn = None # เติม: "AIM_%s_dequeue" % prefix
fin_fn = "AIM_%s_finalize" % prefix # AIM_FALL_finalize
return ( ... ) # ประกอบเป็นข้อความ #if / #define FALL_ROW / #endif
make_row() จะพ่นข้อความ ROW ที่ก็อปไปวางใน ai_engine.c ได้เลยdeq_fn → ROW จะมี .dequeue = None → C คอมไพล์ไม่ผ่าน (function pointer เป็น NULL).a เปลี่ยน AIM เป็น IMAI (ฉบับเต็มมีตัวเลือก STYLE ให้สลับ)สังเกตว่า
make_row()แค่ประกอบ "สตริง" — มันไม่ได้คอมไพล์ C ให้ หน้าที่มันคือ ลดข้อผิดพลาดตอนพิมพ์ ROW ด้วยมือ ให้เราได้ ROW ที่ field ตรงกับสเปกเป๊ะ
ช่องเติมที่ 3: ถามเฟิร์มแวร์ว่าตอนนี้มีกี่โมเดล — เลขนี้จะเพิ่มขึ้นหลังเราเพิ่มโมเดลสำเร็จ:
def scan_registry():
# เติม: อ่านจำนวนโมเดลปัจจุบันมาเก็บใน n
n = 0
pass # เติม: n = edge_ai.count()
models = edge_ai.models()
mine = -1
for i, m in enumerate(models):
hit = (m['name'] == SPEC['name'])
...
edge_ai.count() คืนจำนวนโมเดลที่คอมไพล์รวมใน image ตอนนี้ (sizeof(s_models)/...)
edge_ai.count()เป็น pull ผ่าน IPC เหมือนmodels()— เรียกเมื่อไรก็ได้ มันไปนับs_models[]บน CM55 มาให้สดๆ
ช่องเติมที่ 4: วนทะเบียนหาว่าชื่อโมเดลเราอยู่ index ไหน (ต้องรู้ index ก่อนถึงจะ select() ได้):
for i, m in enumerate(models):
hit = (m['name'] == SPEC['name'])
# เติม: ถ้า hit เป็นจริง ให้ mine = i
pass
if i < len(rows):
rows[i].text('%2d %-16s %s'
% (m['index'], m['name'], SENSOR[m['sensor']]))
rows[i].color(GREEN if hit else DIM) # ของเราเขียว ที่เหลือจาง
rows[i].show()
return mine, n
m['name'] กับ SPEC['name'] — ตรงเมื่อไร จำ i ไว้ใน minehit ระบายเขียว = "โมเดลของเราโผล่แล้ว" (ชัยชนะที่เห็นได้)mine ยังเป็น -1 = ยังไม่เจอ → ต้องกลับไปเช็ก 3 การแก้ + build ใหม่เราหา index จากชื่อ ไม่ hard-code ตัวเลข เพราะพอเพิ่มโมเดล ลำดับ index อาจเลื่อน — หาโดยชื่อปลอดภัยกว่าเสมอ (บทเรียนเดียวกับ
models()ใน บทเรียน 1.1–1.3)
ช่องเติมที่ 5: หัวใจของ MVP วันนี้ — สั่งรันโมเดลที่เราเพิ่ง เพิ่มเข้าไป แล้วอ่าน verdict:
def run_mine(idx):
try:
# เติม: สั่ง select(idx) แล้วอ่านผลมาเก็บใน r
r = None
pass # เติม: edge_ai.select(idx); r = edge_ai.result()
detail.text("running %s — ทำท่าตามคลาส" % SPEC['name'])
detail.color(GREEN)
return r
except OSError as e: # ข้ามคอร์พลาดได้ ต้องเผื่อไว้
detail.text("select ล้มเหลว: %s" % e)
detail.color(RED)
return None
edge_ai.select(idx) สั่ง CM55 สลับมารันโมเดลของเรา (confirm by observation — โยน OSError ได้)edge_ai.result() คืน verdict {label, conf, scores, seq, latency_ms} — เหมือนที่ใช้มาตั้งแต่ บทเรียน 1.1–1.3Fall Detection รันแล้วขยับบอร์ดจริง คลาสจะสลับ normal / fall = โมเดลของเราทำงานห่อ
select()ด้วยtry/except OSErrorเสมอ — โมเดลใหม่ที่เพิ่งเพิ่มมีโอกาส init ไม่ผ่าน (เช่น arena ไม่พอ) เราอยากเห็น error ชัดๆ ไม่ใช่โปรแกรมตายเงียบ
เปิด s19_extend_model.py มี # เติม: วางไว้ 5 จุด ครอบทั้งฝั่ง C (สร้าง ROW) และฝั่ง MicroPython (ยืนยัน):
| # | จุด | เติมด้วย | ถ้าลืม |
|---|---|---|---|
| 1 | SPEC['sensor'] |
edge_ai.SENSOR_IMU |
make_row พังตอนอ่าน sensor |
| 1 | SPEC['labels'] |
["normal", "fall"] |
ROW ไม่มีคลาส |
| 2 | deq_fn |
"AIM_%s_dequeue" % prefix |
ROW มี .dequeue = None |
| 3 | n |
edge_ai.count() |
diff จำนวนโมเดลเป็น 0 เสมอ |
| 4 | mine |
mine = i (เมื่อ hit) |
หาโมเดลไม่เจอ กด Run ไม่ได้ |
| 5 | run_mine |
select(idx) + result() |
กด Run แล้วไม่มี verdict |
ขั้นตอน:
# เติม: ทีละจุด เติมตามคำใบ้rm -rf proj_cm55/build; make program EDGE_AI_MODEL=combo แล้วกลับมากด Re-check → Run mineห้าช่องนี้เดินครบวงจรของสาย Researcher: ออกแบบสเปก → ประกอบ C ROW → build → ยืนยันว่าโผล่ → รันจริง
การเพิ่มโมเดลต้อง build เฟิร์มแวร์ใหม่ ดังนั้นขั้นนี้ทำบน บอร์ดจริง (Emulator รัน MicroPython แต่ไม่ build C):
FALL_ROW + ต่อเข้า s_models[]), Edit 3 (วาง model_fall.c/.h)rm -rf proj_cm55/build; make program EDGE_AI_MODEL=combo (clean build ทุกครั้ง)Fall Detection ควรโผล่เขียว index=6 (count 6→7)normal / fallลบ
build/ก่อน build ทุกครั้ง (cache ของ Ninja กับ timestamp ของไฟล์ที่ sync มาทำให้ link ของเก่าได้) และ hard power-cycle ก่อนเชื่อผลอนุมานบนฮาร์ดแวร์
Emulator รัน MicroPython ได้ แต่ build C ไม่ได้ ในเบราว์เซอร์ — ใช้ซ้อม "ครึ่งบน" ของไฟล์:
s19_extend_model.py กด RunSPEC แล้วดู make_row() เปลี่ยน ROW ตามscan_registry() จะโชว์ 5 โมเดลของ Emulator (ไม่มี Push) — Fall Detection ยัง ไม่โผล่ (เพราะ build ไม่ได้) = ถูกต้อง เป็นบทเรียนselect/result) ทดสอบกับโมเดลที่มีอยู่แล้วบน Emulator ได้ (ลองเลือก Motion แทน)ขอบเขตนี้เองก็เป็นบทเรียน: "เพิ่มโมเดล C" เป็นงานที่ต้องมี toolchain — ต่างจากงาน app-layer ที่เขียน
.pyแล้วรันได้เลยทุกพื้นผิว นี่คือเส้นแบ่งระหว่าง firmware กับ application
ก่อนไปลงมือ นี่คือหน้าเมนู Edge AI ของ Emulator ที่อ่านทะเบียนโมเดลชุดเดียวกับที่ s19_extend_model.py ถาม

จอ emulator ที่รันได้จริง — BENTO Edge AI Emulator บนเบราว์เซอร์ ใช้ซ้อม "ครึ่งบน" (ออกแบบสเปก + อ่าน ROW) ก่อนไป build จริงบนบอร์ด
สังเกตว่าตัว Emulator มี 5 โมเดล ยังไม่มี
Fall Detection— ถูกต้องแล้ว เพราะเบราว์เซอร์ build C ไม่ได้ ตัวที่ 7 จะโผล่ก็ต่อเมื่อเราทำครบ 3 การแก้แล้ว flash ลงบอร์ดจริง
อยากเข้าใจ "เพิ่มโมเดล TFLite เข้าเฟิร์มแวร์ / deploy โมเดลลง MCU" ให้ลึกกว่านี้ ลองตามลิงก์เหล่านี้ (เปิดดูได้ตามสะดวก):
วิดีโอ
เอกสาร / ภาพอ้างอิง
วิดีโอ/ภาพภายนอกเป็นของเจ้าของต้นฉบับ ใช้เพื่อการศึกษา อ้างอิงลิงก์ต้นทาง
MVP ของบทเรียน 7.3–7.4 (เกณฑ์ผ่านของชุดบทเรียน): คุณเพิ่มโมเดลของตัวเองครบ 3 การแก้ แล้ว edge_ai.count() เพิ่มขึ้น + ชื่อโมเดลใหม่โผล่ใน edge_ai.models() และ เลือกรันแล้วได้ verdict จริง บนบอร์ด
"โผล่ในทะเบียน" ไม่ใช่แค่ตัวเลข count เพิ่ม — คุณต้อง
select()มันแล้วเห็น verdict สลับตามการขยับบอร์ดจริง นั่นคือหลักฐานว่าทั้ง 4 ฟังก์ชันของโมเดลต่อสายถูก
ถ้าติด ให้ไต่บันไดนี้ทีละขั้น อย่าเพิ่งกระโดดไปดูเฉลย เพราะของจะเข้าหัวตอนที่คุณพยายามเองก่อน:
# เติม: ทั้ง 5 จุด + ตารางช่องเติม + หัวข้อ Filling a model slot ใน ai_models/README.md ของ SDKs19_extend_model.py มีโครงครบทั้งไฟล์ เหลือเติม 5 จุด + ทำ 3 การแก้ในเฟิร์มแวร์s19_extend_model.py เติมครบพร้อมคอมเมนต์อธิบายทุกช่อง (อ่านให้เข้าใจ ปิดไฟล์ แล้วพิมพ์เอง)s19_extend_model_full.py ฉบับขัดเรียบ: รองรับ AIM_/IMAI_, ตรวจสัญญา 4 ฟังก์ชัน, diff count ก่อน/หลัง, แยกสี CONF_FLOOR + latencyลองเขียนเองให้สุดก่อนนะ ถ้าติดเรื่อง build C จริงๆ ค่อยเปิดเฉลยดู
make_row()ทีละบรรทัด แล้วกลับมาลงมือเอง เดี๋ยวเราค่อย ๆ แกะไปด้วยกัน
การเพิ่มโมเดลตัวแรกซ่อนแนวคิดวิศวกรรม Edge AI หลายชั้นที่รวบยอดทั้งคอร์ส:
ฝั่ง Edge AI / เฟิร์มแวร์
s_models[]) ขับพฤติกรรม ไม่ใช่ชื่อ hard-code → เพิ่มของใหม่ = เพิ่มแถวinit/enqueue/dequeue/finalize) = interface ที่ทุกโมเดลต้องทำตามฝั่งกระบวนการ / เครื่องมือ
count() diff + models() + verdict จริง ไม่เชื่อจนกว่าจะเห็น.py รันได้ทุกพื้นผิวทั้งหมดนี้คือก้าวจาก "ผู้ใช้ Edge AI" เป็น "ผู้ต่อเติม Edge AI" — คุณเปิดฝากระโปรงเครื่องยนต์ได้แล้ว และรู้ว่าจะเสียบของใหม่เข้าไปตรงไหนอย่างปลอดภัย
ทักษะ "เพิ่มโมเดลเข้าเฟิร์มแวร์" ไม่ใช่แบบฝึกหัด — มันคืองานจริงของทีมผลิตภัณฑ์ Edge AI:
เห็นไหมว่า "เพิ่มโมเดลตัวที่ 7" วันนี้ คือทักษะเดียวกับที่ทีมจริงใช้ปล่อยฟีเจอร์ AI ใหม่ผ่าน OTA — เราแค่ทำมันครบวงจรบนโต๊ะเรียน
checklist ปิดงานจากเอกสารภายในของเฟิร์มแวร์ — ไล่ให้ครบก่อนบอกว่า "โมเดลเพิ่มสำเร็จ":
.tflite ใน Python ก่อน wrap)AIM_<NAME>_* / IMAI_<NAME>_* ไม่ชนกับใคร (nm เช็ก — ระวัง mtb_init global)s_models[] แล้ว, <name> อยู่ใน AI_MODELS, วางไฟล์แล้ว.ml_weights (กันล้น flash wall)rm -rf proj_cm55/build; make program EDGE_AI_MODEL=comboedge_ai.count() เพิ่มขึ้น, ชื่อใหม่ใน edge_ai.models(), ได้ verdict จริงข้อสุดท้ายคือกฎทองของการดีบักบนบอร์ด: หลัง flash เซนเซอร์/โมเดลบางตัวต้อง power-cycle ก่อน ไม่งั้นค่าที่วัดได้อาจหลอกเรา — "ONE change per flash, power-cycle before trusting"
งานทำเอง (ท้ายบทเรียน):
s19_extend_model.py ให้ครบทั้ง 5 ช่อง + ทำ 3 การแก้ในเฟิร์มแวร์ จนโมเดลใหม่โผล่ใน edge_ai.models() (บอร์ดจริง)edge_ai.count() ก่อน/หลัง เพิ่มโมเดล แล้วอธิบายว่าทำไมเลขเปลี่ยนโดยไม่ต้องแตะ MicroPythonSPEC ให้เป็นโมเดลของทีมเอง (เลือกเซนเซอร์ที่มี feed อยู่แล้ว) แล้วเล่าว่า 3 การแก้ของทีมต่างจาก Fall ตรงไหนใบ้ข้อ 3 — ถ้าเลือกเซนเซอร์ MIC (เช่น keyword) จะยืม feed_audio ได้ แต่ต้องระวัง front-end (FFT/mel) ให้ตรงกับตอน train — นี่คือกับดัก feature parity ที่เตือนไว้
วันนี้เราได้: เข้าใจว่าการเพิ่มโมเดล = 3 การแก้ · รู้จักสัญญา 4 ฟังก์ชัน + AIM_/IMAI_ · เข้าใจ feed กับ Vela · เพิ่ม Fall Detection เข้าทะเบียนแล้วรันได้จริง
ชุดบทเรียนถัดไป (บทเรียน 8.1–8.2 · Capstone) เราจะรวบทุกอย่างตั้งแต่ DAQ ถึง Apps มาสร้าง ผลิตภัณฑ์ Edge AI ของทีมเอง — เอาทักษะ "ต่อเติมเครื่องยนต์" วันนี้ไปใช้ได้เต็มที่ เจอกันครับ