/*--------------------------------------------------------------------------------------
*  @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<ElectricityDatabf)&&((ElectricityDatabf - 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,清除计数
					if((ElectricityDatabf - ElectricityData) > 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;//如果采集值<BLOCKING_ALARM_DATA,清除计数
						 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);
					 }
				 }
			}	
		}
	}
}
/********************************************************************************************************
*  Function:	Electricity_WorkOffGet						                                                           
*  Object:		电流数据采集
*  输入:			无
*  输出:			无	                                     
*  备注:			1、只要TaskSchedulerFlag.sensorPWBatteryFlag标志位置位或 motorWorkState == MOTOR_WORK_OFF才会采集一次电池电压值            
*							2、uint32_t tempADC2 = 0;临时变量读取AD数值
*							3、uint16_t  BubbleVolt = 0;临时变量计算采集电压
*							4、通过均值算法得出稳定电压值，每采集n次值，前2次值丢弃，比较一下，取最小值
*							
********************************************************************************************************/
void Electricity_WorkOffGet( void )
{
	uint16_t  Electricity_Volt = 0;
	uint32_t tempADC2_15 = 0;
	
	if(( motorWorkState == MOTOR_WORK_OFF ) && (sysAlarmFlag.MechanicalFault != ALARM_CONTINUE) && ( TaskSchedulerFlag.motorSelfTestFlag == TASK_FLAG_SET ))//在电机运行的时候采集数据，在电机停止的时候出来数据
	{
		if( ElectricityOFFflag == 1 )//定时到进行AD采集
		{
			ElectricityOFFflag=0;
			ElectricityOffTime = ONE_SECOND_TIMER; //1s检测一下
			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;   
			ElectricityOffData=(uint16_t)tempADC2_15;
		//	printf("%d\r\n",tempADC2_15);
			if( tempADC2_15 > ELECT_DISCONT_DATA) //如果在关闭电机工程中，采集的电流值大于ELECT_DISCONT_DATA，侧进行机械报警处理
			{
				if( ElectricityCountsOff++ >= 2 )
				{
					ElectricityCountsOff=0;
				  sysAlarmFlag.MechanicalFault = ALARM_ON;
				}
			}
			else
			{
				ElectricityCountsOff=0;
			}
		}
	}	
}
