#define WINDOW_SIZE 32
int movingAverage(int newSample)
{
static int samples[WINDOW_SIZE] = {0};
static int index = 0;
static int sum = 0;
sum -= samples[index];
samples[index] = newSample;
sum += newSample;
index = (index + 1) & (WINDOW_SIZE - 1);
return sum >> 5;
}
void pm25_task() {
// 自己电路接的LED Pin,我这是PA4
// 按照下图1,2,需要10ms一个脉冲驱动LED,等280us后可以测得输出电压
// ADC增加滑动平均
// 计算PM2.5是通过图3的曲线拟合
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
delayus(280);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 50);
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
adc_value = HAL_ADC_GetValue(&hadc1); //获取AD值
}
adc_value = movingAverage(adc_value);
delayus(40);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
// 10ms interrupt
if(htim->Instance == TIM2){
pm25_task();
}
}
float cal_pm25(float voltageRead)
{
if (voltageRead < 0.9)
{
voltageRead = 0.9;
}
else if (voltageRead > 3.4)
{
voltageRead = 3.4;
}
return 180 * voltageRead - 162;
}
float pm25 = 0;
pm25 = adc_value * 3.3 / 4096;
pm25 = cal_pm25(pm25);