Мощным толчком для реализации проекта послужил случай. В один из солнечных дней, без единого облачка, я провёл около 5 часов в солнцезащитных очках под открытым небом. Вечером ощутил сухость в глазах. Взглянул в зеркало и увидел воспалённые покрасневшие глаза. Следующие три дня были очень болезненными для глаз. Стало понимание необходимости теста на защиту от ультрафиолетового излучения приобретённых солнцезащитных очков.
Итак, хочу поделиться опытом создания анализатора ультрафиолетового спектра диапазона UV-A и UV-B, на основе Arduino.
У меня стояла задача изготовить прибор для измерения и анализа степени защиты от ультрафиолетового излучения фильтров для объектива а также солнцезащитных очков и очков корректирующих зрение.
Для реализации проекта я использовал:
1. Arduino Pro mini, на питание 3.3V и частотой 8MHz;
2. Модуль на основе микросхемы ML8511;
3. Повышающий напряжение DC-DC преобразователь MT3608 (приобретался на Алиэкспресс);
4. OLED-дисплей 0.96,128х64 на SSD1306;
5. Корпус от беспроводной телефонной трубки.
Из особенностей при создании прибора отмечу следующие моменты на которые следует обратить внимание. Датчик УФ излучения при использовании, удобнее расположить в том же направлении (ориентации) что и дисплей. Не на торце прибора и под углом. Датчик следует удалить от дисплея на расстояние не менее 7 см, иначе просто не удобно считывать показания в момент воздействия на датчик фонариком с ультрафиолетовым спектром.
Корпус старой трубки от домашнего телефона ещё послужит. В нём есть самое главное, это место для установки двух аккумуляторов на 1,2В и прозрачное стекло защищающее дисплей от повреждения. Из платы пришлось выпаять все до единого элемента, дабы не мешали размещению на двухсторонний скотч модулей.
Используя два аккумулятора по 1.2В в сумме получается 2.4 в что недостаточно для питания схемы, поэтому применил преобразователь повышающий напряжение до 5В с высоким КПД. Модуль MT3608 начинает работать от 2 вольт. Подстроечным резистором на плате модуля выставляем напряжение на выходе модуля (контакты OUT) в 5 Вольт.
В качестве датчика ультрафиолетового излучения выбран модуль на основе микросхемы ML8511 производства Lapis Semiconductor.
Модуль на основе микросхемы ML8511, есть в продаже на торговой площадке Wildberries и Алиэкспресс. Он носит название GY-ML8511 GYML8511 или просто ML8511.
https://www.wildberries.ru/catalog/57614036/detail.aspx
В качестве микроконтроллера использован модуль Arduino Pro mini на ATmega328P-AU, на питание 3.3V и частотой 8MHz. Приобретался на Алиэкспресс.
В данном модуле Arduino Pro mini пришлось заменить микросхему стабилизатора напряжения в корпусе SOT-23 по причине выхода её из работы (сгорела) при втором включении. Производители из Китая в стремлении сделать максимально низкую цену зачастую отступают от оригинальных схем и выбирают менее подходящие по надёжности элементы. В оригинальной схеме установлен стабилизатор MIC5205-3.3, в моём же случае была установлена микросхема с маркировкой LBMK на корпусе.
Я же выбрал и приобрёл в магазине Промэлектроника стабилизатор LD2985BM33R, с низким падением напряжения положительной полярности, 3.3 В, 0.15А производителя ST Microelectronics по цене 39,78 рублей. Этот стабилизатор имеет встроенную защиту от перегрева и перегрузки по току, выдерживает напряжение на входе аж до 16 вольт, низкое падение напряжение. Полный аналог MIC5205-3.3. То что надо! И подешевле. Стабилизатор напряжения был заменён. Забегая вперёд скажу что измеренный общий потребляемый ток прибора от батареек составил в пике 40мА. Номинальный же ток стабилизатора LD2985BM33R составляет 150мА. Отличный результат, позволяющий запитать и сам дисплей от встроенного стабилизатора напряжения в модуле Arduino Pro mini.
OLED-дисплей 0.96,128х64 на SSD1306 приобретался на Алиэкспресс. Модуль удобен тем что имеет всего 4 контакта для подключения.
Для заливки программы в модуль Arduino Pro mini понадобиться программа Arduino IDE и программатор USB/UART CP2102 xpress.ru/item/32796844759.html?click_id=9mTZ21iCEMZsfzo&af=2926_Y6Ljx9&cn=2urus8goes4kj6hllwdqzhysiqtt0f5t&cv=2&cv_source=default&dp=2urus8goes4kj6hllwdqzhysiqtt0f5t&utm_campaign=2926_Y6Ljx9&utm_content=2&utm_medium=cpa&utm_source=aerkol&aff_fcid=625da8bb7d444a279951a6b03a24df3a-1707267989330-03267-_DEghsXJ&aff_fsk=_DEghsXJ&aff_platform=api-new-link-generate&sk=_DEghsXJ&aff_trace_key=625da8bb7d444a279951a6b03a24df3a-1707267989330-03267-_DEghsXJ&terminal_id=a781f0f7b6694fe49ca8ddce577a41bf&sku_id=10000000093681508USB/UART CP2102 https://aliexpress.ru/item/32796844759.html?click_id=9mTZ21iCEMZsfzo&af=2926_Y6Ljx9&cn=2urus8goes4kj6hllwdqzhysiqtt0f5t&cv=2&cv_source=default&dp=2urus8goes4kj6hllwdqzhysiqtt0f5t&utm_campaign=2926_Y6Ljx9&utm_content=2&utm_medium=cpa&utm_source=aerkol&aff_fcid=625da8bb7d444a279951a6b03a24df3a-1707267989330-03267-_DEghsXJ&aff_fsk=_DEghsXJ&aff_platform=api-new-link-generate&sk=_DEghsXJ&aff_trace_key=625da8bb7d444a279951a6b03a24df3a-1707267989330-03267-_DEghsXJ&terminal_id=a781f0f7b6694fe49ca8ddce577a41bf&sku_id=10000000093681508https://aliexpress.ru/item/32796844759.html?click_id=9mTZ21iCEMZsfzo&af=2926_Y6Ljx9&cn=2urus8goes4kj6hllwdqzhysiqtt0f5t&cv=2&cv_source=default&dp=2urus8goes4kj6hllwdqzhysiqtt0f5t&utm_campaign=2926_Y6Ljx9&utm_content=2&utm_medium=cpa&utm_source=aerkol&aff_fcid=625da8bb7d444a279951a6b03a24df3a-1707267989330-03267-_DEghsXJ&aff_fsk=_DEghsXJ&aff_platform=api-new-link-generate&sk=_DEghsXJ&aff_trace_key=625da8bb7d444a279951a6b03a24df3a-1707267989330-03267-_DEghsXJ&terminal_id=a781f0f7b6694fe49ca8ddce577a41bf&sku_id=10000000093681508
В Arduino IDE потребуется подключить библиотеки для работы с оборудованием: Arduino.h; U8g2lib.h; Wire.h
В модуль Arduino Pro mini заливается скетч с следующим содержимым:
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
#define FIRST_ROW_Y 16
#define FIRST_ROW_X 16
#define BOX_H 38
//Hardware pin definitions
const int UVOUT = A0; //Output from the sensor
const int REF_3V3 = A1; //3.3V power on the Arduino board
const int VBATT = A2; //Battery voltage
float maxUV = 0; //Max UV index read
void setup()
{
pinMode(UVOUT, INPUT);
pinMode(REF_3V3, INPUT);
pinMode(VBATT, INPUT);
u8g2.begin();
}
void loop()
{
u8g2.firstPage();
do {
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.315 / refLevel * uvLevel; //уровень опорного 3.3В используется для точного показания датчика UF. Измерьте вольтметром.
float uvIntensity = mapfloat(outputVoltage, 1.002, 2.8, 0.0, 15.0); //Convert the voltage to a UV intensity level причём в (outputVoltage, 1.002, 2.8, 0.0, 15.0) значение 1,002 измеренное значение на выходе датчика UF равно начолу отсчёта, 1,002В принимается за значение 0; 2,8 - это величина напряжения по даташит соответствует 15.0 mW/cm^2
readBattery();
if (maxUV < uvIntensity) {
maxUV = uvIntensity;
}
//u8g2.drawFrame(0,FIRST_ROW_Y+1,128,BOX_H); //тонкая рамка вокруг показаний
u8g2.setFont(u8g2_font_logisoso22_tf); // размер шрифта u8g2_font_logisosoХХ
//Instant UV
u8g2.setCursor(0,45); //строка мгновенного показания UV
u8g2.print(uvIntensity);
//UV Max
u8g2.setCursor(77,22); //строка максимального показания UV
u8g2.print(maxUV);
u8g2.setFont(u8g2_font_chikita_tr); // был шрифт высотой 4 - u8g2_font_u8glib_4_tf Этот высотой 5
// u8g2.setCursor(7,58); u8g2.print(F("0-11 Level"));
u8g2.setCursor(83,32); u8g2.print(F("MAXIMUM"));
u8g2.setCursor(84,42); u8g2.print(F("mW/cm^2"));
showUVCategory();
//u8g2.setCursor(80,64); u8g2.print(F("Garipov.V.A")); // надпись любая может быть в кавычках - u8g2.print(F(" ")
} while ( u8g2.nextPage() );
delay(200);
}
// Reads maxUV and prints the UV category
void showUVCategory() {
char strCat[12];
byte categ = (byte)(maxUV+0.5); //round up
if ((categ >= 0) && (categ < 3)) {
strcpy(strCat, "LOW");
} else if ((categ >= 3) && (categ < 6)) {
strcpy(strCat, "MODERATE");
} else if ((categ >= 6) && (categ < 8)) {
strcpy(strCat, "HIGH !");
} else if ((categ >= 8) && (categ < 10)) {
strcpy(strCat, "VERY HIGH !");
} else if (categ >= 11) {
strcpy(strCat, "EXTREME !");
}
u8g2.setFont(u8g2_font_ncenB12_tr); // другой шрифт для строки уровня УФ
u8g2.setCursor(8,64); //строка отображения уровня УФ (LOW,MODERATE, HIGH, VERY HIGH!,EXTREME!)
u8g2.print(strCat);
}
//Takes an average of readings on a given pin
//Returns the average
int averageAnalogRead(int pinToRead)
{
byte numberOfReadings = 16;
unsigned int runningValue = 0;
for(int x = 0 ; x < numberOfReadings ; x++)
runningValue += analogRead(pinToRead);
runningValue /= numberOfReadings;
return(runningValue);
}
//The Arduino Map function but for floats
//From: http://forum.arduino.cc/index.php?topic=3922.0
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;
}
void readBattery() {
long battery = readBattVcc();
long VccMin = 2300; //Battery minimum voltage read on Vcc
byte batteryBar; //Battery progress bar
int barStep = 140; //step for battery progress bar (235)
batteryBar = (battery - VccMin)/barStep;
//battery icon
u8g2.setFont(u8g2_font_open_iconic_embedded_2x_t);
u8g2.drawGlyph(0, FIRST_ROW_Y, 73 );
// battery status cursor
//u8g2.setFont(u8g2_font_open_iconic_play_1x_t);
//for (byte i=1; i<=batteryBar; i++) {
// u8g2.drawGlyph( 128-9*i,FIRST_ROW_Y-4,75); // строка отображения кубиками напряжения батареи (убрал)
// }
// battery voltage
u8g2.setFont(u8g2_font_freedoomr10_tu);
u8g2.setCursor(25, FIRST_ROW_Y);
u8g2.print(float(battery)/1000, 2); // u8g2.print(float(battery)/1000, 2) 2 - число символов после запятой (было 3)
}
long readBattVcc()
{
int sum=0;
int sample_count=0;
long voltage= 0;
#define NUM_SAMPLES 10
// take a number of analog samples and add them up
while (sample_count < NUM_SAMPLES) {
sum += analogRead(VBATT);
sample_count++;
delay(2);
}
// calculate the voltage
// use 5000 for a 5.0V ADC reference voltage
// 5020V is the calibrated reference voltage (in millivolts) for my project
voltage = ((long)sum / (long)NUM_SAMPLES * 3315) / 1024.0; //Теперь поместите измеренное значение в код следующим образом NUM_SAMPLES * 3315 (предположим, что вы измерили 3.315В) Используется для вычисления напряжения батареи.
return voltage; //Vbattery in millivolts
}
Дисплей прибора отображает текущее показание напряжения последовательно включённых аккумулятора в верхней первой строке после символа батареи. Под показанием напряжения батареи расположена строка отображения текущего измеренного значения УФ излучения mW/cm^2. Ниже расположена строчка с крупным шрифтом, на английском языке, с оценочным показанием УФ излучения (LOW - MODERATE - HIGH ! - VERY HIGH ! - EXTREME !) по всемирно принятой, стандартизированной шкале.
В правой верхней строке выводится максимально измеренное значение количество УФ излучения mW/cm^2 Строка с оценочным показанием УФ излучения, также "замораживает" максимально измеренное значение. Для сброса показаний необходимо выключить прибор кнопкой и вновь включить.
Описание важных, программных строчек в скетче:
float uvIntensity = mapfloat(outputVoltage, 1.002, 2.8, 0.0, 15.0);
В этой строке, после float uvIntensity = mapfloat(outputVoltage, указывается:
1.002 - напряжение на выходе датчика GY-ML8511 подключенному к A0 контакту Ардуино и принимаемому за начало отсчёта интенсивности УФ. Здесь можно подбирать значение (калибровать) в случае если показание на дисплее отличается от значения 0.00
2.8 - напряжение на выходе датчика GY-ML8511 подключенному к A0 контакту Ардуино и принимаемому за значение интенсивности УФ излучения 15 mW//cm^2 Это значение взято из таблицы параметров (dataschit) на ML8511
0.0 - отображаемое значение интенсивности УФ излучения при напряжении на выходе датчика GY-ML8511 при 1,002 вольт.
15.0 - отображаемое значение интенсивности УФ излучения при напряжении на выходе датчика GY-ML8511 при 2.8 вольт.
Статья не окончена, буду дополнять. Есть мысли залить отверстия кнопок корпуса эпоксидной смолой и добавить кнопку RESET. Или перенести всё в другой корпус трубки - посвежее.