一 项目需求
这个小项目是DTU的同学拜托我帮忙做的,就是使用光电探测器测量出光的强度,并将测量值显示在屏幕上面。光电探测器使用的是Thorlabs的PDAPC1,这是一款增益可调的传感器,输出电压信号。屏幕选用市面上常见的0.96寸OLED屏,IIC通讯。需求分析清楚了,整个项目的方案也就明了。我们使用单片机ADC测量传感器的输出电压,计算出相应的光强值并通过IIC通讯显示在屏幕上。
二 硬件
原理图
PCB图与实物图
整个电路设计还是比较常规的,但是用于给光强传感器供电的±12V稳压电路设计还是值得探讨的。
很多运放电路采用的是双电源供电,正电源比较好解决,对于负电源,较为常见的方案是使用电荷泵将正压转换成负压,常用的芯片是ICL7660,使用电荷泵的缺点是输出电流较小(但用于一般的运放电路也并无多大问题)。
这里我采用的方案是将TPS5430稳压电路的输出点接GND,接地点接输出,这样原本接地点的电压就是-12V了,核心要义就是:电压是相对的
三 软件
软件中使用的单片机硬件资源有ADC中断,定时器中断,IIC使用的是软件模拟IIC。为了使用电压采样值更加稳定,这里使用了均值滤波的方式。
程序流程图
这里PO出ADC均值滤波的程序。ADC每完成一次转换,就触发一次中断,在中断回调函数中将采样值存放在数组里面,当达到指定采样次数的时候,就将标志位置1,在while(1)循环中对刚采样的一组电压值进行平均滤波。
#define MAX_sample 10
#define min_size 3
#define max_size 3
uint16_t ADC_Value[MAX_sample];
uint16_t ADC_Value_Tmp[MAX_sample];
uint16_t ADC_Value_Display;
uint8_t pd=0;
int main(void)
{
HAL_ADCEx_Calibration_Start(&hadc1); //AD校准
HAL_ADC_Start_IT(&hadc1);
while(1)
{
if(ADC_Flag)
{
ADC_Data_Handle();
ADC_Flag=0;
}
}
}
void ADC_Data_Handle(void)
{
uint32_t sample_sum=0;
/*中位值平均滤波*/
//.............排序
for(uint8_t i=0;i<MAX_sample-1;i++)
{
uint16_t temp;
for(uint8_t j=0;j<MAX_sample-1;j++)
{
if(ADC_Value_Tmp[j]>ADC_Value_Tmp[j+1])
{
temp=ADC_Value_Tmp[j];
ADC_Value_Tmp[j]=ADC_Value_Tmp[j+1];
ADC_Value_Tmp[j+1]=temp;
}
}
}
//.............计算平均值
for(uint8_t k=min_size;k<MAX_sample-max_size;k++)//去掉min_size个最小值、max_size个最大值
{
sample_sum+=ADC_Value_Tmp[k];
}
//...............计算实际电压值
ADC_Value_Display=(sample_sum/(MAX_sample-min_size-max_size))*3300/4095;
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
ADC_Value[pd++]=HAL_ADC_GetValue(&hadc1);
if(pd==MAX_sample) //达到预设的最大采样值
{
pd=0;
if(ADC_Flag==0)
{
ADC_Flag=1;
memcpy(ADC_Value_Tmp,ADC_Value,sizeof(ADC_Value));
}
}
}
四 总结
项目总体难度不大,每一次项目的梳理都是对知识的总结,只有这样才能进步的更快。项目源码github链接:HaoJosephWen/Code-of-blog (github.com)