В этом проекте мы рассмотрим подключение ультрафиолетового (УФ, в англ. UV) датчика ML8511 к плате Arduino для измерения интенсивности ультрафиолетового света в мВт/см^2. Мы подключим УФ-датчик ML8511 к Arduino и ЖК-дисплею или OLED-дисплею. Ультрафиолетовое излучение происходит в диапазоне длин волн от 10 нм до 400 нм в электромагнитном спектре. Поэтому для получения эффективного выходного сигнала в соответствии с УФ-светом очень помогает датчик GY/ML8511 от компании lapis semiconductor. УФ-датчик ML8511 лучше обнаруживает свет 280 нм – 390 нм , эта длина волны классифицируется как часть спектра лучей UVB-обжигания и большая часть спектра лучей UVA-загара.
Датчик ML8511 очень прост в использовании. Он выдает аналоговое напряжение, линейно связанное с измеренной интенсивностью УФ-излучения (мВт/см2) . Если ваш микроконтроллер может выполнять преобразование аналогового сигнала в напряжение, то вы можете определить уровень УФ-излучения. Датчик имеет низкий ток питания 300 мкА и низкий ток в режиме ожидания 0,1 А. Он поставляется с небольшим и тонким корпусом для поверхностного монтажа (4,0 мм x 3,7 мм x 0,73 мм (0,16″ x 0,15″ x 0,03″), 12-контактный керамический QFN).
Если же вы хотите измерить интенсивность не ультрафиолетового, а окружающего света, то для этого вы можете использовать один из датчиков освещенности — TSL25911 или BH1750.
Необходимые компоненты
- Плата Arduino Nano (купить на AliExpress).
- Датчик УФ-излучения ML8511 (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- Потенциометр 10 кОм (купить на AliExpress).
- OLED дисплей с диагональю экрана 0.96 дюйма (купить на AliExpress).
- Макетная плата
- Соединительные провода.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
УФ-датчик ML8511
Обзор датчика
Датчик УФ ML8511 — это простой в использовании датчик ультрафиолетового света. Датчик УФ (ультрафиолетовый) MP8511 работает, выдавая аналоговый сигнал в зависимости от количества обнаруженного УФ-света. Он может быть очень полезен при создании устройств, которые предупреждают пользователя о солнечных ожогах или определяют УФ-индекс в зависимости от погодных условий.
Этот датчик наиболее эффективно обнаруживает свет в диапазоне длин волн 280-390 нм. Он классифицируется как часть спектра UVB (лучи ожогов) и большая часть спектра UVA (лучи загара). Он выдает аналоговое напряжение, которое линейно связано с измеренной интенсивностью УФ-излучения (мВт/см2) . Если ваш микроконтроллер может выполнять аналого-цифровое преобразование сигнала, то вы можете определить уровень УФ-излучения!
Блок-схема датчика
УФ-датчик ML8511 имеет фотодиод, чувствительный к UV-A (УФ-А) и UV-B (УФ-В). Он также имеет внутренний встроенный операционный усилитель, который преобразует фототок в выходное напряжение в зависимости от интенсивности УФ-излучения.
Выход датчика всегда в форме аналогового напряжения. Через данный выход легко взаимодействовать с внешними микроконтроллерами и АЦП.
Характеристики УФ
Характеристики построены между выходным напряжением датчика и интенсивностью УФ-излучения (мВт/см²) при постоянном питании VDD. Кривые разных цветов отображают работу датчика в разных диапазонах температур
Схема проекта
Ниже приведена принципиальная схема сопряжения УФ-датчика ML8511 с Arduino и ЖК-дисплеем. Контакты ЖК-дисплея RS, EN, D4, D5, D6, D7 подключены к контактам Arduino 12, 11, 5, 4, 3, 2. На ЖК-дисплей подается напряжение 5 В. Он имеет потенциометр 10 кОм, подключенный к контакту 3 ЖК-дисплея для регулировки контрастности.
Датчик УФ имеет 5 контактов Vin, 3V3, GND, OUT, EN. Некоторые модули не имеют контакта Vin, который также не используется. Контакты EN и 3V3 подключены к контакту 3,3 В Arduino. Тот же контакт 3V3 подключен к аналоговому контакту A1, который используется в качестве опорного напряжения. Контакт out подключен к контакту A0 Arduino, а GND к GND.
Это соединение для ML8511 достаточно сложное. Аналого-цифровые преобразования полностью зависят от значения VCC. Мы предполагаем, что это 5,0 В, но если плата питается от USB, это может быть как 5,25 В, так и 4,75 В. Из-за этого неизвестного окна это делает АЦП (аналого-цифровой преобразователь) на плате Arduino немного неточным. Чтобы исправить это, мы используем очень точный встроенный опорный сигнал 3,3 В (с точностью в пределах 1%). Поэтому, выполняя аналого —цифровое преобразование на выводе 3,3 В (подключив его к A1), а затем сравнивая это показание с показанием с датчика, мы можем экстраполировать реалистичное показание, независимо от того, какой VIN (при условии, что он выше 3,4 В).
Если вам больше нравится работать с OLED, нежели с ЖК дисплеем, то можете использовать аналогичную схему с OLED дисплеем.
В качестве OLED-дисплея здесь используется 0,96″ 128×64 I2C OLED-дисплей. Поэтому он подключен к контактам I2C Arduino. Контакт SDA подключен к A4 Arduino, а контакт SCL — к A5.
Исходный код программы
С использованием ЖК дисплея
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 59 60 61 62 63 64 65 66 67 68 |
#include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Hardware pin definitions int UVOUT = A0; //Output from the sensor int REF_3V3 = A1; //3.3V power on the Arduino board void setup() { Serial.begin(9600); lcd.begin(16, 2); pinMode(UVOUT, INPUT); pinMode(REF_3V3, INPUT); Serial.println("ML8511 example"); } void loop() { int uvLevel = averageAnalogRead(UVOUT); int refLevel = averageAnalogRead(REF_3V3); //Use the 3.3V power pin as a reference to get a very accurate output value from sensor float outputVoltage = 3.3 / refLevel * uvLevel; float uvIntensity = mapfloat(outputVoltage, 0.99, 2.8, 0.0, 15.0); //Convert the voltage to a UV intensity level Serial.print("output: "); Serial.print(refLevel); Serial.print("ML8511 output: "); Serial.print(uvLevel); Serial.print(" / ML8511 voltage: "); Serial.print(outputVoltage); Serial.print(" / UV Intensity (mW/cm^2): "); Serial.print(uvIntensity); lcd.clear(); lcd.print("UV Ray Intensity"); lcd.setCursor(0, 1); lcd.print(uvIntensity); lcd.print(" mW/cm^2"); Serial.println(); delay(200); } //Takes an average of readings on a given pin //Returns the average int averageAnalogRead(int pinToRead) { byte numberOfReadings = 8; unsigned int runningValue = 0; for(int x = 0 ; x < numberOfReadings ; x++) runningValue += analogRead(pinToRead); runningValue /= numberOfReadings; return(runningValue); } float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
С использованием OLED дисплея
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
#include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> int UVOUT = A0; //Output from the sensor int REF_3V3 = A1; //3.3V power on the Arduino board #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); void setup() { Serial.begin(9600); pinMode(UVOUT, INPUT); pinMode(REF_3V3, INPUT); display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64) display.clearDisplay(); Serial.println("ML8511 example"); } void loop() { int uvLevel = averageAnalogRead(UVOUT); int refLevel = averageAnalogRead(REF_3V3); //Use the 3.3V power pin as a reference to get a very accurate output value from sensor float outputVoltage = 3.3 / refLevel * uvLevel; float uvIntensity = mapfloat(outputVoltage, 0.99, 2.8, 0.0, 15.0); //Convert the voltage to a UV intensity level Serial.print("output: "); Serial.print(refLevel); Serial.print("ML8511 output: "); Serial.print(uvLevel); Serial.print(" / ML8511 voltage: "); Serial.print(outputVoltage); Serial.print(" / UV Intensity (mW/cm^2): "); Serial.print(uvIntensity); Serial.println(); display.setCursor(20,0); //oled display display.setTextSize(1); display.setTextColor(WHITE); display.println("UV Ray Intensity"); display.setCursor(20,20); //oled display display.setTextSize(3); display.setTextColor(WHITE); display.println(uvIntensity); display.setCursor(20,45); //oled display display.setTextSize(2); display.setTextColor(WHITE); display.println("mW/cm^2"); display.display(); delay(300); display.clearDisplay(); } //Takes an average of readings on a given pin //Returns the average int averageAnalogRead(int pinToRead) { byte numberOfReadings = 8; unsigned int runningValue = 0; for(int x = 0 ; x < numberOfReadings ; x++) runningValue += analogRead(pinToRead); runningValue /= numberOfReadings; return(runningValue); } float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
Объяснение работы кода
1 |
UV_Voltage / uvLevel = 3.3 / refLevel |
uvLevel — это то, что мы считываем с вывода OUT. refLevel — это то, что мы считываем с вывода 3,3 В. Решая это уравнение для UV_Voltage, мы можем получить точное показание.
1 2 3 4 |
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
Сопоставление UV_Voltage с интенсивностью выполняется прямолинейно. Никакой УФ-свет не начинается с 1 В с максимумом 15 мВт/см2 при 2,8 В. В Arduino есть встроенная функция map(), но map() не работает для float, поэтому мы запрограммировали для этого собственную функцию mapFloat() .
Следующая строка преобразует напряжение, считываемое с датчика, в интенсивность мВт/см2.
1 |
float uvIntensity = mapfloat(outputVoltage, 0.99, 2.8, 0.0, 15.0); |