|
本帖最后由 我是吃货 于 2022-9-28 08:47 编辑
传统的离心泵工况诊断方法,传感器安装不便,诊断成本较高,实际应用困难。本文由开发者对通过离心泵工况的机理进行了研究,并设计研发了相应的离心泵工况诊断系统,从系统功能实现,系统硬件总体设计,系统软件总体设计三方面对离心泵工况诊断系统的整体嵌入式架构进行了设计。
(1)系统功能实现
1、能够对离心泵驱动电机各相输入电流进行频谱绘制。系统能向操作人员实时展示离心泵驱动电机各相输入电流在 0~650Hz频带内的频谱。
2、能够对各项离心泵工况诊断指标进行准确计算。系统能对离心泵驱动电机定子电流均方根指标、脉冲因子指标等多项工况诊断指标进行实时计算。同时,系统应能够对离心泵驱动电机输入功率、电网工频进行实时监测。并对各项参数的计算及监测误差控制在低于1.8%的阈值内。
3、实现信息交互。系统下位机应能够与 TFTLCD 屏以及移动端离心泵工况诊断 APP 两个平台之间进行诊断信息交互。
(2)系统硬件设计
根据系统的功能设计指标,本文在系统硬件上设计了 MCU 核心控制模块、AD 采集模块、三相电参数监测模块、内存扩展模块、数据存储模块、信息交互模块、系统供电电源模块共计 7 大功能模块,系统总体框架图如图所示。
其中系统信息交互模块实现了系统诊断信息的实时传输与共享,包括屏显模块、云端通信模块两部分。通过信息交互模块,诊断信息被分别发送至了下位机端和移动端APP,操作人员可以根据需要自行选择是进行现场诊断还是进行远程诊断。信息交互模块的功能框架图如下所示:
屏显模块,负责将诊断信息直接呈现在显示屏上。基于机智云平台设计的云端通信模块,则负责将诊断信息通过机智云服务器发送至操作人员的移动 APP 上。云端通信模块的功能框架如下所示:
WiFi模块对系统计算所得的诊断信息进行封装后传至互联网,并通过互联网上传至机智云服务器,移动端离心泵工况诊断 APP 通过与机智云服务器通信实时获取离心泵的工况诊断信息。
云端通信模块中的WiFi模块负责系统的配置入网。WiFi模块的性能对通信质量起着重要的影响作用。综合考虑传输速率、距离、功耗和接受灵敏度这四方面因素,选用乐鑫 esp8266WiFi 模组作为系统云端通信模块的WiFi模块,其原理图和实物图分别如下所示。
离心泵工况诊断系统样机的 PCB 设计图和实物照片分别如下所示。
(3)系统软件总体设计
在软件设计上,系统对电流信号的采集通过单片机的 ADC 功能,DMA 功能,通用定时器定时功能实现;系统对电流信号的时频转换和对诊断指标的计算通过单片机的 DSP 功能实现;三相电参数监测模块与 MCU 核心控制模块之间的信息交互通过单片机的 SPI 通信功能实现;诊断信息的人机交互通过单片机的 FSMC 驱动功能,ESP8266 芯片的 WIFI入网功能以及单片机的串口通信功能实现;系统内存的扩展通过单片机的 FSMC 驱动功能实现;诊断信息的存储通过单片机的 SDIO 驱动功能实现。
系统初始化在对 MCU 核心控制模块进行复位操作后,程序将从 main 函数出发,首先执行延时函数初始化,单片机 GPIO 引脚初始化,中断嵌套初始化,串口初始化操作,然后依照HARDWARE 中的子文件,依次完成对 AD 采集模块,三相电参数监测模块,内存扩展模块,数据存储模块,信息交互模块的初始化操作,最后完成对 FFT 运算相关参数的初始化,系统初始化程序的逻辑实现流程如下:
信息交互开发信息交互程序包括两方面,一是屏显模块的信息显示程序,二是系统下位机与移动 APP之间的通信程序。屏显模块的信息显示程序较简单,MCU 核心控制模块将屏显模块视为外部 SRAM 设备,通过 FSMC 对其进行驱动,完成显示。离心泵工况诊断系统的屏显界面如下所示:
平台交互开发系统与移动 APP 之间的远程通信是基于第三方云端服务器实现的,系统通过 WiFi 模块接入互联网后,借助于第三方云端服务器与移动端 APP 之间进行数据传递。可以理解为系统在下位机端、云端、移动端三者之间构筑了一个相对完整的物联网信息交互框架。
由于机智云平台可以为用户提供从设备接入到产品运营管理的整个生命周期的服务。本文选用机智云作为系统云端通信的开发平台。基于机智云服务器的云端通信框架示意图如下所示:
云端通信是在设备端、云端、移动客户端三者之间进行的。设备端即诊断系统下位机,在软件上,设备端的云端通信功能要通过 GAgent 应用程序实现。GAgent 是为设备端接入机智云提供的嵌入式固件系统。
在离心泵工况诊断系统中,GAgent 在 ATK-ESP8266 WiFi模块上运行,负责在设备端、云端、移动客户端三者之间搭建以数据点为媒介的信息交互桥梁。在软件上,移动客户端基于 SDK 环境建立了与云端及设备端通信的 API 接口。
设备端与云端,移动客户端与云端之间传输的信息被封装成数据点格式,而 MCU 核心控制模块在云端通信过程中主要负责数据点与系统实际动作之间的对应转换。三端协同工作,确保了物联网中的信息通畅。 移动客户端和设备端之间借助机智云平台进行通信。
(4)云端通信的具体开发步骤如下:
创建产品:在机智云开发者中心官网中选择“创建新产品”,并完成产品的属性配置。具体地,本文在开发过程中,根据诊断系统的应用领域选择产品分类为“安防,监控”类,将产品名称命名为“离心泵工况诊断系统 V1”,选择技术方案类型为 WIFI/移动网络方案,选择通讯方式为 WIFI,选择数据传输方式为定长。
创建数据点:数据点即设备产品功能的抽象。根据系统功能设计要求,分别建立采样频率、电网工频、电机输入功率、离心泵驱动电机定子电流均方根指标、脉冲因子指标、峭度系数指标、总谐波失真指标、信噪比指标、信纳比指标共 9 项只读数值类型的数据点,用于显示诊断信息。建立缺相报警这一项布尔值类型的数据点,用于离心泵驱动电机某相断路时报警。
协议添加:生成并下载 MCU 开发代码包。并在项目工程模板中添加 Gizwits 工程协议文档。
程序改写:基于机智云官网生成的 MCU 代码包,对程序进行改写,将系统计算出的指标值赋给对应数据点。
固件烧录:将 GAgent 固件烧写进 ATK-ESP8266 WIFI 模块中,具体烧录过程见机智云官方文档中心的ESP8266串口烧写教程。 http://docs.gizwits.com/zh-cn/deviceDev/ESP8266%E4%B8%B2%E5%8F%A3%E7%83%A7%E5%86%99%E8%AF%B4%E6%98%8E.html
基于 Android Studio 环境,对机智云提供的 APP 开源框架进行个性化修改,最后生成的移动客户端界面。
建立通信:操作 ATK-ESP8266 WIFI 模块进入 Airlink 模式下配网,绑定设备,进行对接通信测试,完成云端通信的所有配置。
系统APP界面图如下:
离泵工况诊断的功能实现代码如下: [backcolor=rgba(0, 0, 0, 0.03)](1)ADC 参数配置
- //ADC 参数配置:
- void ADC_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- ADC_CommonInitTypeDef ADC_CommonInitStructure;
- ADC_InitTypeDef ADC_InitStructure;
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
-
- GPIO_InitStructureGPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);
- RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);
- ADC_CommonInitStructure.ADC_Mode= ADC_Mode_Independent;
- ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
- ADC_CommonInitStructure.ADC_DMAAccessMode =ADC_DMAAccessMode_Disabled;
- ADC_CommonInitStructure.ADC_Prescaler= ADC_Prescaler_Div4;
- ADC_CommonInit(&ADC_CommonInitStructure);
- ADC_InitStructure.ADC_Resolution= ADC_Resolution_12b;
- ADC_InitStructure.ADC_ScanConvMode= ENABLE;
- ADC_InitStructure.ADC_ContinuousConvMode= DISABLE;
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
- ADC_InitStructure.ADC_ExternalTrigConv= ADC_ExternalTrigConv_T2_TRGO;
- ADC_InitStructure.ADC_DataAlign= ADC_DataAlign_Right;
- ADC_InitStructure.ADC_NbrOfConversion= 3;
- ADC_Init(ADC1, &ADC_InitStructure);
- ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_480Cycles);
- ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_480Cycles);
- ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_480Cycles);
- ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
- ADC_DMACmd(ADC1, ENABLE);
- ADC_Cmd(ADC1, ENABLE);
- }
复制代码
(2) 三相电参数监测模块参数配置: - (2) 三相电参数监测模块参数配置:
- void EMU_init(int Phase,int Wire)
- {
- Write_Att7022(0xD3,0x0000); //ATT7022E 复位
- Write_Att7022(0xC3,0x000000); //校表数据寄存器恢复到上电初始值
- Write_Att7022(0xC9,0x00005A); //使能 SPI 校表写操作
- Write_Att7022(0x01,0xB97E); //模式配置寄存器设置
- Write_Att7022(0x03,0xF884); //EMU 单元配置
- Write_Att7022(0x02,0x0100); //ADC 增益配置寄存器配置
- Write_Att7022(0x31,0x3437); //模拟模块寄存器使能
- Write_Att7022(0x6D, 0xFF00); // Vrefgain 补偿曲线系数 TCcoffA 设置
- Write_Att7022(0x6E, 0x0DB8); // Vrefgain 补偿曲线系数 TCcoffB 设置
- Write_Att7022(0x6F, 0xD1DA); // Vrefgain 补偿曲线系数 TCcoffC 设置
- Write_Att7022(0x1E,HFCONST); //HFconst 3200
- Write_Att7022(0x17,(int)ATT_U_JIAOZHENG(0x0D,228.6)); //A 相电压增益校准
- Write_Att7022(0x18,(int)ATT_U_JIAOZHENG(0x0E,228.6)); //B 相电压增益校准
- Write_Att7022(0x19,(int)ATT_U_JIAOZHENG(0x0F,229.7)); //C 相电压增益校准
- Write_Att7022(0x1A,(int)ATT_I_JIAOZHENG(0x10,1.568)); //A 相电流增益校准
- Write_Att7022(0x1B,(int)ATT_I_JIAOZHENG(0x11,1.568)); //B 相电流增益校准
- Write_Att7022(0x1C,(int)ATT_I_JIAOZHENG(0x12,1.568)); //C 相电流增益校准
- Write_Att7022(0x04,(int)ATT_P_JIAOZHENG(0x01,358.448)); //A 相有功功率增益校准
- Write_Att7022(0x07,(int)ATT_P_JIAOZHENG(0x01,358.448)); //A 相无功功率增益校准
- Write_Att7022(0x0A,(int)ATT_P_JIAOZHENG(0x01,358.448)); //A 相视在功率增益校准
- Write_Att7022(0x05,(int)ATT_P_JIAOZHENG(0x02,358.448)); //B 相有功功率增益校准
- Write_Att7022(0x08,(int)ATT_P_JIAOZHENG(0x02,358.448)); //B 相无功功率增益校准
- Write_Att7022(0x0B,(int)ATT_P_JIAOZHENG(0x02,358.448)); //B 相视在功率增益校准
- Write_Att7022(0x06,(int)ATT_P_JIAOZHENG(0x03,358.448)); //C 相有功功率增益校准
- Write_Att7022(0x09,(int)ATT_P_JIAOZHENG(0x03,358.448)); //C 相无功功率增益校准
- Write_Att7022(0x0C,(int)ATT_P_JIAOZHENG(0x03,358.448)); //C 相视在功率增益校准
- if (Phase==3 && Wire==3){ //SEL 选择
- Write_Att7022(0x35,0x080E); //IO 状态寄存器配置
- }
- else if(Phase==3 && Wire==4){
- Write_Att7022(0x35,0x080F);
- }
- Write_Att7022(0xC5,0x0002); //打开同步
- Write_Att7022(0xC9,0x000000); //关闭 SPI 校表写操作
- }
复制代码 (3) main.c 文件相关程序:
- //频谱绘制,带宽 430Hz
- void Frequency_Spectrum(float32_t * arry,float32_t x,uint16_t n){
- uint16_t i;
- float power;
- for(i=0;i<430;i++){
- if(*(arry+i)/x==1){
- *(arry+i)=1;
- }
- POINT_COLOR = BLACK;
- LCD_DrawLine(15+i,200+208*n,15+i,200+208*n-(*(arry+i))*180);
- }
- POINT_COLOR = BLUE;
- LCD_ShowString(330,20+208*n,120,12,12,"Freq(Hz) Power(dB)");
- for(i=0;i<8;i++){
- power=10*log10(RMSharmonic[i]*RMSharmonic[i]);
- LCD_ShowFloatNum(330,32+208*n+12*i,harmonic_frequency[i],2,12,0);
- if(power>0){
- LCD_ShowFloatNum(396,32+208*n+12*i,power,2,12,0);
- }
- else{
- LCD_ShowString(390,32+208*n+12*i,6,12,12,"-");
- LCD_ShowFloatNum(396,32+208*n+12*i,(-power),2,12,0);
- }
- }
- }
- //频域诊断指标计算
- void Frequency_OperationIndicator(float32_t * arry,uint16_t n)
- {
- uint16_t i;
- float32_t current_power;
- float32_t fundamental_power;
- float32_t harmonic_power;
- float32_t sqrt_harmonic_power;
- for(i=0;i<(FFT_LENGTH/2+1);i++){
- if(i==0)
- amplitude[i]=(*(arry+i)/FFT_LENGTH)* 4.39f; //直流分量幅值还原,频谱修正
- else
- amplitude[i]=(*(arry+i)*2/FFT_LENGTH) *4.39f; //交流分量幅值还原,频谱修正
- }
- arm_max_f32(amplitude,2049,harmonic,harmonic_frequency); //基波基频
- RMSharmonic[0]=harmonic[0]/1.4142135623731f;
- for(i=2;i<11;i++){
- arm_max_f32((amplitude+i*harmonic_frequency[0]-1),2,harmonic+i-1,harmonic_frequency
- +i-1); //10 次以内谐波
- *(harmonic_frequency+i-1)=*(harmonic_frequency+i-1)+i*harmonic_frequency[0]-1;/谐频
- RMSharmonic[i-1]=harmonic[i-1]/1.4142135623731f;
- }
- current_power=square(RMS[n],2); //信号总功率
- fundamental_power=square(RMSharmonic[0],2); //基波功率
- arm_power_f32(RMSharmonic+1,9,&harmonic_power); //谐波功率
- arm_sqrt_f32(harmonic_power,&sqrt_harmonic_power);
- THD[n]=sqrt_harmonic_power/RMSharmonic[0]; //总谐波失真指标计算
- SNR[n]=(fundamental_power+harmonic_power)/(current_power-fundamental_power-harmon
- ic_power);
- SINAD[n]=current_power/(current_power-fundamental_power);
- arm_sqrt_f32(SNR[n],SNR+n); //信噪比指标计算
- arm_sqrt_f32(SINAD[n],SINAD+n); //信纳比指标计算
- THD[n]=20*log10(THD[n]); //dB 换算
- SNR[n]=20*log10(SNR[n]); //dB 换算
- SINAD[n]=20*log10(SINAD[n]); //dB 换算
- Frequency_Spectrum(amplitude,harmonic[0],n);
- }
- //时域诊断指标计算
- void Time_OperationIndicator(float32_t * arry,uint16_t n)
- {
- uint32_t i;
- uint32_t imax;
- float32_t max;
- float32_t mean; //平均值
- float32_t meanabs; //整流平均值
- float32_t meansqrt; //算术平方根的平均值
- float32_t squaremeansqrt; //方根幅值
- arm_max_f32(arry,4096,&max,&imax); //峰值计算
- arm_mean_f32(arry,4096,&mean); //平均值计算
- arm_abs_f32(arry,arry,4096); //绝对值计算
- for(i=0;i<4096;i++){
- KURTOSIS[n]=KURTOSIS[n]+square((*(arry+i)-mean),4);
- }
- KURTOSIS[n]=KURTOSIS[n]/4096;
- KURTOSIS[n]=KURTOSIS[n]/square((*(RMS+n)),4); //峭度系数指标计算
- arm_mean_f32(arry,4096,&meanabs);
- for(i=0;i<4096;i++){
- arm_sqrt_f32(*(arry+i),(arry+i));
- }
- arm_mean_f32(arry,4096,&meansqrt);
- squaremeansqrt=square(meansqrt,2);
- PULSE[n]=max/meanabs; //脉冲因子指标计算
- MARGIN[n]=max/squaremeansqrt; //裕度因子指标计算
- }
- //Gizwits 协议初始化
- void Gizwits_Init(void)
- {
- TIM3_Int_Init(10-1,8400-1); //1MS 系统定时
- usart3_init(9600);
- memset((uint8_t*)¤tDataPoint, 0, sizeof(dataPoint_t)); //设备状态结构体初始化
- gizwitsInit(); //缓冲区初始化
- }
- //机智云用户自定义函数
- void userHandle(void)
- {
- if(wifi_sta) //WIFI 已连接
- {
- currentDataPoint.valueFe = Fe;
- currentDataPoint.valuePin = Pin;
- currentDataPoint.valueTHD = THD[3];
- currentDataPoint.valueSNR = SNR[3];
- currentDataPoint.valueSINAD = SINAD[3];
- currentDataPoint.valueCf = PULSE[3];
- currentDataPoint.valueCq = KURTOSIS[3];
- currentDataPoint.valueCe = MARGIN[3];
- currentDataPoint.valueFs = Fs;
- }
- }
- //主函数
- int main(void)
- {
- uint16_t n;
- int key;
- arm_cfft_radix4_instance_f32 scfft;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //系统中断优先级分组
- delay_init(168); //延时函数初始化
- uart_init(115200); //初始化串口
- KEY_Init(); //按键初始化
- Gizwits_Init(); //机智云协议初始化
- TIM2_Int_Init(); //通用定时器 2 初始化
- ADC_Config(); //ADC 参数配置
- DMA_Config(); //DMA 参数配置
- LCD_Init(); //LCD 初始化
- FSMC_SRAM_Init(); //外部 SRAM 初始化
- arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1); //初始化 scfft 结构体,设定 FFT 参
- 数
- Screen_diaplay(); //界面显示
- EMU_init(3,4); //三相电参数监测模块初始化
- while (1)
- {
- if(flag_dma==1)
- {
- arm_rms_f32(ADC_Con_A[n],4096,RMS+0); //A 相输入电流均方根指标计算
- arm_rms_f32(ADC_Con_B[n],4096,RMS+1); //B 相输入电流均方根指标计算
- arm_rms_f32(ADC_Con_C[n],4096,RMS+2); //C 相输入电流均方根指标计算
- //复数构造
- for(n=0;n<FFT_LENGTH;n++){
- fft_inputbuf[0][2*n]=ADC_Con_A[n]* Kaiser [n];
- fft_inputbuf[0][2*n+1]=0;
- fft_inputbuf[1][2*n]=ADC_Con_B[n]* Kaiser [n];
- fft_inputbuf[1][2*n+1]=0;
- fft_inputbuf[2][2*n]=ADC_Con_C[n]* Kaiser [n];
- fft_inputbuf[2][2*n+1]=0;
- }
- arm_cfft_radix4_f32(&scfft,fft_inputbuf[0]); //FFT 计算(基 4)
- arm_cmplx_mag_f32(fft_inputbuf[0],fft_outputbufA,FFT_LENGTH); //复数求模
- arm_cfft_radix4_f32(&scfft,fft_inputbuf[1]);
- arm_cmplx_mag_f32(fft_inputbuf[1],fft_outputbufB,FFT_LENGTH);
- arm_cfft_radix4_f32(&scfft,fft_inputbuf[2]);
- arm_cmplx_mag_f32(fft_inputbuf[2],fft_outputbufC,FFT_LENGTH);
- Frequency_OperationIndicator(fft_outputbufA,0); //频域诊断指标计算
- Frequency_OperationIndicator(fft_outputbufB,1);
- Frequency_OperationIndicator(fft_outputbufC,2);
- Time_OperationIndicator(ADC_Con_A,0); //时域诊断指标计算
- Time_OperationIndicator(ADC_Con_B,1);
- Time_OperationIndicator(ADC_Con_C,2);
- //合相诊断指标计算
- RMS[3]=(RMS[0]+RMS[1]+RMS[2])/3;
- PULSE[3]=(PULSE[0]+PULSE[1]+PULSE[2])/3;
- MARGIN[3]=(MARGIN[0]+MARGIN[1]+MARGIN[2])/3;
- KURTOSIS[3]=(KURTOSIS[0]+KURTOSIS[1]+KURTOSIS[2])/3;
- THD[3]=(THD[0]+THD[1]+THD[2])/3;
- SNR[3]=(SNR[0]+SNR[1]+SNR[2])/3;
- SINAD[3]=(SINAD[0]+SINAD[1]+SINAD[2])/3;
- Fe=ReadSARegister(0x1C)/8192; //电网工频
- Pin=Calculate_S(HXPhase)*2; //电机输入功率
- LCD_ShowFloatNum(65,640,Fs,0,16,0);
- LCD_ShowFloatNum(65,665,F0,0,16,0);
- LCD_ShowFloatNum(65,690,Fe,2,16,0);
- LCD_ShowString(97,715,8,16,16,"-");
- LCD_ShowFloatNum(105,715,-THD[3],2,16,0);
- LCD_ShowFloatNum(97,740,SNR[3],2,16,0);
- LCD_ShowFloatNum(113,765,SINAD[3],2,16,0);
- LCD_ShowFloatNum(352,640,RMS[3],2,16,0);
- LCD_ShowFloatNum(344,665,PULSE[3],2,16,0);
- LCD_ShowFloatNum(344,690,KURTOSIS[3],2,16,0);
- LCD_ShowFloatNum(344,715,MARGIN[3],2,16,0);
- LCD_ShowFloatNum(312,740,P,2,16,0);
- userHandle(); //机智云协议用户操作
- gizwitsHandle((dataPoint_t *)¤tDataPoint); //机智云协议处理
- key = KEY_Scan(0);
- if(key==KEY1_PRES) //KEY1 按键按下
- {
- printf("WIFI 进入 Airlink 连接模式\r\n");
- gizwitsSetMode(WIFI_AIRLINK_MODE); //Airlink 模式接入
- }
- if(key==WKUP_PRES) //KEY_UP 按键按下
- {
- printf("WIFI 复位,以重新配置连接\r\n");
- gizwitsSetMode(WIFI_RESET_MODE); //WIFI 复位
- }
- }
- }
- }
复制代码
系统总结
综合离心泵工况诊断系统的功能需求和硬件架构,本文从系统初始化、信息交互等方面对系统的功能实现程序进行了设计,基于机智云物联网云平台实现了电流信号的实时采集,诊断指标的实时计算,电流频谱的实时显示,电机功率的实时监测以及系统下位机与屏显模块、移动端 APP 两个平台之间的信息交互。
实物工作情况图如下:
|
|