แนะนำ BH1750 + หลักการ
BH1750 คือเซนเซอร์วัดความสว่างแบบดิจิทัล (Digital Light Sensor) ที่รายงานค่าเป็นหน่วย ลักซ์ (lux) ตรง ๆ ไม่ต้องคำนวณเองเหมือน LDR จึงอ่านค่าได้ นิ่งกว่า แม่นกว่า และแก้สัญญาณรบกวนง่ายกว่า เหมาะกับงาน Smart Farm / Smart Home ที่ต้อง “ตั้งเกณฑ์แสงแล้วสั่งงานอัตโนมัติ” เช่น เปิด/ปิดไฟโรงเรือน เปิดม่าน ม่านบังแดด หรือควบคุมไฟในบ้าน
จุดเด่นที่ควรรู้
- อ่านค่าเป็น lux โดยตรง: ไม่ต้องแปลงแรงดัน → ค่าใช้งานได้เลย
- สื่อสารผ่าน I2C: ใช้สายแค่ SDA/SCL ต่อกับ ESP32 ได้ทันที
- ช่วงวัดกว้าง: ตั้งแต่แสงสลัวในห้องไปจนถึงแสงจ้า (ระดับหมื่นลักซ์)
- โหมดวัดหลายแบบ: ความละเอียดสูง/ต่ำ และ ต่อเนื่อง (Continuous) หรือ ครั้งเดียว (One-shot)
- เสถียรต่อไฟฟ้ากระพริบ: เพราะวัดแบบบูรณาการเวลา (integration) จึงไม่สะท้านกับ PWM ของหลอดไฟเท่ากับ LDR
ภาพรวม & พื้นฐานเริ่มต้นใช้งาน ESP32
หลักการทำงาน
ภายใน BH1750 มี โฟโตไดโอด + วงจรแปลงสัญญาณอนาล็อกเป็นดิจิทัล (ADC) และ ตัวกรองสเปกตรัม ที่ตอบสนองใกล้เคียงสายตาคน (มาตรฐานโฟโตเมตริก) จึงให้หน่วย lux ซึ่งสอดคล้องกับการรับรู้ความสว่างของมนุษย์
เมื่อเริ่มวัด เซนเซอร์จะ “สะสมแสง” ชั่วขณะ (เช่น ~120 ms สำหรับโหมดความละเอียดสูง) แล้วค่อยส่งค่า 16 บิตออกมาทาง I2C ให้ไมโครคอนโทรลเลอร์อ่านไปใช้
หมายเหตุ: BH1750 วัด Illuminance (lux) ไม่ใช่ PAR/PPFD ที่ใช้ในพืชศาสตร์โดยตรง แต่ เพียงพอ สำหรับการควบคุมเชิงสวิตช์ (เปิดไฟ/ปิดไฟ/บังแสง) หรือการเทียบค่าแบบ relative ในงานฟาร์มขนาดเล็ก
โหมดการวัดที่ใช้งานบ่อย
- H-Resolution (~1 lux/สเต็ป, เวลาอ่าน ~120 ms): สมดุลความไวและความเร็ว ใช้ทั่วไป
- H-Resolution2 (~0.5 lux/สเต็ป): ยกระดับความละเอียด เมื่ออยากแยกแสงสลัวมาก ๆ
- L-Resolution (~4 lux/สเต็ป, เร็วขึ้น): ใช้เมื่ออยากอ่านไวหรือแสงแปรผันเร็ว
มีทั้ง Continuous (วัดต่อเนื่อง เหมาะกับกราฟ/แดชบอร์ด) และ One-shot (ประหยัดพลังงาน วัดเป็นครั้งคราว)
การต่อใช้งานกับ ESP32 (ภาพรวม)
- ไฟเลี้ยง: แนะนำ 3.3V (บางบอร์ด breakout ระบุ 3–5V ได้ แต่กับ ESP32 เลือก 3.3V ปลอดภัยกว่า)
- I2C: ปกติ ESP32 ใช้ SDA=GPIO21, SCL=GPIO22 (ปรับได้)
- ที่อยู่ I2C (Address): มาตรฐานมักเป็น 0x23 และสลับเป็น 0x5C ได้ด้วยขา ADDR (ขึ้นกับบอร์ด)
ตั้งเกณฑ์ยังไงให้ไม่กะพริบ (หลัก Hysteresis)
เวลาใช้ค่าแสงเพื่อสั่งรีเลย์ อย่าตัดสินใจที่จุดเดียว (จะกะพริบไปมาเมื่อแสงแกว่ง)
ให้ใช้ ฮิสเทอรีซิส เช่น
- เปิดไฟเมื่อ < 2,000 lux
- ปิดไฟเมื่อ > 2,500 lux
ต่างกัน 500 lux จะช่วยให้ระบบนิ่งขึ้นมาก
เทียบกับ LDR/โฟโต้เรซิสเตอร์
- LDR: ราคาถูก แต่เป็นค่า “ความต้านทาน” ต้องใช้วงจรแบ่งแรงดัน + แปลงสูตรเอง ค่าเพี้ยนตามอุณหภูมิสูง
- BH1750: ดิจิทัล, ได้ lux ตรง ๆ, ผลซ้ำ (repeatability) ดีกว่า และอ่านผ่าน I2C ง่ายกว่า
ข้อควรระวัง
- ตำแหน่งติดตั้ง: อย่าให้บังเงา/โดนน้ำ/ฝุ่นโดยตรง ใส่ฝาครอบโปร่งแสงคุณภาพดี (อะคริลิกใส) จะลดแสงลงเล็กน้อย → ควร “คาลิเบรตออฟเซ็ต” จากหน้างานจริง
- แดดกลางวันจัดมาก: BH1750 อาจเข้าใกล้เพดานช่วงวัดในกลางแจ้งที่แดดแรงมาก ๆ → ถ้าต้องวัดกลางแดด ควรหลบตำแหน่ง/ใช้บังบางส่วนเพื่ออ่านเป็นสัดส่วน
- ไฟ LED ที่หรี่ด้วย PWM: โดยทั่วไป BH1750 เฉลี่ยแสงได้ดี แต่ถ้าเกิดการสั่น (flicker) ให้เพิ่มเวลาเฉลี่ย/ปรับโหมดวัด
- บัส I2C ร่วมหลายตัว: ตรวจ address conflict และความยาวสาย/สัญญาณรบกวน
การต่อวงจร ESP32 + BH1750 + รีเลย์ควบคุมไฟ
อุปกรณ์ที่ใช้
- ESP32 DevKit V1 (3.3V logic)
- เซนเซอร์แสง BH1750 (บอร์ด I2C)
- รีเลย์ 5V แบบ 1/4 ช่อง (นิยมใช้ 4-CH)
- Buck แปลงไฟ 5V ≥ 2A (เช่น 9–12V IN → 5V OUT) สำหรับจ่ายรีเลย์
- สาย Dupont ตัวผู้-ตัวเมีย / สายไฟ AC พร้อมหัวคอนเน็กเตอร์มาตรฐาน
- โหลดไฟฟ้า: หลอดไฟ AC 220V (หรือจะใช้โหลด 12VDC ก็ได้ถ้าอยากหลบไฟบ้าน)
ขั้นตอนการต่อวงจร
- จ่ายไฟ
- จ่ายไฟให้ ESP32 ผ่าน USB (5V จากคอม/อะแดปเตอร์)
- บั๊ก 5V ต่อจากแหล่งจ่าย DC 9–12V → เอา 5V OUT ไปเลี้ยงรีเลย์ (กำลัง ≥2A ถ้าคลิกหลายช่อง)
- ต่อกราวด์ร่วม: GND ของ ESP32 ↔ GND ของรีเลย์ ↔ GND OUT ของบั๊ก
- ต่อ BH1750 (I2C) ไปยัง ESP32
- BH1750 VCC → 3V3 ของ ESP32 (ปลอดภัยสุดกับลอจิก 3.3V)
- BH1750 GND → GND ของ ESP32
- BH1750 SDA → GPIO21 (SDA) ของ ESP32
- BH1750 SCL → GPIO22 (SCL) ของ ESP32
- ADDR: ไม่ต่อ/ต่อ GND = ที่อยู่ 0x23 (ค่าเริ่มต้น), ถ้าต่อ VCC = 0x5C
- ต่อสัญญาณบังคับรีเลย์ (INx) จาก ESP32
- เลือกขา GPIO ดังนี้ (แก้ได้ตามสะดวก)
- GPIO25 → IN1
- รีเลย์หลายรุ่นเป็น Active-LOW (สั่ง ON ด้วย LOW). ดูสกรีน/จัมเปอร์บนบอร์ดแล้วปรับโค้ดให้ตรง
- เลือกขา GPIO ดังนี้ (แก้ได้ตามสะดวก)

ตัวอย่างโค้ด ESP32 (ใช้ไลบรารี BH1750.h + Wire.h)
ติดตั้งไลบรารี
- Arduino IDE → Tools → Manage Libraries…
- ค้นหา “BH1750” (by Christopher Laws) แล้วกด Install
สาย I2C (ค่าเริ่มต้น ESP32): SDA = 21, SCL = 22
ที่อยู่เซนเซอร์: 0x23 (ADDR = GND) หรือ 0x5C (ADDR = VCC)
สแกน I2C ก่อน (เช็ค address)
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // กำหนดขา I2C ของ ESP32
Serial.println("I2C Scanner...");
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.printf("Found I2C device at 0x%02X\n", addr);
delay(2);
}
}
}
void loop() {}

อ่านค่า Lux แบบพื้นฐาน
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
const uint8_t I2C_SDA = 21;
const uint8_t I2C_SCL = 22;
const uint8_t BH1750_ADDR = 0x23; // เปลี่ยนเป็น 0x5C ถ้า ADDR = VCC
void setup() {
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
// โหมดความละเอียดสูง อ่านต่อเนื่อง
bool ok = lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, BH1750_ADDR, &Wire);
if (!ok) {
Serial.println("BH1750 init failed. ตรวจสายไฟ/ที่อยู่ I2C");
while (1) delay(1000);
}
Serial.println("BH1750 ready.");
}
void loop() {
float lux = lightMeter.readLightLevel(); // หน่วยเป็น lux
Serial.printf("Lux: %.1f\n", lux);
delay(500);
}

ควบคุมไฟ/รีเลย์อัตโนมัติด้วยค่าแสง (มี Hysteresis + ฟิลเตอร์)
- เปิดไฟเมื่อมืดกว่า LUX_ON
- ปิดไฟเมื่อสว่างกว่า LUX_OFF
- ใช้ EMA (Exponential Moving Average) เพื่อลดสัญญาณกระพริบ
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
const uint8_t I2C_SDA = 21;
const uint8_t I2C_SCL = 22;
const uint8_t BH1750_ADDR = 0x23; // 0x23 หรือ 0x5C
// ตั้งค่ารีเลย์/ไฟ (เลือกขาที่ต่อจริง)
const int RELAY_PIN = 25;
// รีเลย์ส่วนใหญ่ Active LOW (สั่งติด = เขียน LOW)
const bool RELAY_ACTIVE_LOW = true;
// เกณฑ์ค่าแสง (ปรับตามหน้างาน)
const float LUX_ON = 200.0; // มืดกว่านี้ → เปิดไฟ
const float LUX_OFF = 400.0; // สว่างกว่านี้ → ปิดไฟ
// ฟิลเตอร์ EMA
float emaLux = NAN;
const float EMA_ALPHA = 0.25;
// ตัวจับเวลาแบบไม่บล็อก
unsigned long lastRead = 0;
const unsigned long READ_INTERVAL_MS = 500;
bool lightState = false; // สถานะไฟ/รีเลย์
void setRelay(bool on) {
lightState = on;
if (RELAY_ACTIVE_LOW) {
digitalWrite(RELAY_PIN, on ? LOW : HIGH);
} else {
digitalWrite(RELAY_PIN, on ? HIGH : LOW);
}
}
void setup() {
Serial.begin(115200);
// I2C
Wire.begin(I2C_SDA, I2C_SCL);
// BH1750
if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, BH1750_ADDR, &Wire)) {
Serial.println("BH1750 init failed. ตรวจสายไฟ/ADDR");
while (1) delay(1000);
}
// รีเลย์
pinMode(RELAY_PIN, OUTPUT);
// ตั้งเริ่มต้นให้ปิด
setRelay(false);
Serial.println("System ready.");
}
void loop() {
unsigned long now = millis();
if (now - lastRead >= READ_INTERVAL_MS) {
lastRead = now;
float lux = lightMeter.readLightLevel();
// เริ่มค่า EMA ครั้งแรก
if (isnan(emaLux)) emaLux = lux;
emaLux = EMA_ALPHA * lux + (1.0 - EMA_ALPHA) * emaLux;
// Logic Hysteresis
if (!lightState && emaLux <= LUX_ON) {
setRelay(true); // เปิดไฟเมื่อมืด
Serial.printf("[ON] Lux=%.1f (EMA=%.1f)\n", lux, emaLux);
} else if (lightState && emaLux >= LUX_OFF) {
setRelay(false); // ปิดไฟเมื่อสว่าง
Serial.printf("[OFF] Lux=%.1f (EMA=%.1f)\n", lux, emaLux);
} else {
Serial.printf("Lux=%.1f EMA=%.1f Light=%s\n",
lux, emaLux, lightState ? "ON" : "OFF");
}
}
}
อธิบายโค้ด + Flow การทำงาน
ตั้งค่าพินและที่อยู่ I2C
- I2C_SDA = 21, I2C_SCL = 22 คือขา I2C มาตรฐานของ ESP32 DevKit V1
- BH1750_ADDR = 0x23 (ถ้าโมดูลต่อขา ADDR = GND) หรือ 0x5C (ถ้า ADDR = VCC)
- เปลี่ยนพินได้ด้วย Wire.begin(SDA, SCL) ให้ตรงกับสายที่ต่อจริง
เริ่มต้นระบบ: Serial → I2C → BH1750 → Relay
- Serial.begin(115200) ไว้ดูค่าดีบัก
- Wire.begin(I2C_SDA, I2C_SCL) เปิดบัส I2C
- lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, BH1750_ADDR, &Wire) เริ่มเซนเซอร์โหมดอ่านต่อเนื่อง
- ตั้งค่ารีเลย์ pinMode(RELAY_PIN, OUTPUT) แล้วปิดไฟไว้ก่อนด้วย setRelay(false)
อ่านค่าแสง (lux) แบบต่อเนื่อง
- lightMeter.readLightLevel() คืนค่าเป็น lux (ยิ่งสูง = ยิ่งสว่าง)
- อ่านทุก ๆ READ_INTERVAL_MS (โค้ดใช้ 500 ms) แบบ non-blocking ด้วย millis() เพื่อกันค้างลูป
ฟิลเตอร์สัญญาณด้วย EMA (Exponential Moving Average)
- ตัวแปร emaLux ลดความผันผวนของค่าแสงจากเมฆ/ไฟกระพริบ
- สูตร: emaLux = α * lux + (1-α) * emaLux (แนะนำ α = 0.25)
- อยากนิ่งขึ้น → ลด α (เช่น 0.15) หรืออ่านช้าลง (1000–2000 ms)
เกณฑ์เปิด-ปิดแบบ Hysteresis
- LUX_ON (เช่น 200 lux): ถ้ามืดกว่านี้ → เปิดไฟ
- LUX_OFF (เช่น 400 lux): ถ้าสว่างกว่านี้ → ปิดไฟ
- ช่องว่างระหว่าง ON/OFF ทำให้รีเลย์ไม่กระพริบไปมา
ฟังก์ชัน setRelay() และ Active LOW
- โมดูลรีเลย์ส่วนใหญ่ Active LOW: เขียน LOW = ติด, HIGH = ดับ
- ฟังก์ชันห่อไว้ให้เรียกง่าย และเก็บสถานะ lightState ใช้งานต่อ
ดีบักสถานะและความปลอดภัย
- พิมพ์ค่า lux, emaLux, Light=ON/OFF ใน Serial ช่วยเทสไว
- ถ้า begin() ล้มเหลว → ค้างใน while พร้อมข้อความเตือน ให้ตรวจสาย/ADDR/ไฟเลี้ยง
Flow การทำงาน (ภาพรวม)
Flow 1: เริ่มต้นระบบ
- Boot → เริ่ม Serial
- เริ่ม I2C (Wire.begin)
- เริ่ม BH1750 (โหมด Continuous)
- ตั้งค่ารีเลย์เป็น ปิด
Flow 2: วนลูปอ่านค่าและตัดสินใจ
- ถึงเวลาอ่าน (millis() ครบช่วง) → อ่าน lux
- อัปเดต emaLux ด้วย EMA
- ถ้า lightState = OFF และ emaLux ≤ LUX_ON → สั่ง ON
- ถ้า lightState = ON และ emaLux ≥ LUX_OFF → สั่ง OFF
- พิมพ์สถานะลง Serial → รอรอบถัดไป



งานเครือข่าย/เว็บ (ต่อยอดแสดงผล & ควบคุมผ่าน Wi-Fi)
ดาวน์โหลดโค้ด
กรุณา เข้าสู่ระบบ เพื่อดาวน์โหลด
สรุป
- โปรเจ็กต์นี้ใช้ ESP32 + BH1750 อ่านค่าแสง (lux) แล้วคุมรีเลย์ เปิด/ปิดไฟอัตโนมัติ
- โค้ดตัวอย่างมีทั้ง I2C Scanner, อ่านค่า lux ต่อเนื่อง, ฟิลเตอร์ EMA ลดสัญญาณแกว่ง และ Hysteresis กันรีเลย์กระพริบ
- ปรับเกณฑ์ LUX_ON/LUX_OFF ให้เหมาะกับหน้างาน (ในห้อง/เรือนเพาะ/กลางแจ้ง) และตั้งช่วงอ่าน 500–2000 ms ตามความนิ่งที่ต้องการ
- ใช้งานจริงให้คำนึงถึง ความปลอดภัยไฟ 220VAC (ใช้กล่อง/ฟิวส์/ฉนวน) และเดินสาย I2C ไม่ยาวเกินไป
- สามารถต่อยอดสู่ Smart Farm/Smart Home ได้ เช่น เปิดไฟปลูก, ควบคุมผ้าม่าน/พัดลม, หรือผูกกับ Web Dashboard / แอป PoPo ทำงานบน Wi-Fi แบบ Local
FAQ คำถามที่พบบ่อย
1) BH1750 ใช้ไฟเท่าไร ต่อกับ ESP32 ได้ตรง ๆ ไหม?
ส่วนใหญ่โมดูลรับ 3.3–5V ได้ ต่อกับ 3.3V ของ ESP32 ได้ตรง ๆ และใช้ I2C (SDA=21, SCL=22 ตามบอร์ดยอดนิยม)
2) ทำไมไม่เจอเซนเซอร์บน I2C Scanner?
เช็กสาย SDA/SCL ไม่สลับ, เช็กไฟเลี้ยง, ลองสแกนใหม่ และดูที่อยู่ 0x23 (ADDR=GND) หรือ 0x5C (ADDR=VCC)
3) อยากใช้หลายตัวในบัสเดียว ทำได้ไหม?
ได้ 2 ตัวถ้าเปลี่ยนที่อยู่เป็น 0x23 และ 0x5C อย่างละตัว; มากกว่านั้นแนะนำ I2C Multiplexer (TCA9548A)
4) ค่า lux กระเพื่อมจนไฟกระพริบ แก้ยังไง?
ลดความไวของฟิลเตอร์ (เช่น EMA α = 0.15), เพิ่มช่วงอ่านเป็น 1000–2000 ms, และใช้ Hysteresis ห่างขึ้น
5) ค่ามาตรฐาน lux คร่าว ๆ มีเท่าไร?
ห้องมีไฟ: ~200–500 lux, ห้องทำงาน: ~500–1000 lux, กลางวันกลางแจ้ง: หลายหมื่น lux → ใช้เป็นแนวทางตั้งเกณฑ์ ON/OFF
6) รีเลย์บางรุ่นสั่งกลับขั้ว (ON กลายเป็น OFF) ทำไง?
เปลี่ยนลอจิกเป็น Active LOW/HIGH ในโค้ด หรือดูสเปกบอร์ดรีเลย์ (บอร์ดหลายรุ่นเป็น Active LOW)
7) สาย I2C ยาวได้แค่ไหน?
ยิ่งยาวยิ่งเสี่ยงรบกวน สายสั้นที่สุดยิ่งดี (<30–50 ซม.). ถ้าจำเป็นต้องยาว ให้ลดความถี่ I2C/ใช้สายคู่บิดเกลียว/พิจารณา I2C extender
8) ต้องคาลิเบรต BH1750 ไหมถ้าแสงเพี้ยน?
BH1750 ให้ค่า absolute ดีในระดับหนึ่ง แต่ในงานจริงใช้วิธี ชดเชย offset/สเกล จากค่ามาตรฐานพื้นที่หรือเครื่องวัดอ้างอิง
9) จะส่งค่า lux ไปหน้าเว็บหรือมือถือได้อย่างไร?
ฝั่งเว็บใช้ ESPAsyncWebServer ส่ง JSON/WS แบบเรียลไทม์; ฝั่งมือถือใช้แอป PoPo (Local Wi-Fi) รับค่าแล้วแสดง/สั่งงาน
10) ถ้าจะใช้กับไฟ 220VAC ต้องระวังอะไรบ้าง?
ต้องมี ฉนวน/กล่อง/ฟิวส์, เดินสายให้ปลอดภัย, แยกกราวด์สัญญาณกับไฟแรงดันสูง และทดสอบโดยผู้มีความชำนาญ






