آموزش پروژه‌محور اندازه‌گیری شدت روشنایی

راه‌اندازی BH1750 با ESP32 و Arduino؛ اندازه‌گیری نور بر حسب لوکس

BH1750 یک حسگر دیجیتال نور محیط با خروجی مستقیم لوکس و رابط I2C است. در این راهنما مشخصات تراشه خام و برد آماده، آدرس‌ها، حالت‌های اندازه‌گیری، سیم‌کشی، کد عملی و روش ساخت یک کنترل‌کننده روشنایی مطمئن را بررسی می‌کنیم.

نمای واقعی برد سنجش نور Adafruit BH1750 با کانکتورهای STEMMA QT و پایه‌های ورودی و خروجی
عکس واقعی برد Adafruit BH1750؛ اثر Bryan Siepert / Adafruit با مجوز CC BY-SA 3.0؛ تغییر اندازه و تبدیل به WebP بدون برش. تصویر ویرایش‌شده نیز تحت همین مجوز است.
خروجیروشنایی بر حسب lx
تغذیه تراشه خام2.4 تا 3.6V
رابطI2C تا 400kHz
آدرس0x23 یا 0x5C

BH1750 چیست و لوکس چه معنایی دارد؟

BH1750FVI محصول ROHM یک مبدل نور به داده دیجیتال 16 بیتی است. پاسخ طیفی آن تقریباً به چشم انسان نزدیک شده و اثر مادون‌قرمز در آن کم است. به همین دلیل به‌جای یک عدد خام ADC، روشنایی را بر حسب لوکس گزارش می‌کند.

لوکس شار نوری دریافت‌شده روی هر مترمربع است. این عدد برای کنترل نور اتاق، تنظیم خودکار نمایشگر، ثبت روشنایی گلخانه و تشخیص روز و شب مناسب است؛ اما رنگ نور، UV یا کیفیت طیف را اندازه نمی‌گیرد.

اعداد مهم دیتاشیت BH1750FVI

پارامترمقدار رسمینتیجه عملی
VCC تراشه خام2.4 تا 3.6Vحد مطلق 4.5V مجوز کار عادی با 5V نیست.
ولتاژ مرجع I2C1.65V تا VCCسطح منطق باید با طراحی واقعی برد هماهنگ باشد.
جریان در اندازه‌گیریتیپیک 120µA، بیشینه 190µAحالت Power Down برای پروژه باتری‌خور مفید است.
High Resolution1lx، تیپیک 120ms، بیشینه 180msبرای شروع و نور کم انتخاب پیشنهادی دیتاشیت است.
High Resolution Mode 20.5lx، تیپیک 120msتفکیک بیشتر با همان زمان تیپیک.
Low Resolution4lx، تیپیک 16ms، بیشینه 24msسریع‌تر است ولی تغییرات کوچک را کمتر نشان می‌دهد.
داده خام16 بیت؛ 0 تا 65535 شمارشعدد خام با لوکس یکسان نیست؛ ضریب تبدیل و حالت سنجش مهم‌اند.

آدرس I2C و حالت‌های اندازه‌گیری

وقتی ADDR پایین باشد آدرس هفت‌بیتی 0x23 است و با بالا بردن آن به VCC آدرس 0x5C می‌شود. این دو آدرس اجازه می‌دهند دو حسگر را روی یک باس قرار دهید. برد Adafruit برای حالت پیش‌فرض Pull-down و برای SCL و SDA مقاومت Pull-up ده کیلو اهم دارد.

در حالت Continuous نتیجه با فاصله حالت انتخابی به‌روزرسانی می‌شود. در One Time حسگر پس از تکمیل اندازه‌گیری خودکار به Power Down می‌رود. دیتاشیت برای High Resolution انتظار تا 180ms را لازم می‌داند؛ خواندن فوری ممکن است مقدار قبلی را برگرداند. کتابخانه hp_BH1750 این زمان‌بندی را با API غیرمسدودکننده مدیریت می‌کند.

سیم‌کشی BH1750 با ESP32 و Arduino Uno

برد Adafruit BH1750Generic ESP32Arduino Uno
VIN3V35V فقط برای برد Adafruit مستند
GNDGNDGND
SDAGPIO21A4 / SDA
SCLGPIO22A5 / SCL
ADDRپایین برای 0x23پایین برای 0x23

GPIO21 و GPIO22 پیش‌فرض رایج Generic ESP32 هستند، نه قانون همه بردها. در ESP32-S3، ESP32-C3 و طراحی سفارشی پایه‌های واقعی برد را جایگزین کنید. سیم‌ها را کوتاه نگه دارید و از Pull-upهای تکراری زیاد روی باس پرحسگر پرهیز کنید.

راه‌اندازی گام‌به‌گام در Arduino IDE

  1. در Library Manager عبارت hp BH1750 را جست‌وجو و کتابخانه Stefan Armborst را نصب کنید.
  2. برد را بدون تغذیه سیم‌کشی کنید و سطح ولتاژ ماژول را بررسی کنید.
  3. کد i2c-scanner.ino را اجرا کنید؛ باید 0x23 یا 0x5C دیده شود.
  4. کد اصلی را آپلود و Serial Monitor را روی 115200 baud باز کنید.
  5. برای تصمیم کنترلی چند نمونه بگیرید و از آستانه رفت و برگشت جدا استفاده کنید.

کد BH1750 برای ESP32 و Arduino

#include <Wire.h>
#include <hp_BH1750.h>

#if defined(ESP32)
constexpr int SDA_PIN = 21;
constexpr int SCL_PIN = 22;
#endif

hp_BH1750 lightSensor;
unsigned long measurementStarted = 0;

void startMeasurement() {
  if (!lightSensor.start(BH1750_QUALITY_HIGH, BH1750_MTREG_DEFAULT)) {
    Serial.println(F("I2C start failed; check wiring and reset."));
    while (true) delay(10);
  }
  measurementStarted = millis();
}

void setup() {
  Serial.begin(115200);
#if defined(ESP32)
  if (!Wire.setPins(SDA_PIN, SCL_PIN)) {
    Serial.println(F("Invalid I2C pins."));
    while (true) delay(10);
  }
#endif

  if (!lightSensor.begin(BH1750_TO_GROUND)) {
    Serial.println(F("BH1750 not found; check wiring and address."));
    while (true) delay(10);
  }

  Wire.setClock(100000);
  startMeasurement();
}

void loop() {
  if (lightSensor.hasValue()) {
    const float lux = lightSensor.getLux();
    // hp_BH1750 1.0.2 sets getTime() to 999 on an I2C read error.
    if (lightSensor.getTime() == 999) {
      Serial.println(F("I2C read failed; check wiring and reset."));
      while (true) delay(10);
    } else if (lightSensor.saturated()) {
      Serial.println(F("Full-scale reading: check bright light and I2C."));
    } else {
      Serial.print(F("Illuminance: "));
      Serial.print(lux, 1);
      Serial.println(F(" lx"));
    }
    startMeasurement();
  } else if (millis() - measurementStarted > 2000UL) {
    Serial.println(F("Measurement timeout; check wiring and reset."));
    while (true) delay(10);
  }
  delay(1);
}

تحلیل کد و انتخاب آدرس

پروژه: کنترل چراغ با هیسترزیس

یک رله یا MOSFET مناسب را با ایزولاسیون و حفاظت لازم به خروجی وصل کنید. چراغ را فقط زمانی روشن کنید که چند نمونه پیاپی زیر آستانه پایین باشند و فقط پس از عبور چند نمونه از آستانه بالاتر خاموش کنید. فاصله میان دو آستانه همان هیسترزیس است و از قطع‌و‌وصل سریع نزدیک مرز جلوگیری می‌کند.

پنجره اپتیکی و کالیبراسیون

اگر حسگر پشت شیشه، قاب مات یا پوشش محصول قرار بگیرد، بخشی از نور کم می‌شود. دیتاشیت با تغییر Measurement Time Register امکان جبران اثر پنجره را می‌دهد، اما ضریب را نمی‌توان حدس زد. یک لوکس‌متر مرجع، هندسه ثابت، منبع پایدار و چند سطح روشنایی لازم است.

جدول دقت دیتاشیت، در نور LED سفید 1000lx و شرایط مرجع VCC=DVI=3V و 25°C، نسبت «خروجی خام به لوکس واقعی» را 0.96 تا 1.44 با مقدار تیپیک 1.2 می‌دهد. پس تقسیم بر 1.2 در حالت High و MTreg=69، انحراف اسمی حدود ±20٪ را نشان می‌دهد؛ این عدد تضمین دقت یکسان در هر نور و محیط نیست. در همین تنظیم، سقف محاسباتی 65535/1.2 حدود 54613lx است و در High2 نصف می‌شود. کد مقدار تمام‌مقیاس را هشدار می‌دهد و به‌عنوان اندازه‌گیری معتبر چاپ نمی‌کند.

خطاهای رایج و عیب‌یابی

نشانهعلت محتملبررسی پیشنهادی
حسگر پیدا نمی‌شودآدرس یا پایه اشتباه، نبود زمین مشترکاسکنر را اجرا و 0x23/0x5C را بررسی کنید.
مقدار ثابت یا قدیمیخواندن پیش از پایان تبدیلاز hasValue() و شروع نمونه بعدی استفاده کنید.
پرش نزدیک آستانهسایه، نور مستقیم یا منطق تک‌آستانهمیانه چند نمونه و هیسترزیس اضافه کنید.
اختلاف با لوکس‌مترتلرانس حسگر، زاویه یا پوشش اپتیکیدر هندسه ثابت با مرجع معتبر کالیبره کنید.
ماژول روی Uno داغ یا خراب می‌شودبرد فاقد رگولاتور/Level Shifterشماتیک ماژول را بررسی و با 3.3V و منطق سازگار کار کنید.

پرسش‌های متداول BH1750

آدرس پیش‌فرض BH1750 چیست؟

با ADDR پایین، آدرس هفت‌بیتی 0x23 است؛ اتصال ADDR به VCC آن را به 0x5C تغییر می‌دهد.

آیا می‌توان BH1750 خام را به 5V وصل کرد؟

خیر. VCC کاری تراشه خام 2.4 تا 3.6 ولت است. فقط برد آماده‌ای که صریحاً رگولاتور و Level Shifter دارد ممکن است 5V را بپذیرد.

BH1750 رنگ نور یا UV را اندازه می‌گیرد؟

خیر. خروجی آن روشنایی بر حسب لوکس است و سنجش رنگ یا UV نیازمند حسگر دیگری است.

چرا مقدار بلافاصله بعد از شروع تغییر نمی‌کند؟

تبدیل High Resolution می‌تواند تا 180 میلی‌ثانیه طول بکشد. خواندن غیرمسدودکننده پس از آماده‌شدن داده از مقدار قبلی جلوگیری می‌کند.

GPIO21 و GPIO22 برای همه ESP32ها درست است؟

خیر. این‌ها پیش‌فرض رایج Generic ESP32 هستند؛ پایه‌های برد واقعی خود، به‌ویژه S3 و C3، را بررسی کنید.

منابع و مسیر ادامه یادگیری

  1. دیتاشیت ROHM BH1750FVI، نسخه Rev.D، نوامبر 2011، صفحات 1 و 2 برای تغذیه و مشخصات، صفحات 5 و 7 برای حالت‌ها و تبدیل داده؛ نسخه سازنده میزبانی‌شده در Mouser.
  2. راهنمای رسمی پایه‌های برد Adafruit BH1750 برای VIN، Level Shifter و آدرس.
  3. راهنمای رسمی Arduino برای BH1750 و نصب کتابخانه.
  4. کد و مثال‌های کتابخانه hp_BH1750 نسخه 1.0.2، نوشته Stefan Armborst با مجوز MIT.
  5. مستند رسمی I2C در Arduino-ESP32 برای پایه‌ها و API.

جمع‌بندی و آزمون روی میز کار

برای شروع، برد مستند را با ولتاژ سازگار وصل کنید، آدرس را با اسکنر پیدا کنید و اندازه‌گیری High با MTreg=69 را اجرا کنید. سپس تغییر نور و سایه، پوشش جلوی حسگر، نور شدید و قطع اتصال را روی سخت‌افزار خود آزمایش کنید. این نمونه‌ها برای Uno و Generic ESP32 کامپایل شده‌اند؛ کامپایل جای آزمون واقعی حسگر و کالیبراسیون محصول را نمی‌گیرد.