在线时间372 小时
UID3135871
注册时间2016-10-9
NXP金币20
TA的每日心情 | 怒 2024-2-5 12:06 |
---|
签到天数: 627 天 [LV.9]以坛为家II
版主
- 积分
- 4429
- 最后登录
- 2024-2-5
|
下面我们来测试下MQ135空气质量传感器。本身这个传感器电路并没有什么可讲的,就是个分压电路。
但是对于测得的电压转浓度这一块,确实比较麻烦,因为规格书未提供任何公式,仅提供了产品的曲线。
我们先来看下MQ135的工作电路:
其中红框部分为正在的工作电路,RL为负载分压电阻,我们测试的就是它两端的电压。
蓝框为电阻丝加入电路,对于我们计时气体没有管理。
模块真实电路,在上面电路上,还加了比较电路,以便超出阀值,便输出TTL报警信号。
我们本次,不使用DOut(比较输出功能),仅连接VCC GND 及Aout(分压电压)。
我们选择P1.31 (ADC的5通道)为Aout的连接引脚。
我们看下规格书给出的浓度曲线:
纵坐标是Rs/Ro,横坐标就是气体浓度。
理论上,我们获取了Rs的值(可通过测试的ADC电压然后通过分压计算出:Rs=(Vc/VRL-1)×RL,VRL为ADC测试的电压,RL根据模块电路为1K)
Ro值表示传感器在100ppm 氨气中的电阻值(根本没有条件测试)。
然后取出对应的几点,然后拟合成曲线方程。
以下来自推算方法,直接参考CSDN博客:
https://blog.csdn.net/weixin_38075894/article/details/111589375?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
模拟方程网站:
http://www.qinms.com/webapp/curvefit/cf.aspx
我直接用了它的结果:
这样我们得到相关的浓度公式:
将Ro,RL,Vcc,Vout代入使用C语言计算得到:
Vout为ADC测得的分压值。RL为1K,VCC为5V。
ppm = pow((3.4880*Ro*Vout)/(5-Vout),(1.0/0.3203));
我们知道Ro是Rs的一个特殊的分值(表示在含100ppm 氨气、20℃/65%RH下的Rs电
阻值)。
既然不确定Ro,为了继续做下去。我们假设当前空气的环境就是Ro的环境。
下面我们写ADC相关代码,测试当前的Rs值,用作Ro:
- #include "adc.h"
- #include "chip.h"
- #include "sys.h"
- #include "delay.h"
- /*********************************************************************************************************
- ** 函数名称: void INT_CHAR(uint32_t s)
- ** 函数功能: 将4位整型数据转变成字符型,便于显示。
- ** 输入参数: 要转换的整型数据:uint32_t s
- ** 输出参数: 转换后的字符型数据存储的在dis[]数组中
- ** 返回值: 无
- *********************************************************************************************************/
- unsigned char dis[7];
- void INT_CHAR(uint32_t s)
- {
-
- dis[0] = s/1000%10 +0x30;
- dis[1] = '.';
- dis[2] = s/100%10 +0x30;
- dis[3] = s/10%10 +0x30;
- dis[4] = s/1%10 +0x30;
- dis[5] = 'V';
- dis[6] = '\0';
- }
- /*********************************************************************************************************
- ** 函数名: ADC_Init (void)
- ** 函数功能: ADC初始化
- ** 输入参数: 无
- ** 输出参数: 无
- ** 返回值: 无
- *********************************************************************************************************/
- void ADC_Init (void) {
- static ADC_CLOCK_SETUP_T ADCSetup;
-
- ADCSetup.adcRate=4;//ADC时钟分配系数5 4+1
- ADCSetup.burstMode=0;
- Chip_ADC_Init(LPC_ADC,&ADCSetup);//使能ADC时钟
- Chip_IOCON_PinMux(LPC_IOCON, 1, 31, IOCON_MODE_INACT, IOCON_FUNC3);//设置P1.31 为ADC的5通道
- Chip_ADC_EnableChannel(LPC_ADC,ADC_CH5,ENABLE);//使能通道5
- Chip_ADC_SetStartMode(LPC_ADC,ADC_START_NOW,ADC_TRIGGERMODE_RISING);//ADC正常工作模式
- }
- /*********************************************************************************************************
- ** 函数名: void ADC_StartCnv (void)
- ** 函数功能: 启动转换
- ** 输入参数: 无
- ** 输出参数: 无
- ** 返回值: 无
- *********************************************************************************************************/
- void ADC_StartCnv (void) {
- Chip_ADC_SetStartMode(LPC_ADC,ADC_START_NOW,ADC_TRIGGERMODE_RISING);//启动转换
- }
- /*********************************************************************************************************
- ** 函数名: void ADC_StopCnv (void)
- ** 函数功能: 停止转换
- ** 输入参数: 无
- ** 输出参数: 无
- ** 返回值: 无
- *********************************************************************************************************/
- void ADC_StopCnv (void) {
- Chip_ADC_SetStartMode(LPC_ADC,ADC_NO_START,ADC_TRIGGERMODE_RISING);// 停止转换
- }
- /*********************************************************************************************************
- ** 函数名: uint16_t ADC_Get (void)
- ** 函数功能: 获取转换值
- ** 输入参数: 无
- ** 输出参数: 无
- ** 返回值: ADC值
- *********************************************************************************************************/
- uint16_t ADC_Get (void) {
- uint16_t val;
- ADC_StartCnv(); //启动转换
- ADC_GetCnv(&val); //获取AD值
- ADC_StopCnv();
- return (val);
- }
- /*********************************************************************************************************
- ** 函数名: uint32_t ADC_GetCnv (void)
- ** 函数功能: 获取转换值
- ** 输入参数: 无
- ** 输出参数: 无
- ** 返回值: ADC值
- *********************************************************************************************************/
- void ADC_GetCnv (uint16_t *adGdr) {
- Chip_ADC_ReadValue(LPC_ADC,5,adGdr);
- }
- //多次采样,并获取平均值
- u16 Get_Adc_Average(u8 times)
- {
- u32 temp_val=0;
- u8 t;
- for(t=0;t<times;t++)
- {
- temp_val+=ADC_Get();
- delay_ms(5);
- }
- return temp_val/times;
- }
复制代码 我们在main函数里面,一直输出当前测的的电压(理论上要等48小时以上,我们做实验,直接忽略):
- ADC_Data=Get_Adc_Average(8);
-
- ADC_Data = (ADC_Data * 3300)/4095;
- INT_CHAR(ADC_Data); // 整型数据转换成字符型
- LCD_DisplayAsciiString (30,60,dis,16,Black,White);
- printf("adc=%s\r\n",dis);
复制代码 我们查看串口输出,在0.78V左右。我们算出此时的Rs,Rs=(5/0.78-1)×1K=5.41K。我们把这个值当作Ro,即Ro=5.41K
我们带入公式:
ppm = pow((3.4880*Ro*Vout)/(5-Vout),(1.0/0.3203));
ppm = pow((3.4880*5.41*Vout)/(5-Vout),(1.0/0.3203));
我们把它加到while循环里,查看输出:
- //tmp1=(3.4880*Ro*ADC_Data/1000.0)/(5.0-ADC_Data/1000.0);
- tmp1=(3.4880*5.41*ADC_Data/1000.0)/(5.0-ADC_Data/1000.0);
- tmp2=(1.0/0.3203);
- ppm = pow(tmp1,tmp2);
-
- sprintf(tmp, "%.4f", ppm);
- printf("ppm=%s\r\n",tmp);
-
- delay_ms(5000);
复制代码 下载,查看:
好了,MQ135空气质量检测就到这了。其中Ro取值仅是实验,不准,仅供参考!
水了一篇,谢谢观看~
|
|