Test AS7341 Spectrual Sensor---Comparison of Common Light Sources for Household
Background
For guys who watched the Japanese manga series Dr. STONE, you may like this saying in it----âIn our time, there is no darkness!â. Since Edisonâs invention of the worldâs first practical bulb in 1879, the light bulb has a history of more than 140 years. It was just a moment in the whole human history, but it didnât prevent the light bulb from becoming the most crucial invention. During this period, electric light has gone through many iterations and many technologies have emerged endlessly. Here, I'll use the DFRobot AS7341 visible spectrum sensor to make a detailed comparison of several types of light bulbs commonly used in the household.
Principle
First, we need to learn some basic knowledge about light. As we all know, sunlight is composed of red, orange, yellow, green, cyan, blue, and purple. However, this expression is not accurate. Sunlight is composed of a continuous spectrum that can completely cover the visible light range of the human eyes.
Thanks to rod cells and cone cells in the eyes, humans can see this colorful world. The rod cells are sensitive to low light and good at seeing the outlines of objects in darkness. Rod cells are rich in the eyes of nocturnal animals. The opposite, cone cells respond to different colors of light, restoring the colors of the objects. There are 3 types of cone cells: red, green, and blue in the human retina. A beam of light will stimulate these three types of cone cells to different degrees, and the value is then reduced to the color of light in the brain. In other words, color is just a concept in the human brain. If you mingle red, green, and blue in the right proportion, you can get any of the colors you want. It is the principle that how your phones and computers display all kinds of colors.
Next comes the color temperature. Theoretically speaking, any object with temperature will actively radiate electromagnetic waves to the outside world, and the higher the temperature, the shorter the wavelength. Then the light color looks like going from black to red, yellow, white, and finally blue. Red light emitted by heated and hit iron, and bule light emitted by the gas stove are both due to this principle. When an ordinary incandescent lamp works normally, the lamp filament can reach 2500 degrees Celsius, which equals an absolute temperature of 2773K. This yellow-white light is the temperature of the light produced by the incandescent lamp. Many modern light bulbs, such as fluorescent lights and LED lights, adopted different light-emitting principle. The packaging of the bulb may say something like âcolor temperature 5000Kâ. This is not to say that the light bulb generates such a high internal temperature when working. This temperature, referring to the color of light equivalent to that produced by a black body at the same temperature, is a concept about correlated color temperature. It is very complicated to understand the correlated color temperature. Here I use the formula fitting method to simplify the process into the following steps:
1. In order to calculate the color temperature of light, we need to use the sensor to obtain the spectrum of this light and the sensitivity of the three cones of the human eye to the lights of different wavelengths: the tristimulus function. The tristimulus function can be obtained by looking up the table.
2. Multiply the spectrum by the tristimulus function respectively and then integrate it to get the tristimulus values (X, Y, Z).
3. Through converting to color coordinates (x-y) by formulas, any color can be found in the color coordinates.
4. Finally, calculate the color temperature by coordinates.
Code Implementation
In order to check the spectrum data more directly, I wrote a program using Processing.
/***************************************************************************
Created by dbc0301
***************************************************************************/
import processing.serial.*;
Serial port;
PFont myFont;
int tmp;
//int begin='$';//begin
int end='\r';//end
char rev[] = new char[15];//datas
int revFlag=0;
int[] data=new int[10];//F1,F2,F3,F4,F5,F6,F7,F8,Clear,NIR
//int F1,F2,F3,F4,F5,F6,F7,F8,Clear,NIR;
//Stimulus Function
float[] Fx={0.07763, 0.34806, 0.09564, 0.02910, 0.51205, 1.02630, 0.64240, 0.04677};
float[] Fy={0.00218, 0.02980, 0.13902, 0.60820, 1.00000, 0.75700, 0.26500, 0.01700};
float[] Fz={0.37130, 1.78260, 0.81295, 0.11170, 0.00575, 0.00110, 0.00005, 0.00000};
int textHight=25;
float rt=1;//Length scaling
void receiveDatas(){
for(int i=0;port.available()>0;i++){
tmp=port.read();
if(tmp!=end){
rev=char(tmp);
}else{
rev=char(tmp);
revFlag=1;
tmp=port.read();
break;
}
}
}
void setup(){
//size(1074,241);
size(1250,301);
background(0);//white255 black0
noStroke();
myFont = createFont("Microsoft YaHei", 20);
textFont(myFont);
println(Serial.list()[0]);
port = new Serial(this,Serial.list()[0],115200);
}
void draw(){
receiveDatas();
if(revFlag==1){
String[] m=match(new String(rev), "(.*?):(.*?)\r");//Regular Expression Matching
//printArray(m);
try{
if(m[1].equals("F1")){
data[0]=int(m[2]);
}else if(m[1].equals("F2")){
data[1]=int(m[2]);
}else if(m[1].equals("F3")){
data[2]=int(m[2]);
}else if(m[1].equals("F4")){
data[3]=int(m[2]);
}else if(m[1].equals("F5")){
data[4]=int(m[2]);
}else if(m[1].equals("F6")){
data[5]=int(m[2]);
}else if(m[1].equals("F7")){
data[6]=int(m[2]);
}else if(m[1].equals("F8")){
data[7]=int(m[2]);
}else if(m[1].equals("Clear")){
data[8]=int(m[2]);
}else if(m[1].equals("NIR")){
data[9]=int(m[2]);
}else{
print("Wrong datas!");
}
}catch(NullPointerException e){
println(rev);
printArray(m);
}finally{}
revFlag=0;
//printArray(data);
//delay(10);
}
/*Display*/
//rectMode(CORNER);
background(0);
textSize(20);
fill(#8b3dc5);
rect(0,0,data[0]*rt,30);//F1
text(data[0], data[0]*rt, 0+textHight);//textHeight: veritcal height of text
fill(#00528e);
rect(0,30,data[1]*rt,30);//F2
text(data[1], data[1]*rt, 30+textHight);
fill(#00b1ed);
rect(0,60,data[2]*rt,30);//F3
text(data[2], data[2]*rt, 60+textHight);
fill(#01ffcd);
rect(0,90,data[3]*rt,30);//F4
text(data[3], data[3]*rt, 90+textHight);
fill(#00af50);
rect(0,120,data[4]*rt,30);//F5
text(data[4], data[4]*rt, 120+textHight);
fill(#ffff01);
rect(0,150,data[5]*rt,30);//F6
text(data[5], data[5]*rt, 150+textHight);
fill(#ffc000);
rect(0,180,data[6]*rt,30);//F7
text(data[6], data[6]*rt, 180+textHight);
fill(#c10005);
rect(0,210,data[7]*rt,30);//F8
text(data[7], data[7]*rt, 210+textHight);
fill(#ffffff);
rect(0,240,data[8]*rt,30);//Clear
text(data[8], data[8]*rt, 240+textHight);
fill(#888888);
rect(0,270,data[9]*rt,30);//F8
text(data[9], data[9]*rt, 270+textHight);
//delay(1);
/*Color Temperaure*/
float X,Y,Z,x,y,n,temp;
X=(data[0]*Fx[0] + data[1]*Fx[1] + data[2]*Fx[2] + data[3]*Fx[3] + data[4]*Fx[4] + data[5]*Fx[5] + data[6]*Fx[6] + data[7]*Fx[7]);//20/1000;//20 is the interval of integration. 1000 is used to converted the value into a real number between 0~1
Y=(data[0]*Fy[0] + data[1]*Fy[1] + data[2]*Fy[2] + data[3]*Fy[3] + data[4]*Fy[4] + data[5]*Fy[5] + data[6]*Fy[6] + data[7]*Fy[7]);//20/1000;//But it is meaningless to multiply this number here since it will be reduced in the next step
Z=(data[0]*Fz[0] + data[1]*Fz[1] + data[2]*Fz[2] + data[3]*Fz[3] + data[4]*Fz[4] + data[5]*Fz[5] + data[6]*Fz[6] + data[7]*Fz[7]);//20/1000;
x=X/(X+Y+Z);
y=Y/(X+Y+Z);
n=(x-0.3320)/(0.1858-y);
temp=437*n*n*n+3601*n*n+6831*n+5517;
print(temp);
println("K\n");
}
And the corresponding Arduino program.
#include "DFRobot_AS7341.h"
DFRobot_AS7341 as7341;
void setup(void)
{
Serial.begin(115200);
//Detect if IIC can communicate properly
while (as7341.begin() != 0) {
Serial.println("IIC init failed, please check if the wire connection is correct");
delay(1000);
}
// //Integration time = (ATIME + 1) x (ASTEP + 1) x 2.78µs
// //Set the value of register ATIME, through which the value of Integration time can be calculated. The value represents the time that must be spent during data reading.
as7341.setAtime(29);
// //Set the value of register ASTEP, through which the value of Integration time can be calculated. The value represents the time that must be spent during data reading.
as7341.setAstep(599);
// //Set gain value(0~10 corresponds to X0.5,X1,X2,X4,X8,X16,X32,X64,X128,X256,X512)
as7341.setAGAIN(2);//Use 2 in testing
// //Enable LED
// //as7341.enableLed(true);
// //Set pin current to control brightness (1~20 corresponds to current 4mA,6mA,8mA,10mA,12mA,......,42mA)
// //as7341.controlLed(10);
}
void loop(void)
{
DFRobot_AS7341::sModeOneData_t data1;
DFRobot_AS7341::sModeTwoData_t data2;
//Start spectrum measurement
//Channel mapping mode: 1.eF1F4ClearNIR,2.eF5F8ClearNIR
as7341.startMeasure(as7341.eF1F4ClearNIR);
//Read the value of sensor data channel 0~5, under 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);
//delay(50);
as7341.startMeasure(as7341.eF5F8ClearNIR);
//Read the value of sensor data channel 0~5, under 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(50);
}
In the code, as7341.setAGAIN(2) can be used to adjust the gain of the value. And the values of as7341.setAtime(29) and as7341.setAstep(599) can be adjusted to increase the integral time even in darkness.
The following is the test result. The ten color columns from top to bottom are the Sensor's F1-F8, filter-free channel, and infrared channel. At the same time, the color temperature values are ceaselessly being printed. Due to the accuracy of the sensor itself and the fact that it has not been calibrated by professional instruments, there may be an error of several hundred kelvin. The results are for reference only.
Test
A Test Case Adapted by Parcel Boxes
Here Are the Competitors
Given Data
The following test is performed under this configuration:
as7341.setAtime(29);
as7341.setAstep(599);
as7341.setAGAIN(2);
The first competitor is the 25W incandescent lamp. It can be seen that the curve of the spectrum is very smooth, and the infrared component is very high, which seems to exceed the measurement range of the sensor. The color temperature fluctuates around 2650K.
No. 1
After the test, the whole test box is warm since most of the 25W power is converted to heat.
The followings are No.2-4 LED, which are put together because they are produced by the same manufacturers. It can be seen from the spectrum that all of these bulbs are with a small spike in the waveband of 435-455nm. The color temperature of No.2 is about 4700K, which has a distance to the marked 6000K. The color temperature of No.3 fluctuates at 4750, and No.4 is about 4830K. So, they probably use the same kind of LED beads.
No. 2
No. 3
No. 4
The next one is the No.5 fluorescent light. Though it is labeled as 5W, it looks not as bright as the 3W LED on the spectrum. Its efficiency ratio is really poor. The values look unstable when the fluorescent lamp is just turned on. After 3-5 minutes, the brightness is slightly increased, but still much lower than the 3W LED.
Startingâ¦
3~5 Minutes Later
The last competitor is the 5W, 2700K LED from IKEA. The actual result is about 2680K, which seems pretty accurate. As the most expensive one, this bulb is with the smoothest spectrum curve.
Flicker Frequency
The AS7341 sensor also has the function of measuring the flicker frequency of the light source, but it can only get four results: no flicker, 50HZ, 60HZ, and position frequency flicker. I measured the flicker frequency of each bulb with the sensor and found that they all flicker at 50Zz. This is because the alternating current in our country is officially 50HZ. But they give people different feelings. After turning up the shutter time or turning on the slow-motion photography mode of the cell phone, I found that the cheapest No. 2 LED light flickers very seriously, and the colder color temperature dazzles people. The best one is the No. 6 LED, whose flicker is basically not noticeable. This is because the No. 2 LED adopts a resistance-capacitance voltage-reducing, almost no AC component in the AC is filtered out, while the No. 6 LED uses a professional constant current driver chip, which can control the AC component in a small range. The ordinary incandescent lamp does not have any filter circuit, and it flickers continually under the lens of cell phone, so it is not as dazzling as the No. 2 LED. (The pictures below are all taken in slow motion of x32)
LED No. 2
LED No. 6
Incandescent Lamp No. 1
Generally, the conversion rate of LED light energy has won a perfect victory, but in order to save costs, many manufacturers will choose ordinary lamp beads with low color rendering rate and no constant current circuit. As a result, the LED will produce a lot of flickers. Bulbs produced by big factories are suggested, don't try a cheap one. For another, you can choose a light bulb with a warmer color temperature for daily use, even it will make everything around you look yellow and red, but it is less irritating to the human eyes and not dazzling.
For photographs, in order to restore the true color of the objects, you can choose the 5600K bulb of a high color rending index.