闪烁定义光学闪烁被定义为人造光源的脉动或波动的光现象。
 在低频闪烁中,光是可见的(人眼能够察觉光的闪烁)。超过100 hz的光学闪烁对于人眼来说不再可见,但仍然存在,可能对人体产生影响。
 大多数类型的人造光源在连接到电力主网(家庭或商业办公室)时会发出闪烁,这主要取决于国家的电力频率,通常是50 hz或60 hz。
 由于电流在光源中的交替流动,所有人造光源都会分别在50 hz和60 hz电力主网下发出100 hz或120 hz的闪烁频率。
 为了消除可见的闪烁并减少对人体的影响,大多数发光二极管(led)使用脉冲宽度调制(pwm)调光方法,以实现更高的闪烁频率。
 vd6283传感器可以检测光的闪烁频率,最高可达2 khz。
 最近在弄st的课程,需要样片的可以加群申请:615061293 。
视频教学https://www.bilibili.com/video/bv1fh4y1r7as/
样品申请https://www.wjx.top/vm/ohckxjk.aspx#px#)
源码下载https://download.csdn.net/download/qq_24312945/88394817
开发板设置在手册种给出了,闪烁手册可以查看an5639,资料链接如下。https://www.st.com/content/ccc/resource/technical/document/application_note/group1/9f/7e/8c/ce/36/85/4c/08/dm00776948/files/dm00776948.pdf/jcr:content/translations/en.dm00776948.pdf
在an5639手册中,需要对sb3进行连接。
同时gpio2需要接到mcu的adc通道中。
查看x-nucleo-6283a1手册,可以看到vd6283tx的gpio2连接到mcu的adc端口0-2。
在vd6283tx-satel中,可以看到vd6283tx通过sb3连接到了aflr_1v8。
 需要将aflr_1v8接到开发板的a0端口中。
开发板选择这里使用nucleo-f401re 开发板。
iic配置
串口配置
开启x-cube-als软件包
时钟树配置
adc使用定时器触发采样在app_als_adc_utils.c中,定义了adc使用的频率,为8000hz。
定时器的arr设置为10500-1,那么定时器频率为8000hz。
 trigger event selection :update event 定时器自动更新。
配置adc检测vd6283tx的gpio2管脚的ad值。
 设置触发方式为外部触发,选择刚刚配置的tim2,触发方式为上升沿触发。
开启中断。
keil配置
fft代码配置arm_cortexm4lf_math.lib 库包含了一系列数学函数,特别是适用于基于cortex-m4和cortex-m7处理器的浮点运算单元的优化数学例程。这些例程涵盖了常见的数学运算,如信号处理、滤波、变换等。
 arm_math.h 这个头文件包含了cmsis-dsp库的函数声明、宏定义和结构体定义等,可以通过包含这个头文件,使用库中提供的各种数学函数,包括信号处理、滤波、变换等。
 添加arm_cortexm4lf_math.lib文件。
同时导入arm_math.h文件。
app_x-cube-als.c由于需要进行fft算法,所以需要添加对应数学头文件。
#define arm_math_cm4#include arm_math.h#include app_als_adc_utils.h添加对应的函数申明。
#define flk_channel	(5u)/* * increasing the value of the flk_data_size symbol will increase * processing time, flicker accuracy and memory footprint */#define flk_data_size (1024u)#define fft_size (flk_data_size)/* private variables ---------------------------------------------------------*/static uint8_t is_quit_requested;static uint8_t is_autogain_requested;static int16_t flk_data[flk_data_size];volatile uint8_t als_eventdetected;/* * the fft of a real n-point sequence has even symmetry in the frequency domain. * the second half of the data equals the conjugate of the first half flipped in frequency. * looking at the data, we see that we can uniquely represent the fft using only n/2 complex numbers. * these are packed into the output array in alternating real and imaginary components: * x = { real[0], imag[0], real[1], imag[1], real[2], imag[2] ... real[(n/2)-1], imag[(n/2)-1 } */static arm_rfft_fast_instance_f32 instance_fft;static float32_t fft_in[flk_data_size];static float32_t fft_out_tmp[fft_size];static float32_t fft_out[fft_size/2];/* * the fft of a real n-point sequence has even symmetry in the frequency domain. * the second half of the data equals the conjugate of the first half flipped in frequency. * looking at the data, we see that we can uniquely represent the fft using only n/2 complex numbers. * these are packed into the output array in alternating real and imaginary components: * x = { real[0], imag[0], real[1], imag[1], real[2], imag[2] ... real[(n/2)-1], imag[(n/2)-1 } */static arm_rfft_fast_instance_f32 instance_fft;  static void mx_vd6283a1_analogflicker_process(void); static float32_t complex_abs(float32_t real, float32_t complex);static void init_fft(arm_rfft_fast_instance_f32 *instance, uint32_t size);static void perform_fft(arm_rfft_fast_instance_f32 *instance, int16_t *data, float32_t *ffti, float32_t *ffto, uint32_t size);static void find_flk_freq(uint32_t fs, float32_t *ffto, uint32_t *freq, uint8_t skip_dc, uint32_t size);static int32_t flicker_autogain(uint8_t instance, uint32_t *pappliedgain, uint32_t timeoutms);static void display_gain(uint32_t gain);在mx_vd6283a1_luxcct_init()函数中添加init_fft快速傅里叶变换初始化。
static void mx_vd6283a1_luxcct_init(void){  /* initialize virtual com port */  bsp_com_init(com1);  printf(vd6283tx lux / cct examplenn);  display_commands_banner();    /* initialize arm fft library */    init_fft(&instance_fft, fft_size);	  status = vd6283a1_light_sensor_init(light_sensor_instance_0);  if (status)  {    printf(vd6283a1_light_sensor_init failedn);    while(1);  }}初始化完毕之后,添加频率获取函数。
static void mx_vd6283a1_analogflicker_process(void){    uint32_t fs; /* sampling frequency */    uint32_t pos = 0;     uint32_t flk_freq = 0;    uint32_t index;    uint32_t current_gain;    uint32_t current_exposure;    /* initialize exposure time */    vd6283a1_light_sensor_setexposuretime(light_sensor_instance_0, 100000);    vd6283a1_light_sensor_getexposuretime(light_sensor_instance_0, ¤t_exposure);    printf(exposure set to %lu usn, (unsigned long)current_exposure);    /* initialize gain */    flicker_autogain(light_sensor_instance_0, ¤t_gain, 1);    printf(channel %u gain set to, flk_channel);    display_gain(current_gain);    status = als_adc_start(&fs);    if (status)    {        printf(adc start failedn);        while (1);    }    vd6283a1_light_sensor_startflicker(light_sensor_instance_0, flk_channel, light_sensor_flicker_analog);    while (!is_quit_requested)    {        status = als_adc_get_frame(&flk_data[pos], &index);        /* fill the adc frame buffer */        if (status == 0)        {            pos += adc_frame_size;        }        /* if the adc frame buffer is full, then process it */        if (pos == flk_data_size)        {            perform_fft(&instance_fft, flk_data, fft_in, fft_out, fft_size);            find_flk_freq(fs, fft_out, &flk_freq, 1, fft_size);            pos = 0; /* reset position index */            printf(flicker freq: %4lu hzr, (unsigned long)flk_freq);            fflush(stdout);            if (is_autogain_requested == 1)            {              vd6283a1_light_sensor_stopflicker(light_sensor_instance_0);              flicker_autogain(light_sensor_instance_0, ¤t_gain, 1);              printf(channel %u gain set to, flk_channel);              display_gain(current_gain);              vd6283a1_light_sensor_startflicker(light_sensor_instance_0, flk_channel, light_sensor_flicker_analog);              is_autogain_requested = 0;            }        }        handle_cmd(get_key());    }    als_adc_stop();    vd6283a1_light_sensor_stopflicker(light_sensor_instance_0);    vd6283a1_light_sensor_deinit(light_sensor_instance_0);    printf(quitting the demo...n);    while (1);}在mx_x_cube_als_process函数中开启频率获取函数,关闭光强获取函数mx_vd6283a1_luxcct_process。
添加增益设置函数。
/* * @brief find and apply appropriate gain value depending on saturation value * @warning this function mustn't be called when a capture is ongoing */static int32_t flicker_autogain(uint8_t instance, uint32_t *pappliedgain, uint32_t timeoutms){  int32_t res;  uint8_t i, j;  uint8_t idx = 7; /* start with mid-table value */  const uint8_t sat_limit = 2;  uint32_t saturation;  /* duplicate 0x42ab to avoid 100x and keep multiples of 2 for array size */  const uint16_t gains[] = {    0x42ab, 0x42ab, 0x3200, 0x2154, 0x1900, 0x10ab, 0x0a00, 0x0723,    0x0500, 0x0354, 0x0280, 0x01ab, 0x0140, 0x0100, 0x00d4, 0x00b5  };  /* clip timeout value */  timeoutms = timeoutms == 0 ? 1 : timeoutms;  timeoutms = timeoutms >= 100 ? 100 : timeoutms;  for (i = 0; i <= 3; i++)  {    vd6283a1_light_sensor_setgain(instance, flk_channel, gains[idx]);    vd6283a1_light_sensor_getgain(instance, flk_channel, pappliedgain);    res = vd6283a1_light_sensor_startflicker(instance, flk_channel, light_sensor_flicker_analog);        if (res)      return res;    /* read saturation value each ms so we can exit early if saturation detected */    for (j = 0; j  sat_limit)        break;    }    res = vd6283a1_light_sensor_stopflicker(instance);        if (res)      return res;    /* update index to next value */    if (i)      idx += saturation > sat_limit ? 1 < < (i - 1) : -(1 <  sat_limit)      idx++;  }  /* clip index if it reaches max value */  if (idx > 15)     idx = 15;  vd6283a1_light_sensor_setgain(instance, flk_channel, gains[idx]);  res = vd6283a1_light_sensor_getgain(instance, flk_channel, pappliedgain);  return res;}在下方添加函数的定义。
/* * @brief initilize arm rfft library */static void init_fft(arm_rfft_fast_instance_f32 *instance, uint32_t size){  arm_rfft_fast_init_f32(instance, size);}打印增益函数。
/* * @brief normalize, convert and dislay gain  */static void display_gain(uint32_t gain){    uint32_t g = (gain * 100) / 256;    printf( %3lu.%02lun, (unsigned long)g / 100, (unsigned long)(g % 100));}执行fft。
/* * @brief perform fft on the input buffer using arm rfft library */static void perform_fft(arm_rfft_fast_instance_f32 *instance, int16_t *flk, float32_t *ffti, float32_t *ffto, uint32_t size){    uint32_t i;    uint32_t index = 0;    /* copy the adc sampled signal into the fft input buffer     * this allows to convert the data from int16_t to float32_t */    for (i = 0; i < size; i++)    {        ffti[i] = flk[i];    }    /* perform the fft on the input buffer:     * results are packed in a way so that even indexes contain real values     * and odd indexes contain the complex value of each bin.     * therefore the fft_output array contains fft_size / 2 bins */    arm_rfft_fast_f32(instance, ffti, fft_out_tmp, 0);    /* calculate the magnitude for each bin from the temp fft output buffer */    for (i = 0; i < size; i += 2)    {        ffto[index] = complex_abs(fft_out_tmp[i], fft_out_tmp[i+1]);        if (ffto[index] < 0) ffto[index] = 0;        index++;    }}查找峰值频率值。
/* * @brief find peak frequency value */static void find_flk_freq(uint32_t fs, float32_t *ffto, uint32_t *freq, uint8_t skip_dc, uint32_t size){    uint32_t i;    uint32_t res;    uint32_t index_max = 0;    uint32_t limit = size / 2;    float32_t max_value = -1;    /* do not take account of the dc value if the flag skip_dc is set */    skip_dc ? (i = 1) : (i = 0);    /* run through the output array to detect the peak */    for (; i  max_value)        {            index_max = i;            max_value = ffto[i];        }    }    /* convert index of the bin into frequency */    res = (index_max * fs) / size;    /* return the result if the pointer is valid */    if (freq)    {        *freq = res;    }}计算一个复数的绝对值。
/* * @brief compute absolute value of a complex number */static float32_t complex_abs(float32_t real, float32_t complex){  float32_t res;  arm_sqrt_f32(real * real + complex * complex, &res);  return res;}需要添加函数arm_cortexm4lf_math.lib 库包含了一系列数学函数,特别是适用于基于cortex-m4和cortex-m7处理器的浮点运算单元的优化数学例程。这些例程涵盖了常见的数学运算,如信号处理、滤波、变换等。
 arm_math.h 这个头文件包含了cmsis-dsp库的函数声明、宏定义和结构体定义等,可以通过包含这个头文件,使用库中提供的各种数学函数,包括信号处理、滤波、变换等。
 app_als_adc_utils.c功能主要包括启动和停止adc采样,获取采样数据,adc采样速度设置,以及处理相关的硬件中断。
 app_als_adc_utils.h是app_als_adc_utils.c对应头文件。
			
			
       	 	
    	我军无人机装备在角色上华丽变身,应用上多能互补
         	 	
    	eID及RFID存在什么差异
         	 	
    	骨传导耳机哪个牌子好,骨传导耳机品牌推荐
         	 	
    	数字资产量化交易软件开发合约交易所开发
         	 	
    	汇流环:优越性能下的关键电力传输元件
         	 	
    	VD6283TX环境光传感器驱动开发(4)----移植闪烁频率代码
         	 	
    	浅谈rfid射频识别技术的发展历程
         	 	
    	人工智能新基建的情况怎么样
         	 	
    	蓝牙无线运动耳机哪个牌子好、最适合运动的骨传导耳机
         	 	
    	凌力尔特:2012混合动力及电动汽车技术普及率将提升
         
       	 	
    	UDP简易聊天程序搭建方案
         	 	
    	软组织成像不只是核磁共振,X光亦能见微知著
         	 	
    	盘点2013:土洋厂商竞逐LTE  抢占手机芯片市场
         	 	
    	存内计算成为下一代AI芯片的关键 中国半导体的春天未来或将到来
         	 	
    	车载HUD(抬头显示器)的起源和发展
         	 	
    	5至1.8V转换器无需磁性元件即可工作
         	 	
    	LNG储罐裂纹泄漏的治理方法
         	 	
    	新能源汽车产能过剩  代工是否有必要?
         	 	
    	电源管理芯片企业杰华特微电子发生股东变更
         	 	
    	基于BG822CX芯片的MPWC模块的应用研究