Практически все современные смартфоны обладают функцией автоматического изменения яркости экрана в зависимости от условий освещенности окружающей среды. Аналогичная функция есть и во многих современных мониторах и телевизорах. Поэтому в данной статье мы рассмотрим подключение датчика освещенности BH1750 к Arduino. Значение освещенности мы будем показывать на экране ЖК дисплея 16x2.
Самым распространенным датчиком измерения освещенности у любителей платформы Arduino является фоторезистор – это аналоговый датчик, меняющий свое сопротивление в зависимости от интенсивности света (на нашем сайте вы можете посмотреть все проекты на основе фоторезисторов), однако точность его невысока и значение освещенности он выдает не в люксах. В отличие от него датчик BH1750 выдает значение освещенности как раз в люксах.
Люкс – (от лат. lux – свет; русское обозначение: лк, международное обозначение: lx) – единица измерения освещённости в Международной системе единиц (СИ). Люкс равен освещённости поверхности площадью 1 м² при световом потоке падающего на неё излучения, равном 1 лм (люмен). Соответственно, справедливо равенство: 1 лк = 1 лм/м2. С другой стороны, люкс равен освещённости поверхности сферы радиусом 1 м, создаваемой точечным источником света, находящимся в её центре, сила света которого составляет 1 кд (Кандела). Таким образом, с основными единицами СИ люкс связан соотношением: 1 лк = 1 кд/м2 (википедия).
Также на нашем сайте вы можете посмотреть подключение к плате Arduino таких датчиков освещенности как TEMT6000 и TSL25911.
Принципы работы датчика освещенности BH1750
BH1750 представляет собой цифровой датчик освещенности/люксметр, который можно использовать для автоматической регулировки яркости экранов смартфонов, мониторов, телевизоров и т.п. Также его можно применить для регулировки яркости свечения фар автомобиля. Внешний вид датчика BH1750 показан на следующем рисунке.
Датчик BH1750 работает по протоколу I2C, поэтому его легко подключить практически ко всем современным микроконтроллерам. Распиновка (назначение контактов) датчика освещенности BH1750 приведена в следующей таблице.
Контакт | Описание |
VCC | питание |
GND | земля (общий провод) |
SCL | линия тактирования (Serial CLock) |
SDA | линия данных (Serial Data) |
ADDR | выбор адреса |
В нашем проекте мы для подключения датчика по интерфейсу I2C будем использовать его контакты SDI и SDA.
Датчик BH1750 способен работать при величине питающего напряжения от 2.4V до 3.6V (обычно используется напряжение 3.0V) и во время своей работы потребляет ток 0.12mA. Датчик отличается широким диапазоном и высоким разрешением (65536 градаций освещенности - от 1 до 65536)
Необходимые компоненты
- Плата Arduino Uno (купить на AliExpress).
- Датчик освещенности BH1750 (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
Схема проекта
Схема подключения датчика освещенности BH1750 к плате Arduino представлена на следующем рисунке.
Контакты SDA и SCL (интерфейс I2C) датчика BH1750 подключены к контактам A4 и A5 платы Arduino соответственно (они являются контактами интерфейса I2C в Arduino). Датчик запитывается от контакта 3.3V платы Arduino. Контакты данных ЖК дисплея D4-D7 подключены к контактам D2-D5 платы Arduino, а контакты RS и EN подключены к контактам D6 и D7 платы Arduino. Контакт V0 ЖК дисплея подключен к потенциометру, с помощью которого будет регулироваться яркость ЖК дисплея.
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Объяснение программы для Arduino
Программа для взаимодействия платы Arduino с датчиком освещенности BH1750 достаточно проста. В этом проекте мы для взаимодействия с датчиком BH1750 использовали специальную библиотеку, но можно было бы обойтись и без нее. Полный текст программы приведен в конце статьи, здесь же мы кратко рассмотрим ее основные фрагменты.
Первым делом в программе мы подключим библиотеки для работы с протоколом I2C и ЖК дисплеем.
1 2 |
#include<Wire.h> #include<LiquidCrystal.h> |
В функции setup мы инициализируем датчик BH1750 и ЖК дисплей, а также напечатаем приветственное сообщение на экране ЖК дисплея.
1 2 3 4 5 6 7 8 9 |
void setup() { Wire.begin(); lcd.begin(16,2); lcd.print(" BH1750 Light "); lcd.setCursor(0,1); lcd.print("Intensity Sensor"); delay(2000); } |
Также мы запрограммируем две функции – BH1750_Read (для считывания значения освещенности) и BH1750_Init (для записи значения освещенности).
Функция Wire.beginTransmission() используется для начала передачи по протоколу I2C, а функция Wire.requestFrom(address, 2) используется для считывания значения регистров (аргумент 2 в этой функции – число регистров).
Функция Wire.endTransmission() используется для завершения процесса передачи по протоколу I2C, а функция Wire.write() используется для перехода к необходимому регистру, аргументом этой функции является адрес регистра.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
int BH1750_Read(int address) { int i=0; Wire.beginTransmission(address); Wire.requestFrom(address, 2); while(Wire.available()) { buff[i] = Wire.read(); i++; } Wire.endTransmission(); return i; } void BH1750_Init(int address) { Wire.beginTransmission(address); Wire.write(0x10); Wire.endTransmission(); } |
В функции loop мы в режиме реального времени выводим значение освещенности (в люксах) на экран ЖК дисплея. Сначала мы сравниваем значение, считанное с датчика BH1750, со значением 2 и если оно равно 2, то мы печатаем значение освещенности на экране ЖК дисплея. Мы сравниваем значение с датчика BH1750 со значением 2 потому что функция BH1750_Read возвращает количество считанных регистров с датчика, а мы считываем как раз 2 регистра. Поэтому когда мы считаем 2 регистра с датчика, мы выводим значение освещенности на экран ЖК дисплея.
Далее мы получаем значения обоих регистров и делим получившееся значение на 1.2 (здесь значение 1.2 определяет точность вычислений).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void loop() { int i; uint16_t value=0; BH1750_Init(BH1750address); delay(200); if(2==BH1750_Read(BH1750address)) { value=((buff[0]<<8)|buff[1])/1.2; lcd.clear(); lcd.print("Intensity in LUX"); lcd.setCursor(6,1); lcd.print(value); } delay(150); } |
Исходный код программы (скетча)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include<Wire.h> #include<LiquidCrystal.h> int BH1750address = 0x23; byte buff[2]; LiquidCrystal lcd (7,6,5,4,3,2); //RS, E, D4, D5, D6, D7 void setup() { Wire.begin(); //Serial.begin(9600); lcd.begin(16,2); lcd.print(" BH1750 Light "); lcd.setCursor(0,1); lcd.print("Intensity Sensor"); delay(2000); } void loop() { int i; uint16_t value=0; BH1750_Init(BH1750address); delay(200); if(2==BH1750_Read(BH1750address)) { value=((buff[0]<<8)|buff[1])/1.2; lcd.clear(); lcd.print("Intensity in LUX"); lcd.setCursor(6,1); lcd.print(value); //Serial.print(val); //Serial.println("[lux]"); } delay(150); } int BH1750_Read(int address) { int i=0; Wire.beginTransmission(address); Wire.requestFrom(address, 2); while(Wire.available()) { buff[i] = Wire.read(); i++; } Wire.endTransmission(); return i; } void BH1750_Init(int address) { Wire.beginTransmission(address); Wire.write(0x10); Wire.endTransmission(); } |