【搬运】M5Stick+TSL250R检查LED光源
其基本思想是创建一个简单的设备,可以比较光源(如LED灯泡)的质量。我使用了TSL250R集成电路,包括光电二极管和带有配置反馈回路的运算放大器。该集成电路是输出电压与光强成正比的光学传感器。我把这个传感器放在M5Stick开发板的外壳里,直接连接到ESP32模块。传感器的输出与35号GPIO相连。
输出数据由ESP32板的硬件定时器触发的ADC采样。采样后,计算出FFT和闪烁百分比值。基于FFT得到最大峰值的频率。此外,还显示一个带有输入数据的绘图。在此基础上,我们可以看到输入信号的形状和幅度。所有数据都显示在OLED显示屏上。
程序用C语言编写,使用了ArduinoFFT和U8g2库。
参考电路
测量传感器输出的峰值和平均值。应用一些平均值来降低噪声。
对于正弦波信号,闪烁百分比可通过以下公式计算:
% Flicker = (peak-peak value)/ (2*average value)
如果灯光闪烁波形不是正弦波形,则可根据以下公式计算闪烁百分比:
% Flicker = (max value - min value)/(max value + min value)
以下是一些LED的测试结果:
#include <Arduino.h>
#include <U8g2lib.h>
#include <arduinoFFT.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
U8G2_SH1107_64X128_F_4W_HW_SPI u8g2(U8G2_R1, /* cs=*/ 14, /* dc=*/ 27, /* reset=*/ 33);
arduinoFFT FFT = arduinoFFT();
hw_timer_t *timer = NULL;
bool getSample;
const byte maxSamples = 128;
const word samplingFrequency = 2000;
double vReal;
double vImag;
word adcData;
byte sampleCount;
bool adcDataReady;
void timerInterrupt() {
if (!getSample) {
getSample = true;
}
}
void setup() {
u8g2.begin();
u8g2.setFont(u8g2_font_5x7_tr);
analogReadResolution(12);
getSample = false;
adcDataReady = false;
sampleCount = 0;
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &timerInterrupt, true);
timerAlarmWrite(timer, 1000000 / samplingFrequency, true);
timerAlarmEnable(timer);
}
void readData(void)
{
if (getSample && !adcDataReady) {
adcData = analogRead(35);
sampleCount++;
if (sampleCount >= maxSamples) {
adcDataReady = true;
sampleCount = 0;
} else {
getSample = false;
}
}
}
word getFrequency(void)
{
for (byte i = 0; i < maxSamples; i++) {
vReal = double(adcData);
vImag = 0;
}
FFT.Windowing(vReal, maxSamples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, maxSamples, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, maxSamples);
return FFT.MajorPeak(vReal, maxSamples, samplingFrequency);
}
word getFlicker(void)
{
word flicker = 0;
word minVal = 65535, maxVal = 0;
for (byte i = 0; i < maxSamples; i++)
{
if (minVal > adcData) {
minVal = adcData;
}
if (maxVal < adcData) {
maxVal = adcData;
}
}
if ((minVal + maxVal) != 0) {
flicker = ((maxVal - minVal) / (maxVal + minVal)) * 100;
}
return flicker;
}
void drawPlot(void)
{
word r = 1 << 12;
r = r / 54;
for (byte i = 0; i < maxSamples; i++) {
u8g2.drawPixel(i, 54 - (adcData / r));
}
}
void loop() {
readData();
Frequency:
if (adcDataReady) {
char displayText;
word frequency = getFrequency();
word flicker = getFlicker();
u8g2.clearBuffer();
snprintf (displayText, 19, "F:%dHz", frequency);
u8g2.drawStr(10, 8, displayText);
snprintf (displayText, 19, "Flicker:%d%%", flicker);
u8g2.drawStr(60, 8, displayText);
u8g2.drawLine(0, 10, 163, 10);
drawPlot();
u8g2.sendBuffer();
adcDataReady = false;
getSample = false;
delay(100);
}
}
页:
[1]