ตัวบ่งชี้ความชื้นและอุณหภูมิจาก SHT4x
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”- อ่านความชื้นสัมพัทธ์และอุณหภูมิจาก SHT4x ผ่าน I2C แล้วแสดงเป็นตัวบ่งชี้
- ตั้งเกณฑ์สีของตัวบ่งชี้จากช่วงความชื้นที่สบาย และอธิบายที่มาของเกณฑ์
- เปรียบเทียบอุณหภูมิจาก SHT4x กับ DPS368 และอธิบายว่าทำไมอาจไม่เท่ากัน
SHT4x คืออะไร และตัวเลขในสเปกหมายถึงอะไร
หัวข้อที่มีชื่อว่า “SHT4x คืออะไร และตัวเลขในสเปกหมายถึงอะไร”SHT4x (SHT40/41/45) เป็นเซนเซอร์วัดความชื้นสัมพัทธ์ (RH%) และอุณหภูมิของ Sensirion รุ่น SHT40 แม่นยำ ±1.8 %RH และ
±0.2 °C วัด RH ได้ 0–100% และอุณหภูมิ -40 ถึง +125 °C กินไฟเฉลี่ยต่ำกว่า 0.4 µA ที่อัตราวัด 1 ครั้ง/วินาที
ต่างจาก DPS368/BMI270 ตรงที่ SHT4x ไม่มี register map ให้อ่าน-เขียนทีละ address แต่คุยกันด้วย command-based
protocol: ส่ง 1 byte สั่งวัด แล้วรอ conversion delay (สูงสุดราว 8.2 ms ที่ high precision) ก่อนอ่านผลกลับ 6
byte พร้อม CRC-8 ตรวจสอบความถูกต้อง (polynomial 0x31 ตามมาตรฐานของ Sensirion) — โปรโตคอลระดับนี้เป็นความรู้จริง
ของเซนเซอร์ตระกูลนี้ แต่ ไม่ได้ถูกเขียนเองในไฟล์ของ episode นี้เลย
ทำไมต้องรู้ว่าโค้ดชั้นไหนทำอะไรจริง
หัวข้อที่มีชื่อว่า “ทำไมต้องรู้ว่าโค้ดชั้นไหนทำอะไรจริง”sht4x_driver.c ของ episode นี้ไม่ได้ส่ง command byte, รอ delay, หรือคำนวณ CRC-8/สูตรแปลงหน่วยเอง — มันเรียก
mtb_sht4x_measure_high_precision(i2c_bus, &temp_milli_c, &hum_milli_rh) ของมิดเดิลแวร์ Infineon ตัวเดียว ซึ่ง
ทำทุกขั้นตอน (ส่ง command 0xFD, รอ delay, อ่าน 6 byte, ตรวจ CRC, แปลงหน่วยตามสูตร Sensirion) ไว้ให้เสร็จแล้ว คืน
ค่ากลับมาเป็นหน่วย milli (milli-°C, milli-%RH) — โค้ดของ episode แค่หาร 1000 เพื่อแปลงเป็นหน่วยปกติ
(temperature_c, humidity_rh) โปรโตคอลระดับ byte ที่ README ต้นทางอธิบายไว้ละเอียดจึงเป็นสิ่งที่เกิดขึ้นจริง
บนสาย I2C แต่ซ่อนอยู่ในมิดเดิลแวร์ ไม่ใช่โค้ดที่ episode นี้ให้นักเรียนอ่าน — เหมือนกับที่ DPS368 (บทเรียน 3.1)
ใช้ xensiv_dps3xx_read() และ BMI270 (บทเรียน 3.2) ใช้ config file ของ Bosch: รูปแบบซ้ำของซีรีส์นี้คือห่อโปรโตคอล
ระดับ byte ไว้ในไลบรารีของผู้ผลิตเซนเซอร์เสมอ
เกณฑ์สีจริงมีแค่ 3 โซน ไม่ใช่ 4 โซนตามที่ README ต้นทางอธิบาย
หัวข้อที่มีชื่อว่า “เกณฑ์สีจริงมีแค่ 3 โซน ไม่ใช่ 4 โซนตามที่ README ต้นทางอธิบาย”sht4x_view.c มีฟังก์ชัน hum_level_color() และ set_comfort_chip() ที่ใช้เกณฑ์เดียวกันคือ RH < 40% = Dry
(สีเหลืองอำพัน), 40–60% = Comfort (สีเขียว), RH > 60% = Humid (สีน้ำเงิน) — มีแค่สองจุดตัด (40 กับ 60) ไม่ใช่
สามจุดตัด (30/60/80) และไม่มีโซน “อันตราย” สีแดงแยกต่างหากตามที่ README ต้นทางอธิบาย ช่วง comfort 40–60% ตรงกับ
คำแนะนำทั่วไปของ HVAC/ASHRAE สำหรับความชื้นในอาคารที่สบายและลดการเติบโตของเชื้อรา/ไรฝุ่น
เกณฑ์สีถูกกำหนดซ้ำสองที่ ต้องแก้พร้อมกันเสมอ
หัวข้อที่มีชื่อว่า “เกณฑ์สีถูกกำหนดซ้ำสองที่ ต้องแก้พร้อมกันเสมอ”hum_level_color() (กำหนดสีของ chip) และ set_comfort_chip() (กำหนดข้อความ “Dry”/“Comfort”/“Humid”) เป็นสอง
ฟังก์ชันแยกกัน แต่ต่างก็ hard-code ค่า 40.0f และ 60.0f ของตัวเอง ไม่ได้แชร์ constant เดียวกัน — ถ้าแก้เกณฑ์ใน
ฟังก์ชันเดียวโดยลืมอีกฟังก์ชัน จะได้ข้อความกับสีที่ไม่ตรงกัน (เช่น ข้อความขึ้น “Humid” แต่สียังเป็นสีเขียวของ
“Comfort”)
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”โค้ดของ episode นี้อยู่ใน Developer Hub (อ้างอิงที่ commit 9a8e3ed) — อ่าน Why ของ README ต้นทาง เพื่อเข้าใจความรู้เรื่องโปรโตคอลของ SHT4x แต่ โค้ดตัวอย่างด้านล่างคัดลอกจากไฟล์จริง (Apache-2.0, tesaiot/developer-hub, commit เดียวกัน) เพราะโปรโตคอลระดับ byte อยู่ในมิดเดิลแวร์ ไม่ใช่ในไฟล์ของ episode และเกณฑ์สีจริงต่างจากที่ README ต้นทางอธิบาย
app_sensor/sht4x/sht4x_driver.c — เรียกมิดเดิลแวร์ตัวเดียว ไม่มี command byte/CRC ในไฟล์นี้:
cy_rslt_t sht4x_driver_read_sample(sht4x_sample_t *sample){ int32_t temp_milli_c = 0; int32_t hum_milli_rh = 0;
cy_rslt_t rslt = mtb_sht4x_measure_high_precision(s_i2c_bus, &temp_milli_c, &hum_milli_rh); if (CY_RSLT_SUCCESS != rslt) { return rslt; }
/* Middleware returns milli-units; convert once here for UI/presenter layers. */ sample->temperature_c = ((float)temp_milli_c) / 1000.0f; sample->humidity_rh = ((float)hum_milli_rh) / 1000.0f; return CY_RSLT_SUCCESS;}app_ui/sht4x/sht4x_view.c — เกณฑ์สีตัวจริง สามโซน สองจุดตัด:
static lv_color_t hum_level_color(float humidity_rh){ if (humidity_rh < 40.0f) { return lv_color_hex(0xD97706); /* Dry */ }
if (humidity_rh <= 60.0f) { return lv_color_hex(0x16A34A); /* Comfort */ }
return lv_color_hex(0x2563EB); /* Humid */}main_example.cส่ง I2C handle เข้าsht4x_presenter_start()ตรงตามที่ README ต้นทางอธิบายapp_sensor/sht4x/sht4x_config.h—SHT4X_SAMPLE_PERIOD_MS = 1000(poll ด้วยlv_timerเดียวบน LVGL thread แบบเดียวกับบทเรียน 3.1–3.2) และที่อยู่ I2C หลัก/สำรอง- ดูโฟลเดอร์เต็มที่
int_ep03_sht40_indicator/
จุดที่มักพลาด
หัวข้อที่มีชื่อว่า “จุดที่มักพลาด”- คิดว่าต้องเขียน command byte/CRC-8 เองในโค้ดของ episode นี้ — โปรโตคอลระดับ byte ถูกทำใน
mtb_sht4x_measure_high_precision()ของมิดเดิลแวร์แล้ว ไฟล์sht4x_driver.cของ episode แค่เรียกมันแล้วแปลง หน่วยจาก milli เป็นหน่วยปกติ - จำเกณฑ์สีผิดเป็น 4 โซน (30/60/80%) — เกณฑ์จริงมีแค่ 3 โซนที่จุดตัด 40% และ 60% ไม่มีโซนสีแดง “อันตราย” แยกต่างหาก
- แก้เกณฑ์สีแค่ฟังก์ชันเดียว —
hum_level_color()และset_comfort_chip()มีค่า 40.0f/60.0f แยกกันคนละที่ ต้องแก้พร้อมกันเสมอ ไม่งั้นข้อความกับสีจะไม่ตรงกัน
build และ flash
หัวข้อที่มีชื่อว่า “build และ flash”# ในโฟลเดอร์ master template (ดูบทเรียน 1.1)# 1) ลบไฟล์ของ episode เก่าใน proj_cm55/apps/# 2) คัดลอกไฟล์ทั้งหมดของ episode นี้ลงใน proj_cm55/apps/make buildmake program # flash ผ่าน KitProg3หรือเปิด ตัวอย่างนี้บน Developer Hub แล้ว flash เฟิร์มแวร์สำเร็จรูป
ดูของจริงก่อน
หัวข้อที่มีชื่อว่า “ดูของจริงก่อน”
ก่อนอ่านโค้ด ให้ทายว่าหน้าจอนี้มี object อะไรบ้าง และอะไรเปลี่ยนเมื่อผู้ใช้แตะหรือเมื่อค่าเซนเซอร์เปลี่ยน
- ทาย ก่อนแก้: เลือกค่าหนึ่งค่าที่ README ของตัวอย่างอธิบายไว้ในส่วน How แล้วเขียนว่าจะเห็นอะไรเปลี่ยนบนจอหรือใน log
- แก้และรัน build + flash แล้วเทียบกับที่ทายไว้ ถ้าไม่ตรง ให้หาว่าเข้าใจส่วนไหนผิด
- ทำเพิ่ม ต่อยอดหนึ่งอย่างที่ตัวอย่างยังไม่มี แล้วเก็บภาพหรือวิดีโอไว้ใน portfolio
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”- ความชื้นสัมพัทธ์ขึ้นกับอุณหภูมิอย่างไร
- ทำไมเซนเซอร์สองตัวบนบอร์ดเดียวกันอ่านอุณหภูมิไม่เท่ากัน
- เกณฑ์สีของคุณใช้ช่วงความชื้นเท่าไร และอ้างอิงจากอะไร
คำตอบอยู่ใน README ของตัวอย่างและในโค้ด ถ้าตอบข้อใดไม่ได้ ให้กลับไปอ่านส่วน Why / What / How อีกครั้ง
แหล่งอ้างอิง
หัวข้อที่มีชื่อว่า “แหล่งอ้างอิง”- README ของ episode · โฟลเดอร์โค้ด · commit
9a8e3ed - เปิดตัวอย่างนี้บน Developer Hub
- โค้ดเป็นของ Developer Hub และอ้างอิงด้วยลิงก์ ไม่ได้คัดลอกเข้าคลังนี้
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
เปิดเครื่องทำความชื้นในห้องแห้ง ค่า RH ไต่จาก 35 → 50 → 65 %RH ชิปสถานะ comfort จะแสดงข้อความตามลำดับใด (เป้าหมายข้อ 2)
- Comfort → Comfort → Humid
- Dry → Comfort → Comfort
- Dry → Comfort → Humid
- Dry → Humid → Humid
ดูเฉลย
คำตอบ: C. Dry → Comfort → Humid
set_comfort_chip() ใช้เกณฑ์ < 40 = Dry, 40–60 = Comfort, > 60 = Humid (ข้อความ range_hint บนจอเขียนไว้ตรงกัน) README ของ episode ยังเขียนเกณฑ์ 30/60/80 ซึ่งไม่ตรงกับโค้ดที่ commit นี้
-
ถ้าแก้เกณฑ์บนจาก 60 เป็น 65 เฉพาะใน hum_level_color() เมื่อ RH = 62 %RH จอจะแสดงอย่างไร (เป้าหมายข้อ 2)
- ชิปขึ้น Comfort สีเขียว ตรงกันทั้งหมด
- ชิปขึ้นข้อความ Humid แต่เป็นสีเขียว เพราะข้อความใน set_comfort_chip() ยังใช้เกณฑ์ 60 ของตัวเอง
- ชิปขึ้น Humid สีน้ำเงิน ตรงกันทั้งหมด
- build ไม่ผ่าน
ดูเฉลย
คำตอบ: B. ชิปขึ้นข้อความ Humid แต่เป็นสีเขียว เพราะข้อความใน set_comfort_chip() ยังใช้เกณฑ์ 60 ของตัวเอง
สีมาจาก hum_level_color() แต่ข้อความมาจาก if ใน set_comfort_chip() และ range_hint ก็พิมพ์ตัวเลขไว้อีกที่ เกณฑ์เดียวกันจึงซ้ำอยู่สามจุด การย้ายเกณฑ์ไปเป็นค่าคงที่ตัวเดียวแล้วให้ทุกจุดอ่านจากที่เดียวกันป้องกันความไม่ตรงกันแบบนี้ และทำให้อธิบายที่มาของเกณฑ์ได้ในที่เดียว
-
ระหว่างทำงาน สายหลวมจนอ่านเซนเซอร์ไม่ได้ติดต่อกันหลายวินาที แล้วกลับมาอ่านได้ presenter ทำอะไร (เป้าหมายข้อ 1)
- แสดง error ใหม่ทุกวินาทีจนกว่าจะหาย
- หยุด timer ถาวรหลัง error แรก
- รีเซ็ตบอร์ด
- ขึ้นข้อความ error และ log READ_FAIL ครั้งเดียวเมื่อรหัสเปลี่ยน อ่านต่อทุก 1 วินาที และเมื่ออ่านได้อีกครั้งจะกลับเป็นสถานะ ready พร้อมค่าใหม่
ดูเฉลย
คำตอบ: D. ขึ้นข้อความ error และ log READ_FAIL ครั้งเดียวเมื่อรหัสเปลี่ยน อ่านต่อทุก 1 วินาที และเมื่ออ่านได้อีกครั้งจะกลับเป็นสถานะ ready พร้อมค่าใหม่
sht4x_poll_sensor_cb() ถูกเรียกทุก SHT4X_SAMPLE_PERIOD_MS (1000 ms) ตลอด การแสดง error ถูกกันซ้ำด้วย s_last_status_error และเมื่อ has_new_sample เป็น true จะเรียก sht4x_view_set_ready() อีกครั้ง ผู้ใช้จึงเห็นสถานะจริงโดยจอไม่กระพริบ
-
บนบอร์ดเดียวกัน SHT4x อ่านได้ 31.2 °C แต่ DPS368 อ่านได้ 33.0 °C ข้อใดอธิบายได้สมเหตุสมผลที่สุด (เป้าหมายข้อ 3)
- เซนเซอร์แต่ละตัววัดอุณหภูมิของตัวเองตรงตำแหน่งที่มันอยู่บนบอร์ด ความร้อนจากชิ้นส่วนใกล้เคียง เช่นตัวประมวลผล วงจร Wi-Fi หรือจอ ไม่เท่ากัน และความแม่นยำของแต่ละตัวก็ต่างกัน
- DPS368 เสีย เพราะสองตัวควรอ่านได้เท่ากันทุกครั้ง
- ตัวหนึ่งรายงานเป็น °F
- โค้ดแปลงหน่วยจาก milli-degree ผิด
ดูเฉลย
คำตอบ: A. เซนเซอร์แต่ละตัววัดอุณหภูมิของตัวเองตรงตำแหน่งที่มันอยู่บนบอร์ด ความร้อนจากชิ้นส่วนใกล้เคียง เช่นตัวประมวลผล วงจร Wi-Fi หรือจอ ไม่เท่ากัน และความแม่นยำของแต่ละตัวก็ต่างกัน
SHT4x ออกแบบมาวัดอุณหภูมิและความชื้นของอากาศ (README ระบุ ±0.2 °C) ส่วน DPS368 วัดอุณหภูมิเพื่อใช้ชดเชยการวัดความดันด้วย ทั้งคู่อยู่คนละตำแหน่งบน PCB ที่มีความร้อนสะสม ถ้าต้องการอุณหภูมิห้องจริงควรแยกเซนเซอร์ออกจากแหล่งความร้อน หรือเทียบกับเทอร์โมมิเตอร์อ้างอิง
-
ถ้าความร้อนจากบอร์ดทำให้อากาศรอบ SHT4x อุ่นกว่าอากาศในห้อง ค่า RH ที่อ่านได้จะเป็นอย่างไรเมื่อเทียบกับ RH ของห้อง (เป้าหมายข้อ 3)
- สูงกว่า เพราะอากาศร้อนมีไอน้ำมากกว่า
- ต่ำกว่า เพราะปริมาณไอน้ำเท่าเดิม แต่อากาศที่อุ่นขึ้นรับไอน้ำได้มากขึ้น ความชื้นสัมพัทธ์จึงลดลง
- เท่ากัน เพราะ RH ไม่ขึ้นกับอุณหภูมิ
- สุ่ม ขึ้นกับจังหวะการอ่าน
ดูเฉลย
คำตอบ: B. ต่ำกว่า เพราะปริมาณไอน้ำเท่าเดิม แต่อากาศที่อุ่นขึ้นรับไอน้ำได้มากขึ้น ความชื้นสัมพัทธ์จึงลดลง
RH คือสัดส่วนไอน้ำที่มีอยู่เทียบกับไอน้ำที่อากาศอุณหภูมินั้นรับได้เต็มที่ อากาศอุ่นรับได้มากขึ้น ถ้าไอน้ำเท่าเดิม RH จึงลดลง นี่คือเหตุที่ต้องอ่านอุณหภูมิคู่กับ RH เสมอ และต้องระวังความร้อนจากบอร์ดเมื่อเทียบกับเครื่องวัดในห้อง
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"ตัวบ่งชี้ความชื้นและอุณหภูมิจาก SHT4x" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "Humidity and temperature indicator from the SHT4x" 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
บทเรียนนี้ดัดแปลงจากต้นฉบับด้านล่าง เมื่ออ้างอิงให้คงเครดิตต้นฉบับไว้ด้วย
https://github.com/tesaiot/developer-hub/blob/9a8e3ed1d813bfd67fabf6b7ac15c6ff9750b465/int_ep03_sht40_indicator · Code stays in the Developer Hub and is linked at pinned commits, never copied: the episodes, practice codes and main-branch examples are Apache-2.0; the master template and the OPTIGA client carry Infineon/Cypress EULAs.
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA