柳春晓 发表于 2020-10-10 18:23:18

分光光度计实验-光谱传感器

本帖最后由 柳春晓 于 2020-11-3 17:01 编辑

这篇文章中我将带大家使用光谱传感器来做一个简易的分光光度计,通过数据采集、拟合曲线等操作,最终实现能将水中的溶解物质的浓度显示出来。

## 一、背景介绍

首先来给大家介绍一下分光光度计和光谱传感器是什么。

### 1.分光光度计

**分光光度计:**又称光谱仪,主要由光源、单色器、样品室、检测器、信号处理器和显示与存储系统组成。当我们用他来测量一个液体中含有某物质的浓度时,由于很多物质是有吸光性的,而且不同物质吸收的光谱(颜色)是不同的,利用这些特性就可以鉴别出液体中含有某种物质的浓度。

**光源和单色器:**真实的光度计光源使用的是钨光灯,然后用棱镜作为单色器将钨光灯的光折射,得到由红、橙、黄、绿、蓝、靛、紫组成的连续色谱。我们为了实验的简单性,直接使用一个普通的红色LED灯来模拟光源。

剩下的,样品室我们使用的是比色皿,某宝3RMB/个;检测器就是我们的光谱传感器;信号处理单元使用UNO控制器

### 2.光谱传感器

AS7341可见光传感器,采用业内知名的ams公司推出的新一代AS7341光谱传感IC。该传感器有8个可见光通道、1个闪烁通道、1个NIR通道和1个未加滤光片的通道。该传感器拥有6个独立的16位ADC通道,可以并行的处理数据。可检测F1(405-425nm)、F2(435-455nm)、F3(470-490nm)、F4(505-525nm)、F5(545-565nm)、F6(580-600nm)、F7(620-640nm)、F8(670-690nm)八个波段的波长强度。

### 3.设备安装

需要准备:

**Arduino UNO - 1**

**Arduino扩展板 - 1**

**光谱传感器 - 1**

**红色LED灯 - 1**

**比色皿 - 1**

**显示器 - 1**

**3D打印外壳 - 1 **

**烧杯 - 6(或其他容器)**

**染料(或其他溶于水的物质)**

由于组装比较简单,这里就不一步步展示安装过程了,组装完成后:


## 二、调试光谱传感器


将LED灯的正负极对应接到板子的正负极上点亮小灯,光谱传感器按照上图连接,然后烧录代码:
/*!
* @file getData.ino
* @brief 读取光谱传感器10个光通道的数值,光源的某波长的光越多,对应通道的数值越大
*
* @copyright   Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
* @licence   The MIT License (MIT)
* @author (li.feng@dfrobot.com)
* @versionV1.0
* @date2020-07-16
* @get from https://www.dfrobot.com
* @url https://github.com/DFRobot/DFRobot_AS7341
*/
#include "DFRobot_AS7341.h"
/*!
* @brief Construct the function
* @param pWire IC bus pointer object and construction device, can both pass or not pass parameters, Wire in default.
*/
DFRobot_AS7341 as7341;

void setup(void)
{
Serial.begin(115200);
//检测IIC是否能正常通信
while (as7341.begin() != 0) {
    Serial.println("IIC初始化失败,请检测连线是否正确");
    delay(1000);
}
////Integration time = (ATIME + 1) x (ASTEP + 1) x 2.78µs
////设置寄存器ATIME的值,通过该值可计算Integration time的值,该值表示读取数据过程中必须要消耗的时间
//as7341.setAtime(29);
////设置ASTEP寄存器的值,通过该值可计算Integration time的值,该值表示读取数据过程中必须要消耗的时间
//as7341.setAstep(599);
////设置增益(0~10对应 X0.5,X1,X2,X4,X8,X16,X32,X64,X128,X256,X512)
//as7341.setAGAIN(7);
////使能LED
////as7341.enableLed(true);
////设置引脚电流控制亮度(1~20对应电流 4mA,6mA,8mA,10mA,12mA,......,42mA)
////as7341.controlLed(10);

}
void loop(void)
{
DFRobot_AS7341::sModeOneData_t data1;
DFRobot_AS7341::sModeTwoData_t data2;


//开始光谱的测量.
//通道映射的模式 :1.eF1F4ClearNIR,2.eF5F8ClearNIR
as7341.startMeasure(as7341.eF1F4ClearNIR);
//读取传感器数据通道0~5的值,eF1F4ClearNIR模式下.
data1 = as7341.readSpectralDataOne();

Serial.print("F1(405-425nm):");
Serial.println(data1.ADF1);
Serial.print("F2(435-455nm):");
Serial.println(data1.ADF2);
Serial.print("F3(470-490nm):");
Serial.println(data1.ADF3);
Serial.print("F4(505-525nm):");   
Serial.println(data1.ADF4);
//Serial.print("Clear:");
//Serial.println(data1.ADCLEAR);
//Serial.print("NIR:");
//Serial.println(data1.ADNIR);
as7341.startMeasure(as7341.eF5F8ClearNIR);
//读取传感器数据通道0~5的值,eF5F8ClearNIR模式下.
data2 = as7341.readSpectralDataTwo();
Serial.print("F5(545-565nm):");
Serial.println(data2.ADF5);
Serial.print("F6(580-600nm):");
Serial.println(data2.ADF6);
Serial.print("F7(620-640nm):");
Serial.println(data2.ADF7);
Serial.print("F8(670-690nm):");
Serial.println(data2.ADF8);
Serial.print("Clear:");
Serial.println(data2.ADCLEAR);
Serial.print("NIR:");
Serial.println(data2.ADNIR);
delay(1000);
}

在比色皿中什么都没加入的情况下,打开串口监视器后,可以观察到数据中,F7波段的光强度最高,因此我们将采用F7波段光的强度作为参考,记录F7的数据。


##三、实验

接下来我们通过一个实验来记录几组数据。需要准备6个烧杯(或其他容器),一些染料。

1.将6个烧杯中都倒入100ml的清水准备好

2.将染料按照一定比例加入6个清水的烧杯中,第一杯不加,第二杯加入1滴,第三杯加入2滴,第四杯加入3滴,第五杯加入4滴,第六杯加入5滴。

3.将6个烧杯中的溶液搅拌好,分别倒入到比色皿中进行数据测量,为保证数据准确性,每一次更换溶液时要将比色皿清洗干净,并将测量出的数据记录到excel表格中。


## 四、分析数据

通过观察数据,我们可以看到随着染料浓度越来越高,F7的强度就变得越来越低,我们假设每滴入一滴染料会使浓度增加15%,所以我们的六次数据可以拟合成一条浓度0%-75%的曲线。接下来我们就在Excel中将这条曲线拟合出来。

1.首先选中浓度一行的数据,然后选中F7一行的数据,最后点击创建散点图。

2.在出现的散点图中任选一点右键,选择添加趋势线,趋势线选项选择一个最贴合数据点的曲线,最后显示公式,这样就可以得到最终拟合出的公式了。我获得的公式是:y = 2E-06x2 - 0.0257x + 70.525。

## 五、屏幕直接显示未知的浓度

将上一步的公式直接带入到代码中,在代码中添加代码:**outdata=(0.000002*data2.ADF7*data2.ADF7-0.0257*data2.ADF7+70.525);**

然后加入对应的显示屏的库文件,以及修改显示部分的代码,教程最后的附件中会给出最终的代码和需要的库。
#include "DFRobot_AS7341.h"
#include <DFRobot_SSD1306_I2C.h>

const chCode chBuf[] = {
{0x6d53,0xe6b593,0xC5A8,{0x00,0x40,0x20,0x40,0x10,0x40,0x17,0xfc,0x84,0x84,0x48,0x88,0x41,0x40,0x11,0x44,0x13,0x48,0x25,0x30,0xe9,0x20,0x21,0x10,0x21,0x08,0x21,0x44,0x21,0x82,0x01,0x00}},
{0x5ea6,0xe5baa6,0xB6C8,{0x01,0x00,0x00,0x80,0x3f,0xfe,0x22,0x20,0x22,0x20,0x3f,0xfc,0x22,0x20,0x22,0x20,0x23,0xe0,0x20,0x00,0x2f,0xf0,0x24,0x10,0x42,0x20,0x41,0xc0,0x86,0x30,0x38,0x0e}}
};

DFRobot_AS7341 as7341;
DFRobot_SSD1306_I2C oled12864;
double outdata;
void setup(void)
{
Serial.begin(115200);
oled12864.begin(0x3c);
//检测IIC是否能正常通信
while (as7341.begin() != 0) {
    Serial.println("IIC初始化失败,请检测连线是否正确");
    delay(1000);
}
}
void loop(void)
{
DFRobot_AS7341::sModeOneData_t data1;
DFRobot_AS7341::sModeTwoData_t data2;


//开始光谱的测量.
//通道映射的模式 :1.eF1F4ClearNIR,2.eF5F8ClearNIR
as7341.startMeasure(as7341.eF1F4ClearNIR);
//读取传感器数据通道0~5的值,eF1F4ClearNIR模式下.
data1 = as7341.readSpectralDataOne();

Serial.print("F1(405-425nm):");
Serial.println(data1.ADF1);
Serial.print("F2(435-455nm):");
Serial.println(data1.ADF2);
Serial.print("F3(470-490nm):");
Serial.println(data1.ADF3);
Serial.print("F4(505-525nm):");   
Serial.println(data1.ADF4);
//Serial.print("Clear:");
//Serial.println(data1.ADCLEAR);
//Serial.print("NIR:");
//Serial.println(data1.ADNIR);
as7341.startMeasure(as7341.eF5F8ClearNIR);
//读取传感器数据通道0~5的值,eF5F8ClearNIR模式下.
data2 = as7341.readSpectralDataTwo();
Serial.print("F5(545-565nm):");
Serial.println(data2.ADF5);
Serial.print("F6(580-600nm):");
Serial.println(data2.ADF6);
Serial.print("F7(620-640nm):");
Serial.println(data2.ADF7);
Serial.print("F8(670-690nm):");
Serial.println(data2.ADF8);
Serial.print("Clear:");
Serial.println(data2.ADCLEAR);
Serial.print("NIR:");
Serial.println(data2.ADNIR);
delay(1000);
outdata=(0.000002*data2.ADF7*data2.ADF7-0.0257*data2.ADF7+70.525);
Serial.print("浓度:");
Serial.println(outdata);

oled12864.setChCode(chBuf);

oled12864.setCursor(1, 1);
oled12864.print("浓度");
oled12864.setCursor(110, 1);
oled12864.print("%");
oled12864.setCursor(40, 1);
oled12864.print(outdata);
}
最后我随意混合了一些溶液装入了比色皿中
将比色皿放入我们的仪器中,可以通过屏幕直接读取到溶液的浓度


官方wiki链接:https://wiki.dfrobot.com.cn/_SKU_SEN0365_AS7341_Visible_Light_Sensor




wcm_e45 发表于 2020-10-13 15:39:06

高级啊, 能不能对不同的玉米油做个比对啊,能不能查地沟油啊,哈!

柳春晓 发表于 2020-10-14 09:26:51

wcm_e45 发表于 2020-10-13 15:39
高级啊, 能不能对不同的玉米油做个比对啊,能不能查地沟油啊,哈!

可以的,你这个点子非常棒{:6_209:}

微笑的rockets 发表于 2020-10-16 11:12:04

wcm_e45 发表于 2020-10-13 15:39
高级啊, 能不能对不同的玉米油做个比对啊,能不能查地沟油啊,哈!

这个需要做实验,不确定他们的光谱吸收特性。
不过这是一个非常好的想法,建议实际的测一下。

川山甲的壳 发表于 2020-11-2 11:26:48

这个能做什么衣服最吸热的实验吗? 比如黑色把所有的光都吸收了,然后就测不出光谱值了。这样的场景也要在全黑的情况下实现吗?

柳春晓 发表于 2020-11-2 21:11:13

川山甲的壳 发表于 2020-11-2 11:26
这个能做什么衣服最吸热的实验吗? 比如黑色把所有的光都吸收了,然后就测不出光谱值了。这样的场景也要在 ...

衣服是布料,它的遮光效果比吸光效果要强,所以还要看布料的透光性,这个影响因素不稳定,检测衣服吸热性的话还是直接用测温传感器效果更好。纯黑的环境问题,试验中也不是纯黑的环境,盒子里是有一个LED灯作为光源的,之所以在盒子里是为了去除环境光的影响,保证每一种液体都是在相同的光源下。

rzegkly 发表于 2020-11-7 07:23:57

科学探究很好的器材

柳春晓 发表于 2020-11-10 11:55:03

rzegkly 发表于 2020-11-7 07:23
科学探究很好的器材

{:6_202:}{:6_202:}

rzegkly 发表于 2020-11-10 12:07:28

柳春晓 发表于 2020-11-10 11:55


{:5_178:}

dbc0301 发表于 2020-11-11 09:36:12

专业{:6_209:}

云天 发表于 2020-11-27 11:17:55

趋势线,提取公式很好。{:6_209:}

菜先生 发表于 2022-1-25 21:40:15

这是我们公司的核心技术

赤星三春牛! 发表于 2022-1-29 10:16:45

啊!厉害!!!
页: [1]
查看完整版本: 分光光度计实验-光谱传感器