บทความ › ไมโครคอนโทรลเลอร์และโค้ด
เซนเซอร์ สำหรับของเล่น ESP32: ปุ่ม PIR อัลตราโซนิก แสง ดิน IMU อุณหภูมิ
เซนเซอร์ที่ใช้บ่อยในของเล่นและงาน DIY แต่ละตัวคุยกับบอร์ดแบบไหน digital analog หรือ I2C ไฟ 3.3 V กับ 5 V ต่างกันยังไง และตัวไหนต้องลดแรงดันสัญญาณก่อนเข้า ESP32
- เซนเซอร์แบ่งตามวิธีคุยได้ 3 แบบ: digital (สูง/ต่ำ), analog (แรงดันต่อเนื่อง ผ่าน ADC) และ bus อย่าง I2C หรือ 1-Wire
- ขา GPIO ของ ESP32 รับได้ไม่เกินราว 3.6 V โมดูล 5 V ที่ส่งสัญญาณ 5 V กลับมา เช่น HC-SR04 ต้องลดแรงดันก่อน
- ใช้ขา analog ฝั่ง ADC1 (GPIO32–39) เพราะ ADC2 ใช้ไม่ได้ตอนเปิด Wi-Fi
- เซนเซอร์ analog ทุกตัวต้อง calibrate กับของจริง เช่นวัดค่าดินแห้งกับดินเปียกก่อนตั้งเกณฑ์
เซนเซอร์คือ “ตา หู และมือสัมผัส” ของของเล่นอิเล็กทรอนิกส์ ก่อนเลือกตัวไหน ให้ถามสองข้อ: มันส่งข้อมูลกลับมาแบบไหน (digital, analog หรือ I2C) และมันใช้ไฟกับส่งสัญญาณที่แรงดันเท่าไร สองข้อนี้ตัดสินว่าต่อตรงได้ หรือต้องมีตัวต้านทานคั่น บทนี้เป็นแผนที่รวมเซนเซอร์ที่ใช้บ่อย 7 แบบ
ตัวเลขอ้างอิง ESP32 รุ่นแรก (ESP32-WROOM) บน Arduino-ESP32 core 3.x
สามวิธีที่เซนเซอร์คุยกับบอร์ด
- Digital ส่งแค่สูงหรือต่ำ อ่านด้วย
digitalRead()เช่น ปุ่ม และ PIR - Analog ส่งแรงดันต่อเนื่อง บอร์ดแปลงเป็นตัวเลขด้วย ADC อ่านด้วย
analogRead()เช่น ตัวต้านทานแปรตามแสง (LDR) และเซนเซอร์ความชื้นดิน ESP32 ให้ค่า 0–4095 (12 บิต) - Bus ส่งเป็นข้อมูลดิจิทัลหลายไบต์ผ่านโปรโตคอล เช่น I2C (สาย SDA, SCL) หรือ 1-Wire (สายข้อมูลเส้นเดียว) ได้ค่าที่แปลงหน่วยมาแล้ว และต่อหลายตัวบนสายชุดเดียวได้
มีแบบที่สี่ที่ไม่เข้ากลุ่ม คือ จับเวลาพัลส์ อย่างอัลตราโซนิก HC-SR04 ที่ความกว้างพัลส์บอกระยะ
ตารางรวม: เซนเซอร์ 7 แบบสำหรับของเล่น
| เซนเซอร์ | วัดอะไร | วิธีคุย | ไฟเลี้ยง / สัญญาณ | ข้อควรรู้ |
|---|---|---|---|---|
| ปุ่มกด | กด/ปล่อย | digital | ไม่ต้องใช้ไฟ ใช้ pull-up ภายใน | ต้องกัน bounce |
| PIR | คนหรือสัตว์ขยับ | digital | ดูสเปกโมดูล, ขาออก 3.3 V | รอ 30–60 วินาทีหลังเปิดไฟ |
| HC-SR04 | ระยะ 2–400 cm | จับเวลาพัลส์ | 5 V, echo ออก 5 V | ต้องลดแรงดันขา echo |
| LDR | ความสว่าง | analog | ต่อเป็นวงจรแบ่งแรงดัน | ไม่เป็นเชิงเส้น |
| ความชื้นดิน (capacitive) | ดินแห้งหรือเปียก (ค่าเทียบ) | analog | 3.3–5.5 V, ขาออก 0–3.0 V | calibrate ดินแห้ง/เปียก |
| IMU (MPU-6050) | ความเร่ง + การหมุน 6 แกน | I2C | บอร์ดเบรกเอาต์ 3–5 V | address 0x68 / 0x69 |
| อุณหภูมิ (BME280 / DS18B20) | อุณหภูมิ (+ความชื้น ความกด) | I2C / 1-Wire | BME280 ดูบทเฉพาะ, DS18B20 3.0–5.5 V | ความร้อนจากบอร์ดทำค่าเพี้ยน |
3.3 V กับ 5 V: เรื่องที่พังบอร์ดได้
ESP32 ทำงานที่ 3.3 V วิศวกรของ Espressif ตอบในฟอรัมว่าขาอินพุตรับได้ไม่เกิน VDD + 0.3 V คือราว 3.6 V ขา GPIO จึงไม่รับ 5 V ตรง ๆ
แยกให้ออกสองเรื่อง:
- ไฟเลี้ยงเซนเซอร์ เลี้ยงโมดูลด้วย 5 V ได้ ถ้าโมดูลออกแบบมาแบบนั้น
- สัญญาณที่ส่งกลับเข้าขา ESP32 ต้องไม่เกิน 3.3 V
โมดูลความชื้นดิน capacitive เลี้ยง 5 V ได้แต่ส่งออกสูงสุด 3.0 V จึงปลอดภัย ส่วน HC-SR04 รุ่นดั้งเดิมเลี้ยง 5 V และขา echo ส่งออก 5 V ต้องลดแรงดันก่อน (รุ่นใหม่บางรุ่นทำงานที่ 3.3 V ได้ ดูสเปกของตัวที่ซื้อ)
ก่อนต่อเซนเซอร์ตัวใหม่ ถามว่า “ขาที่ส่งสัญญาณกลับมาสูงสุดกี่โวลต์” ไม่ใช่แค่ “เลี้ยงไฟกี่โวลต์”
ตัวอย่างคำนวณ: HC-SR04 ตั้งแต่สายถึงระยะ
ลดแรงดันขา echo ด้วยตัวต้านทาน 2 ตัว (voltage divider) R1 = 1 kΩ จาก echo ไป GPIO และ R2 = 2 kΩ จาก GPIO ลงกราวด์
- Vout = 5 V × R2 ÷ (R1 + R2) = 5 × 2 ÷ 3 ≈ 3.33 V อยู่ในช่วงปลอดภัย
- ผลรวม 3 kΩ มากกว่า 1 kΩ ตามที่ Adafruit แนะนำ กระแสจากขา echo จึงไม่เกินที่โมดูลจ่ายได้
แปลงพัลส์เป็นระยะ สูตรใน datasheet: ระยะ (cm) = เวลาพัลส์ (µs) ÷ 58
- วัด echo ได้ 1,160 µs → 1,160 ÷ 58 = 20 cm
- ตรวจด้วยความเร็วเสียง 340 m/s: 0.00116 s × 340 ÷ 2 = 0.197 m ≈ 20 cm (หารสองเพราะเสียงเดินทางไปและกลับ)
- datasheet แนะนำให้วัดห่างกันเกิน 60 ms ไม่ให้เสียงสะท้อนรอบก่อนปนรอบใหม่ → อ่านได้ไม่เกินราว 16 ครั้งต่อวินาที
// ESP32, TRIG = GPIO5, ECHO = GPIO18 (ผ่านตัวแบ่งแรงดัน)
const int TRIG = 5, ECHO = 18;
void setup() { Serial.begin(115200); pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT); }
void loop() {
digitalWrite(TRIG, HIGH); delayMicroseconds(10); digitalWrite(TRIG, LOW);
unsigned long us = pulseIn(ECHO, HIGH, 30000); // timeout 30 ms
if (us) Serial.println(us / 58.0); // cm
delay(60);
}
วัตถุที่วัดควรเรียบและใหญ่พอ datasheet ระบุพื้นที่ไม่น้อยกว่า 0.5 ตารางเมตรสำหรับค่าตามสเปก ผ้า ขนตุ๊กตา หรือวัตถุเอียง ๆ สะท้อนเสียงได้น้อย ค่าจะกระโดด
Analog บน ESP32: เลือกขาให้ถูก
- ADC ให้ค่า 0–4095 ที่การลดทอน 11 dB วัดได้ราว 150–3,100 mV ไม่ใช่ 0–3.3 V เต็ม ปลายสองข้างอ่านไม่แม่น
- ใช้
analogReadMilliVolts()ได้ค่ามิลลิโวลต์ที่ calibrate แล้ว ดีกว่าแปลงจากanalogRead()เอง - ADC2 ใช้ไม่ได้ตอนเปิด Wi-Fi (เอกสาร ESP-IDF) ของเล่นที่ต่อ Wi-Fi ให้ใช้ขา ADC1 คือ GPIO32–39
- GPIO34–39 เป็นอินพุตอย่างเดียว ไม่มี pull-up/pull-down ภายใน ใช้กับปุ่มต้องมีตัวต้านทานภายนอก
LDR ต่อเป็นวงจรแบ่งแรงดันกับตัวต้านทาน 10 kΩ (Adafruit แนะนำสำหรับในร่ม) ตัวอย่าง: ห้องมืด ~10 lux LDR ประมาณ 10 kΩ → 3.3 × 10 ÷ (10 + 10) = 1.65 V ห้องสว่าง 100 lux LDR ~1.5 kΩ → 3.3 × 10 ÷ 11.5 ≈ 2.87 V ค่า LDR แต่ละตัวต่างกัน วัดตัวที่ซื้อมาจริงด้วยมัลติมิเตอร์
ความชื้นดิน อ่านค่าตอนอยู่ในอากาศ (แห้งสุด) กับตอนจุ่มน้ำ (เปียกสุด) แล้วใช้สองค่านั้นเป็นขอบ อย่าใช้ตัวเลขจากบทความอื่น เพราะต่างกันทุกตัว
Digital และ bus: ปุ่ม PIR IMU อุณหภูมิ
- ปุ่ม ใช้
pinMode(pin, INPUT_PULLUP)เปิดตัวต้านทานภายในราว 45 kΩ ต่อปุ่มลงกราวด์ อ่านได้ LOW เมื่อกด ปุ่มเชิงกลเด้ง (bounce) ตอนกด ต้องหน่วงหรือกรองในโค้ด - PIR ขาออกเป็น 3.3 V เมื่อจับการเคลื่อนไหวได้ (ตามที่ Adafruit ทดสอบ) จัมเปอร์ H = ค้างสูงตราบที่ยังมีการเคลื่อนไหว, L = ส่งครั้งเดียว ต้องรอ 30–60 วินาทีหลังเปิดไฟให้เซนเซอร์นิ่ง
- IMU MPU-6050 คุยผ่าน I2C address 0x68 ดึงขา AD0 ขึ้นเพื่อย้ายไป 0x69 บอร์ดเบรกเอาต์ของ Adafruit รับไฟ 3–5 V มีตัวลดแรงดันในตัว เหมาะกับของเล่นที่ต้องรู้ว่าเอียงหรือถูกเขย่า
- อุณหภูมิ BME280 ใช้ I2C ให้ทั้งอุณหภูมิ ความชื้น ความกด (ดูบท BME280 กับ ESP32) DS18B20 ใช้ 1-Wire ไฟ 3.0–5.5 V ต้องมี pull-up ราว 4.7 kΩ ที่สายข้อมูล และแปลงค่าที่ 12 บิตใช้เวลา 750 ms
ข้อผิดพลาดที่เจอบ่อย
- ต่อขา echo ของ HC-SR04 ตรงเข้า ESP32 อาจใช้ได้ไปสักพักแล้วขานั้นเสีย ใส่ตัวแบ่งแรงดันเสมอ
- ใช้ขา ADC2 แล้วค่าหายตอนเปิด Wi-Fi ย้ายไป GPIO32–39
- ใช้ INPUT_PULLUP กับ GPIO34–39 ไม่มีผล ขาลอย ค่ามั่ว
- ทดสอบ PIR ทันทีหลังเสียบไฟ ได้สัญญาณหลอก รอให้นิ่งก่อน
- ปักเซนเซอร์ดินแบบ resistive ทิ้งไว้ทั้งเดือน ขากร่อน ค่าเลื่อน เปิดไฟเฉพาะตอนอ่าน หรือเปลี่ยนเป็น capacitive
- วางเซนเซอร์อุณหภูมิชิดบอร์ด ความร้อนจาก ESP32 ทำให้อ่านสูงเกินจริง เว้นระยะหรือพิมพ์กล่องที่มีช่องระบาย (ดูพิมพ์กล่องให้บอร์ด)
ความปลอดภัย
เซนเซอร์ทั้งหมดในบทนี้ใช้ไฟ 3.3–5 V จากบอร์ดหรืออะแดปเตอร์ที่ปิดมิดชิด ห้ามต่อเซนเซอร์เข้ากับไฟบ้านโดยตรง ถ้าเซนเซอร์ดินอยู่กลางแจ้ง กันน้ำส่วนวงจรและสายต่อ เพราะความชื้นทำให้ลัดวงจรได้ แม้แรงดันต่ำ
บทนี้เป็นบทสุดท้ายของเส้นทาง ต่อไปลองรวมเซนเซอร์กับเซอร์โวจากบทก่อน เป็นของเล่นที่ตอบสนองต่อคนได้
แหล่งข้อมูล
- HC-SR04 Ultrasonic Ranging Module datasheet — Elecfreaks (via SparkFun)
- ADC — Arduino-ESP32 docs (Espressif)
- GPIO and RTC GPIO — ESP-IDF Programming Guide (Espressif)
- HC-SR04: Connect the sensor — Adafruit Learning System
- Capacitive Soil Moisture Sensor SEN0193 — DFRobot Wiki
- MPU-6050 Pinouts — Adafruit Learning System
คำถามที่พบบ่อย
เซนเซอร์ความชื้นดินแบบไหนดีกว่า
แบบ capacitive ทนกว่า เพราะขั้วเคลือบไว้ ไม่มีกระแสไหลผ่านดิน ส่วนแบบ resistive ที่เป็นขาโลหะเปลือยจะกร่อนจากกระแสไฟตรงเมื่อปักไว้นาน ๆ แต่แบบ capacitive ก็ต้องกันน้ำส่วนวงจรด้านบนและขอบ PCB ที่ตัดไว้
อ่านค่า analog จาก ESP32 แล้วแกว่ง ทำยังไง
อ่านหลายครั้งแล้วเฉลี่ย ใช้ analogReadMilliVolts() ที่ calibrate แล้วแทน analogRead() และอย่าวางสายสัญญาณ analog ขนานกับสายมอเตอร์หรือเซอร์โว
ต่อเซนเซอร์ I2C หลายตัวพร้อมกันได้ไหม
ได้ ถ้า address ไม่ชนกัน เช่น MPU-6050 อยู่ 0x68 และย้ายไป 0x69 ได้ด้วยขา AD0 รัน I2C scanner ก่อนทุกครั้งเพื่อดูว่าเจอครบ
วงจรและโค้ดในบทความทดสอบกับบอร์ดตัวอย่าง บอร์ดต่างรุ่นอาจใช้ขาต่างกัน ตรวจ pinout ของบอร์ดที่ใช้ก่อนต่อไฟเสมอ