/*-------------------------------------------------------------------------------------- * @file Bubble_ADCSetup.c * @author 鲍胜文 * @version base on stm32f0x * @date 2015.09.11 * @brief OPB350L187芯片ADC采集处理 ---------------------------------------------------------------------------------------*/ #include "stm32f10x_gpio.h" #include "stm32f10x_adc.h" #include "stm32f10x_dma.h" #include "ControlSystem.h" #include "TypeDefine.h" #include "ADCSetup.h" #include "Bubble_ADCSetup.h" #include "SystemAlarm.h" #include "DrawLCDGUI.h" uint16_t BubbleVolt[20]={ 0xffff , 0xffff , 0xffff , 0xffff , 0xffff, 0xffff , 0xffff ,0xffff , 0xffff , 0xffff , 0xffff , 0xffff, 0xffff , 0xffff , 0xffff , 0xffff , 0xffff , 0xffff, 0xffff , 0xffff};//气泡采集数组 uint16_t ElectricityVolt[50]={0}; //电机运行电流采集数组 uint16_t ElectricityVolt2[20]={0};//电机停止时采集数组 uint16_t BubbleCounts=0;//气泡检测次数 uint16_t BubbleData=0; //气泡检测数据 uint16_t BoxData=0; //药盒检测数据 uint16_t BoxCont=0; //药盒检测次数 uint16_t BubbleCheckTime=0; //气泡检测时间 uint16_t BubbleCheckFlag=0; //气泡检测时间到,置位该标志 uint16_t CheckDoneFlag=0; //采集完成标志,置位该标志 uint8_t BubbleCountFlag=0; //气泡采集次数完成标志,置位该标志 uint8_t BlockageRecovery = 0; //堵塞自检恢复 uint8_t AnotherAlarm=0; //发生堵塞报警得时候发生未装药盒报警标志 uint16_t ElectricityCheckFlag=0; //电流检测时间到,置位该标志 uint16_t ElectricityCheckTime=0; //电流检测时间 uint16_t ElectDoneFlag=0; //电流采集完成标志,置位该标志 uint16_t ElectricityCounts=0 ; //电流检测次数 uint16_t ElectricityData=0; //电流检测数据 uint16_t ElectricityDatabf=0; //电流检测数据备份 uint8_t ElectCountFlag=0; //电流采集次数完成标志,置位该标志 uint8_t ElectStartCount=0; //按运行按键时,电流采集次数,求基准值 uint16_t Elect_adaption_buf[5]={0};//自适应压力值缓冲区 uint16_t Elect_adaption_buf1[5]={0};//小于基准值150时,自适应压力值缓冲区重新备份 uint16_t Elect_adaption_buf2[5]={0};//大于基准值150时,自适应压力值缓冲区重新备份 uint8_t ElectLargeCount=0; //计算大于电流基准值150的次数 uint8_t ElectSmallCount=0; //计算小于电流基准值150的次数 uint8_t ElectRunCount=0; //计算堵塞变为正常运行的采集次数 uint8_t ElectBlockingCount=0; //计算堵塞采集次数 uint8_t ElectricityCountsOff=0 ; //电机关闭时电流检测次数 uint16_t ElectricityOffTime=0; //电机关闭时电流检测时间 uint16_t ElectricityOFFflag=0; //电机关闭时电流检测时间到,置位该标志 uint16_t ElectricityOffData=0; //电流检测数据 /****************************************** * 功能:ADC2初始化,使用PC04引脚采集 ******************************************/ void OPB350L_ADCInit(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2 | RCC_APB2Periph_GPIOC, ENABLE); /* Configure PC.04 (ADC Channel12) as analog input -------------------------*/ GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_2); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); /* ADC2 configuration ------------------------------------------------------*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;/*ADC工作在独立模式*/ ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//不连续采集,开启一次AD,采集一下 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;/*软件触发*/ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1;/*单通道*/ ADC_Init(ADC2, &ADC_InitStructure); /* ADC1 regular channel12 configuration */ ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 1, ADC_SampleTime_55Cycles5); /* Enable ADC1 */ ADC_Cmd(ADC2, ENABLE); /* Enable ADC1 reset calibration register */ ADC_ResetCalibration(ADC2); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC2)); /*开始校准*/ ADC_StartCalibration(ADC2); /* 等待校准结束*/ while(ADC_GetCalibrationStatus(ADC2)); //ADC_SoftwareStartConvCmd(ADC2, ENABLE);/*开启转换*/ } /******************************************************************************************************** * Function: OPB350L_ADCGet * Object: 红外气泡数据采集 * 输入: 无 * 输出: 无 * 备注: 1、只要TaskSchedulerFlag.sensorPWBatteryFlag标志位置位或 motorWorkState == MOTOR_WORK_OFF才会采集一次电池电压值 * 2、uint32_t tempADC2 = 0;临时变量读取AD数值 * 3、uint16_t BubbleVolt = 0;临时变量计算采集电压 * 4、通过均值算法得出稳定电压值,每采集n次值,前2次值丢弃,比较一下,取最小值 * ********************************************************************************************************/ void OPB350L_ADCGet( void ) { uint32_t tempADC2 = 0; uint16_t Bublle_Volt = 0; uint16_t t = 0; uint8_t i,j; uint8_t Bubble_Alarm_cont=0;//一个周期内采集值低于报警阈值的次数 if(( motorWorkState == MOTOR_WORK_ON ) && (TaskSchedulerFlag.sensorPWHallFlag == TASK_FLAG_SET) && (BubbleCountFlag == TASK_FLAG_CLEAR))//在电机运行的时候采集数据,在电机停止的时候出来数据 { if( BubbleCheckFlag == 1 )//定时到进行AD采集 { BubbleCheckFlag=0; ADC_RegularChannelConfig(ADC2, ADC_Channel_13, 1, ADC_SampleTime_55Cycles5); ADC_SoftwareStartConvCmd(ADC2, ENABLE); //启动转换 while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC )); //等待转换完成 Bublle_Volt=ADC_GetConversionValue(ADC2); //获取转换结果*ADC_ConvertedValue* tempADC2 = Bublle_Volt * 2515 / 4096; //printf("a=%d\r\n",tempADC2); BubbleVolt[BubbleCounts] = (uint16_t)tempADC2 ; //6这个数值是从分压电路得到 BubbleCounts++; if( BubbleCounts > 20) { BubbleCounts=20; BubbleCountFlag=TASK_FLAG_SET;//当采集次数大于20时,不在采集 } CheckDoneFlag=1;//采集标志 } } else if( CheckDoneFlag == 1) { CheckDoneFlag=0; for( i = 1; i < BubbleCounts; i++ ) { for( j = 0; j < (BubbleCounts - i); j++ ) { if( BubbleVolt[j] > BubbleVolt[j + 1] ) { t = BubbleVolt[j]; BubbleVolt[j] = BubbleVolt[j + 1]; BubbleVolt[j + 1] = t; } } // printf("b=%d\r\n",BubbleVolt[j]); } BubbleData=0; BoxData=0; for( i = 2; i < BubbleCounts-2; i++ ) //去掉前两位和后两位,然后求和取平准值 { BoxData = (BoxData + BubbleVolt[i]); } BoxData = (BoxData/(BubbleCounts-4)); // printf("%d\r\n",BubbleData); /* if( sysAlarmFlag.NonePillCase != ALARM_ON ) //没有未装药盒报警,进行下面判断 { if(( BoxData < BOX_ALARM_UPPER_DATA ) && ( BoxData > BOX_ALARM_LOWER_DATA ))//判断未装药盒报警 { if( BoxCont++ >= 1 ) { BoxCont=0; SysAlarmJudge.NonePillCaseJudgeFlag = TASK_FLAG_SET; realTimeData.pressureF=10; } } else { BoxCont=0; } }*/ for( i = 1; i < BubbleCounts-2; i++ ) //去掉前两位和后两位,然后求和取平准值 { if( (BubbleVolt[i] < Bubble_Alarm_Value )&&(BubbleVolt[i] > Bubble_Alarm_Value_Down)) //判断气泡报警检测 { Bubble_Alarm_cont++;//低于阈值 加一 } } BubbleData = BubbleVolt[1]; //printf("c=%d\r\n",BubbleData); BubbleCounts=0; SysAlarmJudge.BubbleFaultJudgeFlag = TASK_FLAG_SET; if( Bubble_Alarm_cont >= 2) //一个周期内采集两次小于阈值的数值,报警 { Bubble_Alarm_cont=0; // BubbleData=500; } } } /******************************************************************************************************** * Function: Electricity_ADCGet * Object: 电流数据采集 * 输入: 无 * 输出: 无 * 备注: 1、只要TaskSchedulerFlag.sensorPWBatteryFlag标志位置位或 motorWorkState == MOTOR_WORK_OFF才会采集一次电池电压值 * 2、uint32_t tempADC2 = 0;临时变量读取AD数值 * 3、uint16_t BubbleVolt = 0;临时变量计算采集电压 * 4、通过均值算法得出稳定电压值,每采集n次值,前2次值丢弃,比较一下,取最小值 * ********************************************************************************************************/ void Electricity_ADCGet( void ) { uint32_t tempADC2_15 = 0; uint16_t Electricity_Volt = 0; uint16_t t = 0; uint8_t k=0; uint8_t i,j; if(( motorWorkState == MOTOR_WORK_ON ) && (TaskSchedulerFlag.sensorPWHallFlag == TASK_FLAG_SET) && (ElectCountFlag == TASK_FLAG_CLEAR) && (realTimeData.stateRun != Airout)&& (realTimeData.stateRun != WaitState))//在电机运行的时候采集数据,在电机停止的时候出来数据 { if( ElectricityCheckFlag == 1 )//定时到进行AD采集 { ElectricityCheckFlag=0; ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 1, ADC_SampleTime_55Cycles5); ADC_SoftwareStartConvCmd(ADC2, ENABLE); //启动转换 while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC )); //等待转换完成 Electricity_Volt=ADC_GetConversionValue(ADC2); //获取转换结果*ADC_ConvertedValue* tempADC2_15 = Electricity_Volt * 2515 / 4096; // tempADC2_15 = Electricity_Volt; // printf("%d\r\n",tempADC2_15); ElectricityVolt[ElectricityCounts] = (uint16_t)tempADC2_15 ; //6这个数值是从分压电路得到 // printf("a=%d\r\n",ElectricityVolt[ElectricityCounts]); ElectricityCounts++; if( ElectricityCounts > 50) { ElectricityCounts=50; ElectCountFlag=TASK_FLAG_SET;//当采集次数大于50时,不在采集 } ElectDoneFlag=TASK_FLAG_SET;//采集标志 } } else if( ElectDoneFlag == TASK_FLAG_SET) { ElectDoneFlag=TASK_FLAG_CLEAR; // if( ElectricityCounts == 50) { for( i = 1; i < ElectricityCounts; i++ ) { for( j = 0; j < (ElectricityCounts - i); j++ ) { if( ElectricityVolt[j] > ElectricityVolt[j + 1] ) { t = ElectricityVolt[j]; ElectricityVolt[j] = ElectricityVolt[j + 1]; ElectricityVolt[j + 1] = t; } } // printf("a=%d\r\n",ElectricityVolt[j]); } } ElectricityData=0; ElectricityData = ElectricityVolt[ElectricityCounts-3]; // printf("Data=%d\r\n",ElectricityData); if(( sysAlarmFlag.NonePillCase != ALARM_ON )&&(realTimeData.stateRun != Airout))//没有未装药盒报警,进行下面判断 { if(ElectricityData < BOX_ALARM_DATA) { if( ElectSmallCount++ >= 1) //连续2次采集数值都大于基准值BLOCKING_ALARM_DATA,进行报警处理 { ElectSmallCount=0; realTimeData.pressureF=10; SysAlarmJudge.NonePillCaseJudgeFlag = TASK_FLAG_SET; // if((sysAlarmFlag.JamFault == ALARM_ON) && ( EngineeringModeValue.closedState == ENGINEERINGMODE_ON )) // { // TaskSchedulerFlag.JamSelfcheckingFlag = TASK_FLAG_WAIT; //堵塞自检标志等待 // sysAlarmFlag.JamFault = ALARM_OFF;//结束报警 // AnotherAlarm = 1; // ElectRunCount=0; // } } } else { ElectSmallCount=0; } } if(TaskSchedulerFlag.JamSelfcheckingFlag == TASK_FLAG_WCLEAR) { /*堵塞基准值>电机电流值且(堵塞基准值)-(电机电流值且)>=(KVO堵塞阈值)*/ if((ElectricityData=BLOCKING_ALARM_DATA)) { JamSelfcheckThroughCycle ++; // printf("JamSelfcheckThroughCycle=%d\r\n",JamSelfcheckThroughCycle); } if(JamSelfcheckCycle >= 2)//自检3个周期后 { // printf("JamSelfcheckCycle=%d\r\n",JamSelfcheckCycle); JamSelfcheckCycle = 0; /*解除报警*/ if(JamSelfcheckThroughCycle>=3)//堵塞恢复 { TaskSchedulerFlag.JamSelfcheckingFlag = TASK_FLAG_WAIT; //堵塞自检标志等待 StartToRun_flag =1; TaskSchedulerTimer.rtdXmitTimer = TEN_SECOND_TIMER;//准备快速发送实时数据 /*重新采集基准值*/ start_flag = 1; ElectricityCounts = 0; SysHornToneType = SoundOff; } /*继续堵塞*/ else { ElectLargeCount = 0;//防止堵塞恢复时,滞流夹打开 ElectRunCount = 0; SysAlarmJudge.JamFaultJudgeFlag = TASK_FLAG_SET; realTimeData.pressureF=50; TaskSchedulerTimer.rtdXmitTimer = TEN_SECOND_TIMER;//准备快速发送实时数据 TaskSchedulerFlag.JamSelfcheckingFlag = TASK_FLAG_SET; } JamSelfcheckThroughCycle = 0;//堵塞解除自检周期 } else { TaskSchedulerTimer.motorStopTimer = 1500; } } //printf("c=%d\r\n",ElectricityData); ElectricityCounts=0; if( start_flag ==1) //连续取值五个周期,求最大值 { Elect_adaption_buf[ElectStartCount] = ElectricityData; ElectStartCount++; if( ElectStartCount > 3) { ElectricityDatabf = ((Elect_adaption_buf[1] + Elect_adaption_buf[2] + Elect_adaption_buf[3])/3); // printf("Databf=%d\r\n",ElectricityDatabf); ElectStartCount=0; start_flag=0; } } else { if(TaskSchedulerFlag.JamSelfcheckingFlag == TASK_FLAG_WCLEAR) { JamSelfcheckCycle ++; } if( ElectricityData > ElectricityDatabf ) //判断堵塞报警数据处理 { ElectRunCount=0; if((ElectricityData - ElectricityDatabf) > BLOCKING_ALARM_DATA) { Elect_adaption_buf2[ElectLargeCount] = ElectricityData; if( ElectLargeCount ++>= 2) //连续2次采集数值都大于基准值BLOCKING_ALARM_DATA,进行报警处理 { ElectLargeCount=0; SysAlarmJudge.JamFaultJudgeFlag = TASK_FLAG_SET; realTimeData.pressureF=50; for(k=0;k<3;k++) //基准值滚动式更新 { Elect_adaption_buf[k+1] = Elect_adaption_buf2[k]; } ElectricityDatabf=((Elect_adaption_buf[1]+Elect_adaption_buf[2]+Elect_adaption_buf[3])/3); // printf("Databf=%d\r\n",ElectricityDatabf); if(infusionMode == FirstDoseMode) { FirstSurplusDose = realTimeData.firstDose; } else if(infusionMode == SuperadditionMode) { PCASurplusDose = realTimeData.superaddition; } } } else { for(k=0;k<3;k++) //基准值滚动式更新 { Elect_adaption_buf[k] = Elect_adaption_buf[k+1]; } Elect_adaption_buf[3] = ElectricityData; ElectricityDatabf = ((Elect_adaption_buf[1] + Elect_adaption_buf[2] + Elect_adaption_buf[3])/3); // printf("Databf=%d\r\n",ElectricityDatabf); } } else if( ElectricityData <= ElectricityDatabf ) { ElectLargeCount=0; { // ElectSmallCount=0; //如果采集值 BLOCKING_ALARM_DATA) //运行时关闭止流夹,然后再次打开,基准值重新备份 { Elect_adaption_buf1[ElectRunCount] = ElectricityData; if( ElectRunCount++ >= 2) //连续2次采集数值都大于基准值BLOCKING_ALARM_DATA,进行基准数据重新采样处理 { ElectRunCount=0; for(k=0;k<3;k++) //基准值滚动式更新 { Elect_adaption_buf[k+1] = Elect_adaption_buf1[k]; } ElectricityDatabf=((Elect_adaption_buf[1]+Elect_adaption_buf[2]+Elect_adaption_buf[3])/3); // printf("Databf=%d\r\n",ElectricityDatabf); } } else { ElectRunCount=0;//如果采集值 ELECT_DISCONT_DATA) //如果在关闭电机工程中,采集的电流值大于ELECT_DISCONT_DATA,侧进行机械报警处理 { if( ElectricityCountsOff++ >= 2 ) { ElectricityCountsOff=0; sysAlarmFlag.MechanicalFault = ALARM_ON; } } else { ElectricityCountsOff=0; } } } }