3157浏览
查看: 3157|回复: 0

[M10项目] 做一个“视听两用”的简易行空板紫外线测试仪

[复制链接]
本帖最后由 zoey不种土豆 于 2025-2-14 17:59 编辑

长时间暴露在太阳紫外线 (UV) 辐射下会对皮肤和眼睛构成健康风险,从而导致过早衰老甚至癌症。有视觉障碍的人可能无法感知到阴影或阳光强度变化等视觉线索。他们可能没有意识到自己何时暴露在阳光直射下或紫外线水平很高。虽然人们通常会对暴露在强烈的阳光下产生“视觉印象”,但盲人可能会错过这一点,尤其是当凉爽的空气、风寒等也会阻止裸露的皮肤产生温暖的感觉时。如果没有视觉提示,就更难评估防晒需求并认识到防晒霜、帽子或太阳镜的重要性。
做一个“视听两用”的简易行空板紫外线测试仪图11

考虑到以上因素,我的想法是设计一个可穿戴或便携式紫外线指数计的原型,并为盲人提供声音通知。
本项目实现了紫外线辐射暴露监测应用程序的原型,以预防因过度暴露在紫外线中而引起的疾病。与普通的紫外线计一样,它测量当前的紫外线辐射强度水平,并将其与相应的紫外线指数和风险水平一起显示(可选)。此外,它还将 UV 指数表示为音调序列。
该解决方案可以使用 MCU 板(工作功率 3.3v - 5.v,至少一个可用的模拟引脚和两个可用的数字引脚)、一个 GUVA-S12D 紫外线传感器板、一个按钮、一个(可充电的)电池和可选:图形显示/RGB LED。

做一个“视听两用”的简易行空板紫外线测试仪图6

该项目主要用行空板M10和DFRobot的Gravity紫外线传感器来实现。

硬件准备
行空板M10
Gravity: GUVA-S12SD UV紫外线传感器

开发环境
Jupyter Notebook

什么是紫外线,如何测量?
紫外线(UV)光是一种电磁辐射,波长范围为200纳米至400纳米,比可见光(400纳米至750纳米)短,但比X射线长。紫外线约占太阳总电磁辐射输出的10%。短波紫外线能够损伤DNA并消毒接触的表面。对人类而言,皮肤暴露于紫外线下的常见影响是晒黑和晒伤,同时也会增加患皮肤癌的风险。
紫外线根据波长分为三个波段:UVA(315-400纳米),UVB(280-315纳米)和UVC(100-280纳米)。地球大气层,尤其是臭氧层,吸收了大部分太阳紫外线辐射。UVC被完全阻挡,大部分UVB被吸收,留下UVA作为到达地球表面的主要紫外线辐射。UVA的穿透力强于UVB,但能量较低,它能够到达皮肤深层,导致光老化并引发不同类型的皮肤癌。紫外线辐射强度以每平方米毫瓦(mW/m²)为单位测量。
为评估紫外线辐射的能量及其相关风险水平,紫外线指数(UV Index)应运而生。紫外线指数描述了地面水平的红斑紫外线辐射的预期日常峰值水平。红斑是指由于紫外线辐射导致的皮肤异常发红,例如晒伤,这是皮肤细胞因紫外线辐射而受损的结果。紫外线指数是一个从0到11+的线性刻度,指数值越高,表示紫外线辐射强度越高,当皮肤未受保护时,晒伤发生得越快、越严重。
紫外线指数由世界卫生组织(WHO)定义,并且在全球范围内统一。
做一个“视听两用”的简易行空板紫外线测试仪图7

安全的紫外线指数取决于个人的皮肤类型和暴露时长。一般来说,紫外线指数等于或低于2,属于安全水平。
紫外线指数为3到5,为中等水平,需要一些防护措施。
紫外线指数为6到7,为较高水平,需要采取防护措施,如戴帽子、太阳镜和涂抹防晒霜。
紫外线指数为8到10,则表示等级较高,需要额外的防护措施,如在中午时段寻找阴凉处和穿着防晒服。
紫外线指数为11或以上,是极端水平,需要采取所有可能的预防措施。

项目设计思路
项目计划根据测得的紫外线水平和相关风险等级得出紫外线指数,以图像和声音的两种方式提醒使用者。

图像提醒
设计GUI ,在背景图像上显示 UV 指数值和相关的风险级别,并带有与风险级别相关的颜色,或者,单个 RGB LED 可以显示与风险级别相关的颜色。

声音提醒
用一连串音调的形式呈现紫外线指数:
每个音调序列的开头是一个基准音调C,随后是——
与(四舍五入后的)紫外线指数1到5级相对应的若干个F音调,或者——
在五个F音调之后,与(四舍五入后的)紫外线指数6到10级减5相对应的若干个A音调,或者——
对于(四舍五入后的)紫外线指数11级及以上,是五个F音调接着五个A音调和一个C音调(高八度)。
比如,如果紫外线指数是4,音调序列就是C、F、F、F、F;如果紫外线指数是6.7,音调序列就是C、F、F、F、F、F、A、A。

以乐谱形式表示,音调序列如下图所示:
做一个“视听两用”的简易行空板紫外线测试仪图1
表示紫外线指数 0 - 11 级的音调序列的乐谱



制作过程
第一步 连接硬件
把紫外线传感器连接到行空板M10的P21接口上。
做一个“视听两用”的简易行空板紫外线测试仪图5

第二步 编程
编写中使用了 UNIHIKER 库和 PinPong 库。
  1. # -*- coding: UTF-8 -*-
  2. # Experiment Effect: Print the analog value of the UNIHIKER P21 pin
  3. # Wiring: Connect a DFRobot Gravity:Analog UV Sensor V2 to the UNIHIKER P21 pin
  4. import time
  5. from pinpong.board import Board, Pin
  6. from unihiker import GUI
复制代码

第三步 辅助函数
紫外线指数(UV Index)
紫外线传感器模块的输出电压与传感器检测到的紫外线强度成正比。输出电压公式为:Vo = 4.3 * 二极管电流(微安,uA).
如果光电流为1uA(对应9 mW/cm²的紫外线强度),输出电压为4.3V。
紫外线指数是通过将从传感器读取的电压值与以下GUVA-S12D传感器的映射表进行比较来计算的。
做一个“视听两用”的简易行空板紫外线测试仪图4
GUVA-S12D - 电压 - UV 指数映射

  1. # Function to convert sensor output voltage (mV) to UV index
  2. # for a GUVA-S12D based analog UV sensor based on a conversion table.
  3. # See http://www.esp32learning.com/code/esp32-and-guva-s12sd-uv-sensor-example.php
  4. # for conversion table ...
  5. def uv_index(mv):
  6.     uvi_mv_thresholds = [50, 227, 318, 408, 503, 606, 696, 795, 881, 976, 1079, 1170];
  7.     for threshold in uvi_mv_thresholds:
  8.         if (mv < threshold ):
  9.             break
  10.     i = uvi_mv_thresholds.index(threshold)
  11.     if (i < 11 ):
  12.         uvi = mv/threshold*(i+1)
  13.     else:
  14.         uvi = 11
  15.     return uvi
复制代码

紫外线水平(Risk level)
对于紫外线传感器来说:“输出电压为:Vo =4.3×二极管电流(微安,uA)。因此,如果光电流为1uA(约等于9 mW/cm²),输出电压就是4.3V。
  1. # Function to convert sensor output voltage (mV) to mW/m^2
  2. # for a GUVA-S12D based analog UV sensor: "The output voltage is: Vo = 4.3 * Diode-Current-in-uA.
  3. # So if the photocurrent is 1uA (~ 9 mW/cm^2), the output voltage is 4.3V."
  4. def uv_level(mv):
  5.     return ( mv / 43 * 9 ) # 1 uA per 9 mW/cm^2 at 4.3V
复制代码

风险等级
做一个“视听两用”的简易行空板紫外线测试仪图2

  1. def uv_risk_level(uvi):
  2.     # UV risk level mapping (UV index threshold,risk level,display color)   
  3.     risk_levels=[(2,"low","green"),(5,"moderate","yellow"),(7,"high","orange"),(10,"very high","red"),(11,"extreme","violet")]
  4.     for risk_level in risk_levels:
  5.         if (uvi <= risk_level[0]):
  6.             break
  7.     return risk_level
复制代码

可听紫外线指数(Audible UV Index)
紫外线指数通过内部蜂鸣器播放的音调序列来呈现:
每个序列的开头是一个基础音调 C。
随后是与(四舍五入后的)紫外线指数1到5级相对应的若干个 F 音调,或者——
在五个 F 音调之后,与(四舍五入后的)紫外线指数6到10级减5相对应的若干个 A 音调,或者——
对于(四舍五入后的)紫外线指数11级及以上,是五个 F 音调接着五个 A 音调和一个高八度的 C 音调。
示例:
如果紫外线指数是 4,音调序列是 C, F, F, F, F。
如果紫外线指数是 6.7,音调序列是 C, F, F, F, F, F, A, A。
如果紫外线指数是 11 或更高,音调序列是 C, F, F, F, F, F, A, A, A, A, A, C(高八度)。
  1. def buzzer_play_uv_index_melody(uvi):
  2.     # Play the corresponding tone sequence for the measured UV index on the buzzer:
  3.     # C5 (F5){UV index} for an UV index < 6,
  4.     # C5 (F5){5} (A5){UV index - 5} for an UV index 6 - 10 and
  5.     # C5 (F5){5} (A5){5} C6 for UV index 11 ...
  6.     buzzer.set_tempo(4, 160)
  7.     buzzer.pitch(523, 4) # C5
  8.     for i in range(0,uvi):
  9.         if i < 5:
  10.             buzzer.pitch(698, 4) # F5
  11.         elif i < 10:
  12.             buzzer.pitch(880, 4) # A5
  13.         else:
  14.             buzzer.pitch(1046, 4) # C6
复制代码

第四步 应用代码
按钮的中断处理程序
  1. def btn_a_rasing_handler(pin):  # Interrupt event callback function for button A rising edge
  2.     global btn_a_pressed
  3.     btn_a_pressed = True
复制代码

初始化
  1. # ADC analog input pins supported: P0 P1 P2 P3 P4 P10 P21 P22
  2. # adc21 = ADC(Pin(Pin.P21))  # Use Pin object with ADC to enable analog input - Method 1
  3. adc21 = Pin(Pin.P21, Pin.ANALOG)  # Initialize the pin as an analog input - Method 2
复制代码

按钮的中断处理
  1. btn_a_pressed = False
  2. button_a.irq(trigger=Pin.IRQ_RISING, handler=btn_a_rasing_handler)  # Trigger on rising edge
复制代码

第五步 图形用户界面(GUI)设置
图形用户界面会在背景图像上显示测量到的紫外线指数(UV指数)以及相应的风险等级,并且背景图像会带有与风险等级相关联的颜色。

做一个“视听两用”的简易行空板紫外线测试仪图3
屏幕显示此时紫外线指数较高

  1. # GUI:
  2. #   Display a background image with the color touch of the risk level,
  3. #   the UV index and the risk level text ...
  4. bg = gui.draw_image(x=0, y=0, h=320, w=240, image='img/background_green.jpg')
  5. title = gui.draw_text(x=120, y=80, text="UV Index", origin="center", color="white", font_size=25)
  6. uv_index_text = gui.draw_digit(x=120, y=160, text="UVI", origin="center", color="white", font_size=50) # Display UV index using 7-segment font
  7. uv_risk_text = gui.draw_text(x=120, y=240, text="N/A", origin="center", color="white", font_size=25)
复制代码

第六步 主循环
  1. r0 = None
  2. while True:
  3.     # Read the sensor value ...
  4.     # v = adc21.read()  # Read the analog signal value from pin A0 - Method 1
  5.     v = adc21.read_analog()  # Read the analog signal value from pin A0 - Method 2
  6.     # Calculate UV index, level and risk ...
  7.     i = uv_index(v)
  8.     l = uv_level(v)
  9.     r = uv_risk_level(i)
  10.     # Print the data ...
  11.     # print("P21 =", v)
  12.     # print("UV index =",i)
  13.     # print("UV level =",l)
  14.     # print("Risk level:",r[1])
  15.     # print("-----------------------------------------------------------------------")
  16.    
  17.     # Update UI ...
  18.     uv_index_text.config(text="%.2f" % i)
  19.     if r0 != r: # Update the background image and the risk level text only if the risk level changed ...
  20.         bg.config(image='img/background_'+r[2]+'.jpg')
  21.         uv_risk_text.config(text=r[1])
  22.    
  23.     # If the button has been pressed, play the UV index 'melody' ...
  24.     if  btn_a_pressed:
  25.         btn_a_pressed = False
  26.         buzzer_play_uv_index_melody(round(i))
  27.    
  28.     i0 = i
  29.     l0 = l
  30.     r0 = r
复制代码

测试一下,大功告成!

做一个“视听两用”的简易行空板紫外线测试仪图10

做一个“视听两用”的简易行空板紫外线测试仪图9

做一个“视听两用”的简易行空板紫外线测试仪图8



项目文件:
下载附件行空板紫外线指示仪.rar


原文作者:tf++
原文链接:https://community.dfrobot.com/makelog-315051.html
发表时间:2025.02.05




您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail