# เฉลยปุ่มและ debounce พร้อมเหตุผล

ตารางเป็นผลคำนวณจาก calls ที่ประกาศใน test_input.cpp เดิม ไม่ใช่ log วัดบอร์ด ไม่มีรัน host tests ใหม่ Header ของสองชุดมีไบต์เดียวกัน ส่วน observations.csv เดิมมีเฉพาะ header ไม่มีผลฮาร์ดแวร์

## B1 · raw เป็นความหมายที่แปลงจากขา

UNO R3 ตั้งปุ่ม D2 ไป GND ด้วย INPUT_PULLUP และใช้ LED_BUILTIN ส่วน classic ESP32 ตั้งปุ่ม GPIO27 ไป GND และ LED ภายนอก GPIO25 ตาม sketch ทั้งสองคำนวณ digitalRead(buttonPin)==LOW จึงให้ raw_pressed=true/1 เมื่ออ่าน LOW ชื่อ GPIO ไม่ใช่ตำแหน่งขาบน header อย่าย้ายตัวเลขขาหรือวงจรระหว่างรุ่นโดยไม่ตรวจคู่มือ คงคำแนะนำแรงดันและ pinout ของบทเดิม

## B2 · candidate กับ stable คนละหน้าที่

raw คือค่าปุ่มที่โปรแกรมอ่านใน call candidate คือค่าล่าสุดที่เริ่มจับเวลารอ changedAt ถูกตั้งเมื่อ raw ต่างจาก candidate stable เป็นค่าที่ผ่านเงื่อนไขเวลา event=true เฉพาะ call ที่ stable เปลี่ยน เริ่มแต่ละ sequence ด้วย candidate=false/stable=false/changedAt0 แล้วไล่ 15 calls ตาม trace-answers ตารางนี้คำนวณ elapsed ของทุก call แม้ไม่ต้องเปลี่ยน stable เพื่อให้ฝึกอ่านสถานะ

## B3 · bounce เริ่มเวลาใหม่

100ms rawtrue เริ่ม candidate ที่100;105ms rawfalse เริ่มใหม่ที่105;110ms rawtrue เริ่มใหม่ที่110 เมื่อ139 elapsed29ms ยัง stablefalse/eventfalse;140 elapsed30ms จึง stabletrue/eventtrue เกณฑ์ due ใช้ >=30 ไม่ใช่ >30 นี่คือเงื่อนไขจากค่าที่อ่านในโจทย์ ไม่ได้พิสูจน์ว่าปุ่มจริงไม่เปลี่ยนเลยระหว่าง calls หรือ30msเหมาะกับปุ่มทุกตัว

## B4 · event เกิดทั้งกดและปล่อย

170ms candidate/stabletrueตรงกัน eventfalse จึงไม่เกิด eventกดซ้ำ ตอนปล่อย200 rawfalse เริ่ม200 แต่210 rawtrue กลับไป candidatetrue ที่210;220 rawfalse เริ่ม220;249 elapsed29 stableยังtrue;250 elapsed30 stablefalse/eventtrue event1จึงหมายถึง stable เปลี่ยน ทั้งกดและปล่อย ต้องอ่าน stable ประกอบ ไม่ใช่รับรองกดหนึ่งครั้งทุกบรรทัด

## B5 · elapsed unsigned ข้าม wrap

UINT32_MAX−9=4294967286 ค่า19ให้ (19−4294967286) mod4294967296=29ms;20ให้30ms stableเปลี่ยนที่20ตามขอบเดิม การลบแบบuint32เป็นส่วนของ header ไม่เปลี่ยนเป็นsignedหรือเทียบ now>=changedAt+30 โดยไม่พิจารณาwrap อย่างไรก็ตามโจทย์ไม่แยก reset/หลายwrap/ช่วงที่ไม่อ่าน ต้องมีrunและขอบช่วงก่อนนำไปอ้างผลจริง

## B6 · due และคาบที่ตั้ง

due(499,0,500)=false เพราะelapsed499;due(500,0,500)=true ที่ขอบ500 ส่วนprevious=UINT32_MAX−100=4294967195:now98ให้elapsed199ไม่due;99ให้200due LED500ms/รายงาน200msเป็นค่าตั้ง sketchทำ if ครั้งเดียวและตั้ง last=now ไม่วนcatch-upทุกคาบที่พลาด จึงไม่สรุปว่าช้ากี่รอบจากตารางนี้หรือรับรองคาบจริงเหมือนนาฬิกา

## B7 · event กับ serial report

changed || due(now,lastReport,200) ให้พิมพ์เมื่อมีeventหรือครบช่วงจากlastReport และตั้งlastReport=now ทุกครั้งที่พิมพ์ ขณะไม่มีeventอาจยังมีบรรทัดรายงานevent0 และเมื่อมีeventก็เริ่มนับช่วงรายงานใหม่ ตารางtraceแสดงทุกupdateที่ประกาศ ไม่ใช่บรรทัดที่Serialส่งจริง ไม่มีdelay()ไม่ได้แปลว่าSerialหรือทุกงานใช้เวลาเป็นศูนย์ ต้องตรวจเวลาค้าง/intervalบนบอร์ดแยก

## B8 · รายงานที่ไม่แต่งผลวัด

ตัวอย่างช่วงกด:อ้าง press_release calls4–6 ที่110/139/140ms elapsed0/29/30และ stable0/0/1,event0/0/1 ค่าที่เห็นเป็นผลคำนวณ ไม่รู้bounceจริงระหว่างcalls,wiring,USB,LEDหรือSerial Receiptcompileเดิมยืนยันbuildtarget ไม่ยืนยันupload/MCUtiming วางprotocolของตนเมื่อมีบอร์ดและใช้observations.csvเดิมที่ยังว่างบันทึกผลจริง ไม่กรอกโจทย์เหล่านี้เป็นผลทดลองจริง

เสนอ 16 คะแนนเพื่อทบทวน ข้อละคำตอบ 1 และเหตุผล/หน่วย/ขอบ 1 แยกจากเกณฑ์เดิมและผลผู้เรียนจริง
