STM32、LM2904和ESP8266构建的噪声预警系统(续篇)
由于前阵子帮我哥弄毕设,晚更新了一阵子,感觉不是很有意思,后面就没有更新的想法了,本来想着可以做大一点,加入网页可以增加新的元素,语音播报内容的更新,比如对噪音的记录以及语音的识别,然后部署到云服务器(好像还有3个月过期,一直闲置)等等。
一、 模拟量分贝检测LM2904介绍
顾名思义,它是一款输出模拟量的传感器,该模块对震动很敏感,测量时要放在平稳的位置。stm32的adc全称为Analog(模拟量)-to-Digital (数字量)Converter,就是把模拟信号转化为数字信号,使用这种传感器的一般步骤为将ADC模块与某引脚相连,再用该引脚去接入所要测试的地方,ADC模块便可以经过换算得到所要测试部位的电位。模拟量和电位是线性关系,单片机的adcADC是12位逐次逼近型的模拟数字转换器,故其值为0~4095(即000000000000 ~ 111111111111),由于lm2904的供电电压为5v,故输出模拟值为4095时,电压即为5v,按照比例即可通过不同噪声得到输出不同的电压。
得到电压怎么计算出分贝呢,这俩个词语看似毫不相关,卖家提供了一个算法,由于本人c语言基础确实较差,无法将公式写出(咳咳,实际上看了一下就溜了),需要算法可以私聊一下。或者第二种思路,利用excel表格里面那个函数?忘记叫什么了,就是利用数据推公式!对对对!我看到某宝店铺有一个近似计算公式如下:
db=输出信号/(供电电压-1.7)*100+30
二、代码参考
stm32 adc初始化函数用一下正点原子哥的代码,注释乱码了,有需要可以去原子哥那里下载。
#include "adc.h"
#include "delay.h"
//
//±¾³ÌÐòÖ»¹©Ñ§Ï°Ê¹Óã¬Î´¾×÷ÕßÐí¿É£¬²»µÃÓÃÓÚÆäËüÈκÎÓÃ;
//ALIENTEK miniSTM32¿ª·¢°å
//ADC ´úÂë
//ÕýµãÔ×Ó@ALIENTEK
//¼¼ÊõÂÛ̳:www.openedv.com
//ÐÞ¸ÄÈÕÆÚ:2012/9/7
//°æ±¾£ºV1.0
//°æÈ¨ËùÓУ¬µÁ°æ±Ø¾¿¡£
//Copyright(C) ¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾ 2009-2019
//All rights reserved
//
//³õʼ»¯ADC
//ÕâÀïÎÒÃǽöÒÔ¹æÔòͨµÀΪÀý
//ÎÒÃÇĬÈϽ«¿ªÆôͨµÀ0~3
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //ʹÄÜADC1ͨµÀʱÖÓ
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ÉèÖÃADC·ÖƵÒò×Ó6 72M/6=12,ADC×î´óʱ¼ä²»Äܳ¬¹ý14M
//PA1 ×÷ΪģÄâͨµÀÊäÈëÒý½Å
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //Ä£ÄâÊäÈëÒý½Å
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //¸´Î»ADC1,½«ÍâÉè ADC1 µÄÈ«²¿¼Ä´æÆ÷ÖØÉèΪȱʡֵ
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC¹¤×÷ģʽ:ADC1ºÍADC2¹¤×÷ÔÚ¶ÀÁ¢Ä£Ê½
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //Ä£Êýת»»¹¤×÷ÔÚµ¥Í¨µÀģʽ
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //Ä£Êýת»»¹¤×÷ÔÚµ¥´Îת»»Ä£Ê½
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //ת»»ÓÉÈí¼þ¶ø²»ÊÇÍⲿ´¥·¢Æô¶¯
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADCÊý¾ÝÓÒ¶ÔÆë
ADC_InitStructure.ADC_NbrOfChannel = 1; //˳Ðò½øÐйæÔòת»»µÄADCͨµÀµÄÊýÄ¿
ADC_Init(ADC1, &ADC_InitStructure); //¸ù¾ÝADC_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ»¯ÍâÉèADCxµÄ¼Ä´æÆ÷
ADC_Cmd(ADC1, ENABLE); //ʹÄÜÖ¸¶¨µÄADC1
ADC_ResetCalibration(ADC1); //ʹÄܸ´Î»Ð£×¼
while(ADC_GetResetCalibrationStatus(ADC1)); //µÈ´ý¸´Î»Ð£×¼½áÊø
ADC_StartCalibration(ADC1); //¿ªÆôADУ׼
while(ADC_GetCalibrationStatus(ADC1)); //µÈ´ýУ׼½áÊø
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //ʹÄÜÖ¸¶¨µÄADC1µÄÈí¼þת»»Æô¶¯¹¦ÄÜ
}
//»ñµÃADCÖµ
//ch:ͨµÀÖµ 0~3
u16 Get_Adc(u8 ch)
{
//ÉèÖÃÖ¸¶¨ADCµÄ¹æÔò×éͨµÀ£¬Ò»¸öÐòÁУ¬²ÉÑùʱ¼ä
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADCͨµÀ,²ÉÑùʱ¼äΪ239.5ÖÜÆÚ
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //ʹÄÜÖ¸¶¨µÄADC1µÄÈí¼þת»»Æô¶¯¹¦ÄÜ
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//µÈ´ýת»»½áÊø
return ADC_GetConversionValue(ADC1); //·µ»Ø×î½üÒ»´ÎADC1¹æÔò×éµÄת»»½á¹û
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);//¶à´Îµ÷ÓÃȡƽ¾ùÖµ
delay_ms(5);
}
return temp_val/times;
}
main函数如下:
记得提前初始化一下adc以及定义变量
adcx=Get_Adc_Average(ADC_Channel_1,10);
temp=(float)adcx*(3.3/4096)/3.3*100+30;
adcx=temp;
printf("%d",adcx);
delay_ms(100);
if(adcx>80)
{
location[count]=adcx;//location是自己定义的一维数组
count++; //
if(count==4) //噪声填满5次,开始警告
{
count=0; //清空
LED0=1; //灯亮,也可以接一下蜂鸣器,达到预警效果即可,需要发出声音可以用web,小爱同学或者其他播报器
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
delay_ms(1000);
LED0=0; //没必要一直响
}
printf("%d ´超过80DB\r\n",adcx);
}
}
建议:计算采样的平均数,达到5次开始预警也可以保留,但是得写一个计数器,当数组没填满,且里面有相邻时间大于预期的时间(结合现实,不能说早上吵到了,晚上再吵到也算累计五次),清空数组(重置),记得修改延迟频率!。
长太息以掩涕兮,哀民生之多艰。
余虽好修姱以鞿羁兮,謇朝谇而夕替。
既替余以蕙纕兮,又申之以揽茝。
亦余心之所善兮,虽九死其犹未悔。
怨灵修之浩荡兮,终不察夫民心。
众女嫉余之蛾眉兮,谣诼谓余以善淫。
固时俗之工巧兮,偭规矩而改错。
背绳墨以追曲兮,竞周容以为度。
忳郁邑余侘傺兮,吾独穷困乎此时也。
宁溘死以流亡兮,余不忍为此态也。
鸷鸟之不群兮,自前世而固然。
何方圜之能周兮,夫孰异道而相安?
屈心而抑志兮,忍尤而攘诟。
伏清白以死直兮,固前圣之所厚。