Menggunakan Sensor Cahaya BH1750

BH1750 merupakan sensor digital yang dapat mengukur intensitas cahaya. Berbeda dengan light-dependent resistor atau phototransistor, BH1750 sudah dapat mengeluarkan nilai intensitas cahaya dalam satuan lux (lx). Sehingga, tidak perlu ada konversi dari satuan elektrik ke satuan intensitas cahaya dalam kode program.

Sensor jenis ini biasanya digunakan pada perangkat ponsel, televisi LCD, dan semacamnya untuk menyesuaikan tingkat kecerahan layar terhadap intensitas cahaya lingkungan perangkat. Sensor ini dapat mengukur intensitasi cahaya dengan rentang 1 sampai 65535 lx.

Yang cukup menarik adalah, sensor ini mudah didapatkan dari berbagai macam marketplace populer di Indonesia dengan harga yang relatif murah (Rp.15,000 - Rp.20,000). Dengan harga tersebut, sensor sudah terpasang pada sebuah PCB dengan berbagai komponen pendukung dan 5 buah pin header male untuk daya, komunikasi, dan pemilihan alamat perangkat.

Menghubungkan Sensor ke Microcontroller

Dalam kesempatan ini, penulis akan menghubungkan sensor ke perangkat ESP32 dengan menggunakan kabel jumper. Kemudian, penulis akan menggunakan bahasa pemrograman C++ dengan framework Arduino.

Sebelum memulai, pastikan kondisi-kondisi yang dijabarkan dalam bagian Absolute Maximum Ratings dan Operating Conditions pada dokumen datasheet sensor terpenuhi. Hal ini perlu diperhatikan agar sensor dapat berfungsi dengan seharusnya. Yang perlu dicatat adalah nilai maksimum tegangan Vcc yang diperbolehkan. Meskipun 3.6 Volt adalah nilai maksimum tegangan Vcc yang diperbolehkan, namun jika sensor digunakan dalam bentuk modul siap pakai, maka tegangan 5 Volt perangkat Arduino pun harusnya tidak menjadi masalah. Namun, penulis akan tetap menggunakan perangkat ESP32 dengan tegangan 3.3 Volt untuk berjaga-jaga.

Sensor menggunakan protokol komunikasi inter-integrated circuit atau yang biasa disingkat I2C atau I^2^C. Hubungkan pin SDA pada mikrokontroler ke pin SDA pada sensor, dan pin SCL pada mikrokontroler ke pin SCL pada sensor. Lakukan hal yang sama untuk pin Vcc dan GND.

Berinteraksi dengan Sensor

Berkomunikasi dengan Sensor yang menggunakan protokol I^2^C dapat dilakukan dengan mudah jika menggunakan framework Arduino. Semua fungsi-fungsi yang dibutuhkan sudah dapat digunakan dengan menggunakan objek Wire dari library Wire bawaan Arduino.

Untuk membaca pengukuran intesitasi cahaya dari sensor, kita harus mengirimkan instruksi ke sensor dengan menggunakan protokol I^2^C. Setelah instruksi diberikan, kita diharuskan menunggu selama durasi yang telah disebutkan pada dokumen datasheet sensor. Setelah waktu tunggu berakhir, kita dapat membaca sebanyak 2 byte dari sensor yang kemudian dikonversi menjadi nilai lx.

Sebagai contoh, kita akan melakukan sekali pengukuran dengan mode high resolution. Instuksi yang harus dikirimkan adalah: 00100000 dalam bilangan biner. Kemudian, waktu yang diperlukan oleh sensor untuk melakukan pengukuran adalah 120 millisecond. Berikut adalah contoh kode program nya:

#include <Arduino.h>
#include <Wire.h>

static constexpr auto SENSOR_ADDRES = 0x23;
static constexpr auto ONETIME_HIRES = 0b00100000;

void setup()
{
  Serial.begin(115200);

  Wire.begin();
}

void loop()
{
  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(ONETIME_HIRES);
  auto result = Wire.endTransmission();

  if (result != 0)
  {
    Serial.println("Failed communicating with sensor!");
    return;
  }

  delay(120);

  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.requestFrom(SENSOR_ADDRESS, 2);

  uint8_t msb = Wire.read();
  uint8_t lsb = Wire.read();
  uint16_t raw = msb << 8 | lsb;
  float lx = (float)raw / 1.2f;

  Wire.endTransmission();

  Serial.print("Lux: ");
  Serial.println(lx);

  delay(1000);
}

Penjelasan Kode Program

Kode program dimulai dengan mencantumkan header file Arduino.h dan Wire.h

#include <Arduino.h>
#include <Wire.h>

Kemudian, definisikan alamat sensor BH1750 dan perintah atau instruksi yang digunakan untuk mengukur intensitas cahaya.

static constexpr auto SENSOR_ADDRES = 0x23;
static constexpr auto ONETIME_HIRES = 0b00100000;

Dua baris tersebut dapat digantikan dengan

#define SENSOR_ADDRES 0x23
#define ONETIME_HIRES 0b00100000;

Namun, penulis lebih suka menggunakan static constexpr yang diikuti dengan auto daripada menggunakan directive #define. Hal ini mungkin akan dibahas di masa yang akan datang.

Kemudian, pastikan kita dapat berkomunikasi dengan mikrokontroler dengan menggunakan protokol UART dengan kecepatan 115200 bit per detik. Selanjutnya, perintahkan mikrokontroler untuk menggunakan pin SDA dan pin SCL yang sudah didefinisikan oleh pembuat board Arduino atau ESP32 dengan memanggil fungsi begin pada objek Wire. Semua ini dilakukan satu kali saja ketika fungsi setup dipanggil oleh mikrokontroler.

void setup()
{
  Serial.begin(115200);

  Wire.begin();
}

Pada fungsi loop, lakukan sekali pengukuran dengan mode high resolution. Hal ini dilakukan dengan mengirimkan instruksi ONETIME_HIRES dengan menggunakan objek Wire.

Wire.beginTransmission(SENSOR_ADDRESS);
Wire.write(ONETIME_HIRES);
auto result = Wire.endTransmission();

Hal-hal yang terjadi ketika tiga baris kode tersebut dieksekusi oleh mikrokontroler:

  • Mikrokontroler memulai komunikasi I^2^C dengan sensor pada alamat SENSOR_ADDRESS atau 0x23.
  • Mikrokontroler mengirimkan instruksi ONETIME_HIRES.
  • Mikrokontroler menyudahi komunikasi I^2^C, hasil komunikasi disimpan pada variabel result.

Kemudian, cek apakah komunikasi dapat terjalin atau tidak. Jika tidak, kirimkan pesan error melalui serial dan keluar dari fungsi loop.

if (result != 0)
{
  Serial.println("Failed communicating with sensor!");
  return;
}

Jika berhasil, tunggu setidaknya 120 millisecond untuk sensor untuk melakukan pengukuran.

delay(120);

Kemudian, mulai komunikasi I^2^C kembali dengan sensor untuk mendapatkan hasil pengukuran.

Wire.beginTransmission(SENSOR_ADDRESS);
Wire.requestFrom(SENSOR_ADDRESS, 2);

Dua baris kode tersebut digunakan untuk memulai komunikasi I^2^C ke sensor dan meminta sensor untuk mengembalikan data sebanyak 2 byte.

uint8_t msb = Wire.read();
uint8_t lsb = Wire.read();
uint16_t raw = msb << 8 | lsb;

Hasil pembacaan dari sensor merupakan nilai lux dengan dalam bentuk bilangan bulat 16 bit. Namun, I^2^C hanya memungkinkan sensor untuk mengembalikan nilai dalam bentuk bilangan bulat 8 bit. Sehingga, 2 bilangan 8 bit yang didapatkan dengan memanggil fungsi read() dari objek Wire akan dikonversi menjadi satu bilangan 16 bit. Most significant byte (MSB) dari bilangan 16 bit tersebut akan dikirimkan pertama kali, dan least significant byte (LSB) dari bilangan 16 bit tersebut akan dikirimkan terakhir. Maka dari itu, kita geser nilai MSB ke kiri sebanyak 8 bit, kemudian kita tambahkan nilai LSB.

Kemudian, konversi nilai lx dalam bentu 16 bit menjadi nilai lx sesungguhnya dengan membagi bilangan tersebut dengan bilangan 1.2.

float lx = (float)raw / 1.2f;

Selanjutnya, akhiri komunikasi I^2^C dengan sensor.

Wire.endTransmission();

Kirimkan hasil pengukuran melalui serial agar dapat dilihat melalui komputer yang terhubung dengan mikrokontroler melalui kabel.

Serial.print("Lux: ");
Serial.println(lx);

Tunggu selama satu detik sebelum memulai pengukuran kembali.

delay(1000);

Kesimpulan

Sensor BH1750 merupakan sensor intensitas cahaya lingkungan yang dapat memberikan hasil pengukuran dalam satuan lx secara digital dengan menggunakan protokol I^2^C. Sensor tersebut juga menggunakan instruksi dan pola komunikasi yang cukup sederhana sehingga dapat digunakan dengan mudah tanpa menggunakan pustaka kode khusus selain dari bawaan framework Arduino.

Referensi