工作时间 周一至周六 :8:30-17:00 联系方式 电话:021-51360000 地址:浦东新区金吉路778号1幢703 email:embedchina@163.com 客服热线:18717992104 技术咨询:17811901598 |
粉尘仪开发设计说明书浏览数:758次
粉尘仪开发设计说明书 1引言 本仪器是以激光为光源的光散射式快速测尘仪,有多种切割器可供选择,内置滤膜采样装置,可在连续监测空气中颗粒物的同时收集粉尘样品,以便进行成份分析和运用滤膜称重法求出质量浓度转换系数K值。PMS5XXXS 系列是一款可以同时监测空气中颗粒物浓度和甲醛浓度的二合一传感器。其中颗粒物浓度的监测基于激光散射原理,可连续采集并计算单位体积内空气中不同粒径的悬浮颗粒物个数,即颗粒物浓度分布,进而换算成为质量浓度。甲醛浓度的监测基于电化学原理,具有高精度、高稳定性的特点。颗粒物浓度数值和甲醛浓度数值合并以通用数字接口形式输出。本传感器可嵌入各种与空气质量监测和改善相关的仪器设备,为其提供及时准确的浓度数据。本仪器适用于公共场所可吸入颗粒物浓度的快速测定、中央空调排气口PM10和PM2.5浓度检测、工矿企业生产现场等劳动卫生方面粉尘浓度检测、环境保护领域可吸入尘浓度的监测,以及用于空气净化器净化效率评价等。 本设计说明书的主要目的是为本产品相关的设计人员提供本控制软件的设计思路和代码的解释,从而可以对现有的代码进行维护和进一步完善,以及在现有的基础上增加新的功能。 项目背景: 本项目主要解决检测空气中粉尘的浓度(主要是PM10和PM2.5浓度),为客户提供及时准确的浓度数据。 定义: u16 PM25value_A——定义瞬时PM2.5的值 N 50——每通道采50次 M 4 ——为4个通道 Currentzeropoint——当前零点 u8 recbufferIndex——rec缓冲器的索引 workMode——工作模式 AD_Value[N][M]——用来存放ADC转换结果,也是DMA的目标地址 After_filter[M]——用来存放求平均值之后的结果
任务概述 PMS5XXXS 系列是一款可以同时监测空气中颗粒物浓度和甲醛浓度的二合一传感器。其中颗粒物浓度的监测基于激光散射原理,可连续采集并计算单位体积内空气中不同粒径的悬浮颗粒物个数,即颗粒物浓度分布,进而换算成为质量浓度。甲醛浓度的监测基于电化学原理,具有高精度、高稳定性的特点。颗粒物浓度数值和甲醛浓度数值合并以通用数字接口形式输出。本传感器可嵌入各种与空气质量监测和改善相关的仪器设备,为其提供及时准确的浓度数据。 需求概述 本仪器要适用于公共场所可吸入颗粒物浓度的快速测定、中央空调排气口PM10和PM2.5浓度检测、工矿企业生产现场等劳动卫生方面粉尘浓度检测、环境保护领域可吸入尘浓度的监测,以及用于空气净化器净化效率评价等。 2.2 条件与限制 PMS5003 需要 5V 供电,这是因为风机需要 5V 驱动。但其他数据通讯和控制管脚均需要 3.3V 作为高电平。因此与之连接通讯的主板 MCU 应为 3.3V 供电。如果主板 MCU 为 5V 供电,则在通讯线(RXD、TXD)和控制线(SET、RESET)上应当加入电平转换芯片或电路。SET 和 RESET 内部有上拉电阻,如果不使用,则应悬空。PIN7 和 PIN8 为程序内部调试用,应用电路中应使其悬空。应用休眠功能时应注意:休眠时风扇停止工作,而风扇重新启动需要至少 30秒的稳定时间,因此为获得准确的数据,休眠唤醒后传感器工作时间不应低于 30 秒。 总体设计 主要特性 激光散射原理实现精准测量 零错误报警率 实时响应并支持连续采集 最小分辨粒径 0.3? m 全新专利结构,六面全方位屏蔽,抗干扰性能更强 进出风口方向可选,适用范围广,用户无需再进行风道设计 可实时输出甲醛监测数据 工作原理 本传感器采用激光散射原理。即令激光照射在空气中的悬浮颗粒物上产生散射,同时在某一特定角度收集散射光,得到散射光强随时间变化的曲线。进而微处理器利用基于米氏(MIE)理论的算法,得出颗粒物的等效粒径及单位体积内不同粒径的颗粒物数量。传感器各功能部分框图如图 1 所示 甲醛监测功能采用电化学原理实现,加入数据处理算法,所获得的数据稳定、精确。 技术指标 注:颗粒物浓度一致性数据为通讯协议中的数据 2(见附录 A)测量环境条件为 20℃,湿度 50% 数字接口定义 图2 接口示意图
型号定义 尺寸结构 单位:mm 串口1初始化 void USART1_Configuration(void) { USART_InitTypeDef USART_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 |RCC_APB2Periph_USART1, ENABLE ); USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; /* Configure the USART1 synchronous paramters */ USART_ClockInit(USART1, &USART_ClockInitStructure); USART_ClockInit(USART2, &USART_ClockInitStructure); USART_ClockInit(USART3, &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; /* Configure USART1 basic and asynchronous paramters */ USART_Init(USART1, &USART_InitStructure); USART_Init(USART2, &USART_InitStructure); USART_Init(USART3, &USART_InitStructure);
USART_ClearFlag(USART1, USART_IT_RXNE); USART_ClearFlag(USART2, USART_IT_RXNE); USART_ClearFlag(USART3, USART_IT_RXNE); USART_ITConfig(USART1,USART_IT_RXNE, ENABLE); USART_ITConfig(USART2,USART_IT_RXNE, ENABLE); USART_ITConfig(USART3,USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); USART_ITConfig(USART1, USART_IT_ORE, ENABLE); USART_ClearFlag(USART1, USART_FLAG_TC); USART_ClearFlag(USART2, USART_FLAG_TC); USART_ClearFlag(USART3, USART_FLAG_TC); USART_Cmd(USART1, ENABLE); USART_Cmd(USART2, ENABLE); USART_Cmd(USART3, ENABLE); }
当时钟低电平时活动,这时时钟从第二个边沿进行数据捕获,直到捕获到最后一位数据的时钟时脉冲不从SCLK输出,做完此活动后进行时钟参数初始化设置。我们设定此设备的工作波特率为9600。 发送接收到的数据 void mputs_1(char *p,u8 i) { while(i--) { /* Send one byte from USARTy to USARTz */ USART_SendData(USART1, *p++);
/* Loop until USARTy DR register is empty */ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) { } } } u16 GetPumpSumTime() { return parameter.totalpumptime; } u16 GetLaserSumTime() { return parameter.lasertotaltime; } s16 GetSPAN() { return parameter.span25; } void StopDetect() { workMode=3; } void StartDetect() { workMode=4; } void SetPumpSpeed(u16 sp) { PumpSpeedbak=sp; parameter.pumpspeed=sp; saveParameterToFlash(); }; void SetCorrectMode(){ //correct mode gtime=0; // clear the time counter ,gtime is count in mS workMode=1;//setting the correct MODE tag } void PkgResponse(char *p,u8 num) { u32 i=2000; PB9_H; //max485 DE=1 transmit mode
mputs_1(p,num); while(i--); PB9_L; //max485 DE=0 receive mode } 以上的代码用到了以下参数: RS-485通信接收命令 PM2.5 CPM值发送请求
PM10 CPM测定结果请求
SPM CPM测定结果请求 /1000
测定停止请求
1.1.4.1测定开始
泵运行累计时间发送请求
泵运行电流发送请求
泵运行转速发送请求
泵运行转速设定请求
激光运行累计时间发送请求 小时为单位
BG测定开始请求
BG测定停止请求
BG测定结果请求
SPAN测定开始请求
SPAN测定停止请求
SPAN测定结果请求
K值设定请求 /1000
K值查询请求
1.1.22 校正模式
命令响应 CPM值发送请求响应
CPM值测定周期设定响应
测定停止请求响应
泵运行累计时间发送请求响应
激光运行累计时间发送请求响应
BG测定开始请求响应
BG测定停止请求响应
BG测定结果发送请求响应
SPAN测定开始请求响应
SPAN测定停止请求响应
SPAN测定结果发送请求响应
* DATA1、DATA2 采用HEX (16进制) 数值。 255时DATA1为00H、DATA2为FFH。 * DATA 为00H或01H,00H: 失败 01H: 成功。 读取各参数值,按照新的数据计算CRC,做出对比,得出相应结果 int ParsePkg(PKG pkg) { int temp; char responsebuffer[8]; if(pkg.DEVaddr==MACHINE_ID) { if(pkg.function==0x03) { if(pkg.MEMaddr==0x000D) temp= GetPM2point5(1); else if(pkg.MEMaddr==0x000C) temp= GetPM10(1); else if(pkg.MEMaddr==0x0001) temp= GetSPM(); else if(pkg.MEMaddr==0x0004) temp= GetPumpspeed(); else if(pkg.MEMaddr==0x0014) temp=GetPumpCurrent(); else if(pkg.MEMaddr==0x0024) temp=GetPumpSumTime(); else if(pkg.MEMaddr==0x0005) temp=GetLaserSumTime(); else if(pkg.MEMaddr==0x0007) temp=GetBG() ; else if(pkg.MEMaddr==0x0009) temp=GetSPAN() ; else if(pkg.MEMaddr==0x000b) temp=GetKvalue(); responsebuffer[0]=pkg.DEVaddr; responsebuffer[1]=pkg.function; responsebuffer[2]=0x02; responsebuffer[3]=temp>>8; responsebuffer[4]=temp; pkg.Pcrc= GetCRC((char *)&responsebuffer,5); responsebuffer[6]=pkg.Pcrc>>8; responsebuffer[5]=pkg.Pcrc; PkgResponse(responsebuffer,7); } if(pkg.function==0x06) //config memory { if(pkg.MEMaddr==0x0003) StopDetect(); else if(pkg.MEMaddr==0x0033) StartDetect(); else if(pkg.MEMaddr==0x0004) SetPumpSpeed(pkg.Mdata);
else if(pkg.MEMaddr==0x0008) SPANOnOff(pkg.Mdata); else if(pkg.MEMaddr==0x000A) SetKvalue(pkg.Mdata); else if(pkg.MEMaddr==0x000F) SetCorrectMode(); //correct MODE
responsebuffer[0]=pkg.DEVaddr; responsebuffer[1]=pkg.function; responsebuffer[2]=pkg.MEMaddr>>8; responsebuffer[3]=pkg.MEMaddr; responsebuffer[4]=pkg.Mdata>>8; responsebuffer[5]=pkg.Mdata; pkg.Pcrc= GetCRC((char *)&responsebuffer,6); responsebuffer[7]=pkg.Pcrc>>8; responsebuffer[6]=pkg.Pcrc; PkgResponse(responsebuffer,8);
} } else return -1; } static u8 uart1_rec_buf[32]; static u8 uart2_rec_buf[32]; static u8 uart3_rec_buf[32]; void USART1_IRQHandler(void) {
static u16 dat; if (USART_GetITStatus(USART1, USART_IT_ORE) == SET) { USART_ClearITPendingBit(USART1,USART_IT_ORE); USART_ReceiveData( USART1 );
} if ( USART_GetITStatus( USART1, USART_IT_IDLE ) != RESET ) { USART_ClearITPendingBit(USART1,USART_IT_IDLE); recbufferIndex=0; uart1received=1; USART_ReceiveData( USART1 ); USART_DR) } if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { /* Clear the USART1 Receive interrupt */ USART_ClearITPendingBit(USART1, USART_IT_RXNE); dat = USART_ReceiveData( USART1 ); uart1_rec_buf[recbufferIndex++]=dat; } } 此时是打开阀门,让空气流入,检测其中PM2.5和PM10的浓度值,在检测是仪器要做的是响应帧,匹配设备地址 0x01 同时要求crc校验正常,此时读取PM2.5、PM10、SPM 、泵速度、泵电流、泵累计时间、激光累计时间、BG结果和SPAN结果,然后进行K值的查询,再重新设定下相关功能值,然后按照新的数据计算CRC后向主机发送响应,向主机发送响应后,停止测定,BG和SPAN,然后进行K值的设定,再重新设定下相关功能值后按照新的数据再次计算CRC,如果地址不是自己或者crc校验错误,直接退出。 int main(void) { static float temp; PKG pkg; static unsigned short c1; uart1received=0; //=================================== GPIO_Configuration(); RCC_Configuration(); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, DISABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); PB5_H;
NVIC_Configuration(); GetParameterFromFlash(); if(parameter.totalpumptime==0xffff) { parameter.k=1; parameter.span25=0; parameter.span10=0; parameter.bg25=0; parameter.bg10=0; parameter.totalpumptime=0; parameter.lasertotaltime=0; parameter.pumpspeed=0; savetag=1; } PC8_L;//optocouple open
PB9_L; //max485 DE=0 receive mode TIM1_Configuration() ; PWMTimeinit(); GetParameterFromFlash(); detectspeed_init(); /* Disable FSMC only for STM32 High-density and XL-density devices */ USART1_Configuration(); /* //ConfigSensor3Pause(); get_advalue(); currentzeropoint=advalue[0];//get the current zero pint value // mputs_1("\n please input the v0 value(example 0.01): "); while(1)
{ PC3_H;//working light if(savetag){ saveParameterToFlash(); savetag=0; } get_advalue(); temp= GetPumpCurrent(); //if(temp<150) // CP1_Freq=0; //cp1 will stop count if speed too low if(uart1received){ recbufferIndex=0; uart1received=0; c1 = crc16(uart1_rec_buf, 6); if((c1>>8==uart1_rec_buf[7])&&((c1&0x00ff)==uart1_rec_buf[6])) { pkg.DEVaddr=uart1_rec_buf[0]; pkg.function=uart1_rec_buf[1]; pkg.MEMaddr=uart1_rec_buf[2]<<8|uart1_rec_buf[3]; pkg.Mdata=uart1_rec_buf[4]<<8|uart1_rec_buf[5]; pkg.Pcrc=uart1_rec_buf[7]<<8|uart1_rec_buf[6]; ParsePkg(pkg) ; } else ;//recbufferIndex=0 ; //reset receive buffer index } if(workMode==1) //1 denotes correct MODE { //Correct MODE
ctm= correctMode(); } else if(workMode==3) //3 denotes stop detect {
PC0_L; //magnet valve 1 off PC1_L; //magnet valve 2 off PC2_L; //magnet valve 3 off PC4_L;//PMS5003 SET=0 sensor sleep PC6_L; //PMS5003 SET=0 sensor sleep SetMotorSpeed(0); laser_running_tag=0; } else if(workMode==4) //4 denotes work detect) {//Normal working MODE PC0_H; //magnet valve 1 on SetMotorSpeed(parameter.pumpspeed);// the pump power on PC4_H;//PMS5003 SET=1sensor A PC1_L;//magnet valve NO.2 off PC2_L; //magnet valve 3 off PC6_L; //close the second sensor
PM25value_A=uart3_rec_buf[6]<<8|uart3_rec_buf[7]; //keep get the sensor value PM10value_A=uart3_rec_buf[8]<<8|uart3_rec_buf[9]; laser_running_tag=1; } } } 这段代码是主要的工作代码,它表示电磁阀1开启,电磁阀2和电磁阀3保持关闭状态。 然后开启气泵电源,开启传感器1电源。要预热30秒以上。开始检测空气中粉尘浓度后每一秒发送一个数据读取请求,采集60个数据,做平均计算,数据即为分钟均值,存储在相应位置。当接收到上位机的数据请求,根据请求,发送相应数据。SPM CPM数据为PM10 CPM数据与K值的乘积。当打开电磁阀3,向传感器1、传感器2和气泵供应电源保持此状态1分钟以上。关闭气泵15秒左右之后,进行1分钟测定如果测试BG数据大于10则重新进行步骤以上操作,如果测试BG数据小于等于10,则进行下一步;关闭电磁阀3。打开电磁阀1,电磁阀2。打开气泵。15秒后开始测定传感器1和传感器2的数据。连续测试3分钟。根据传感器2的分钟均值对传感器2的分钟均值数据进行调整。进行1分钟的传感器1和传感器2的数据测定。 如果两者的误差在10%以内,调整完成,仪器进入测量模式。如果两者的误差在10%以上,重复所需步骤。如果3次步骤17都不能达到10%的误差,放弃调整,输出测试失败状态。测量模式,关闭电磁阀2和传感器2,电磁阀1和传感器1保持工作状态,电磁阀3关闭。 输出结果 1.主要输出为单位体积内各浓度颗粒物质量以及个数,其中颗粒物个数的单位体积为 0.1 升,质量浓度单位为:微克/立方米。 2.输出分为主动输出和被动输出两种状态。传感器上电后默认状态为主动输出,即传感器主动向主机发送串行数据,时间间隔为 200~800ms,空气中颗粒物浓度越高,时间间隔越短。主动输出又分为两种模式:平稳模式和快速模式。在空气中颗粒物浓度变化较小时,传感器输出为平稳模式,即每三次输出同样的一组数值,实际数据更新周期约为 2s。当空气中颗粒物浓度变化较大时,传感器输出自动切换为快速模式,每次输出都是新的数值,实际数据更新周期为 200~800ms。 甲醛浓度输出:单位体积内甲醛质量浓度,单位为毫克/立方米。 典型输出特性 纵坐标单位μ g/m³,横坐标单位:次。 温度与一致性的对应关系 使用说明书 打开阀门,让空气流入,空气经过过滤后检测其中PM2.5和PM10的浓度值,电磁阀1开启,电磁阀2和电磁阀3保持关闭状态。 然后开启气泵电源,开启传感器1电源。要预热30秒以上。开始检测空气中粉尘浓度后每一秒发送一个数据读取请求,采集60个数据,做平均计算,数据即为分钟均值,存储在相应位置。当接收到上位机的数据请求,根据请求,发送相应数据。SPM CPM数据为PM10 CPM数据与K值的乘积。当打开电磁阀3,向传感器1、传感器2和气泵供应电源保持此状态1分钟以上。关闭气泵15秒左右之后,进行1分钟测定如果测试BG数据大于10则重新进行步骤以上操作,直到测试结果BG数据小于等于10,则进行下一步;关闭电磁阀3。打开电磁阀1,电磁阀2。打开气泵。15秒后开始测定传感器1和传感器2的数据。连续测试3分钟。根据传感器2的分钟均值对传感器2的分钟均值数据进行调整。进行1分钟的传感器1和传感器2的数据测定。 如果两者的误差在10%以内,调整完成,仪器进入测量模式。如果两者的误差在10%以上,重复所需步骤。如果3次步骤17都不能达到10%的误差,放弃调整,输出测试失败状态。测量模式,关闭电磁阀2和传感器2,电磁阀1和传感器1保持工作状态,电磁阀3关闭。 在使用时请注意使用安全事项以及注意事项,务必在安全的有效的环境下使用。 |