Started a gui menuflow
Dependencies: LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI BSP_DISCO_F429ZI
Diff: Monitoring.c
- Revision:
- 2:5828e6917e75
diff -r 35eb0c8fa2c0 -r 5828e6917e75 Monitoring.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Monitoring.c Tue Jun 09 22:57:20 2020 +0000 @@ -0,0 +1,1375 @@ +*********************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#define EXTERN extern +#include "SS.h" +#include "main.h" +#include "_ss_pwm.h" +#include "_SS_I2CX_Drivers.h" +#include "_SS_I2CX_SDP600.h" +#include "_SS_I2CX_X201641.h" +#include "Ventilation.h" +#include "MotorTempTable.h" +#include "_SS_FlowComputer.h" +#include "_SS_TSI_4040.h" +#include "_SS_Data_Logging.h" +#include "_SS_OnOffActioner.h" +#undef EXTERN + +#define INIT_VARIABLES +#define EXTERN +#include "Monitoring.h" +#undef EXTERN +#undef INIT_VARIABLES + + +// *********************** Register locations ********************************** +#define DMA_IFCR1 (*(volatile uint32_t *)0x40020004) +#define DMA_CCR1 (*(volatile uint32_t *)0x40020008) +#define DMA_CNTDR1 (*(volatile uint32_t *)0x4002000c) +#define DMA_CPAR1 (*(volatile uint32_t *)0x40020010) +#define DMA_CMAR1 (*(volatile uint32_t *)0x40020014) + +#define ADC1_SR (*(volatile uint32_t *)0x40012400) +#define ADC1_SQR1 (*(volatile uint32_t *)0x4001242C) +#define ADC1_SQR2 (*(volatile uint32_t *)0x40012430) +#define ADC1_SQR3 (*(volatile uint32_t *)0x40012434) +#define ADC1_LTR (*(volatile uint32_t *)0x40012428) +#define ADC1_HTR (*(volatile uint32_t *)0x40012424) +#define ADC1_CR1 (*(volatile uint32_t *)0x40012404) +#define ADC1_CR2 (*(volatile uint32_t *)0x40012408) + + +// ************************* ADC CONFIGURATION CHANNELS ************************ +#define FREE_MEAS_CHANNEL 0 +#define PPROX_MEAS_CHANNEL 1 +#define CURRENT_MEAS_CHANNEL 2 +#define ALIM_24V_MEAS_CHANNEL 6 +#define TEMP_PHASE_A 5 +#define TEMP_PHASE_B 4 +#define TEMP_PHASE_C 3 + +// ********************* 24V ALARM MANAGEMENT ********************************** +#ifndef C_M3_DEVICETEST_TARGET + +#endif + + + +// ************************ I2C SENSORS MANAGEMENT ***************************** +#ifndef C_M3_DEVICETEST_TARGET + #define READING_NO_SENSOR 0 + #define READING_FLOW_SENSORS 1 + //#define READING_PRESSURE_SENSORS 2 + #define STOP_READING_FLOW_SENSORS 3 + #define START_READING_FLOW_SENSORS 4 + #define NUMBER_I2C_REBOOT 3 + + #define FLOW_SENSOR_READING 0 + #define FLOW_SENSOR_OK 1 + #define FLOW_SENSOR_FAIL 2 + static u8 ucStatusSDP600=FLOW_SENSOR_READING; + static u8 ucStatusX201641=FLOW_SENSOR_READING; + + static volatile u8 ucReadingFlowSensor=START_READING_FLOW_SENSORS; // I2Cx sensor managment + static u8 ucCounterFlowErrorMeasurement=0; + static u16 uiTotalCounterFlowErrorMeasurement=0; + + #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) + #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW + #define SMOOTH_BLOWER_RAW_FLOW_COUNTER 50 + static u16 uiBlowerRAWFlowTemp[SMOOTH_BLOWER_RAW_FLOW_COUNTER]; + static u8 ucIndexBlowerRAWFlowSmooth=0; + + #define BLOWER_RAW_FLOW_SAMPLES_NUMBER 200 + static u32 ulSumBlowerFlowRAWMes=0; + static u16 uiBlowerRAWFlowSamplesCounter=BLOWER_RAW_FLOW_SAMPLES_NUMBER; + #endif + + #define SMOOTH_BLOWER_FLOW_LARGE_COUNTER 75//100 // MUST BE HIGHER THAN SMOOTH_BLOWER_FLOW_SMALL_COUNTER + #define SMOOTH_BLOWER_FLOW_SMALL_COUNTER 15 // MUST BE LOWER THAN SMOOTH_BLOWER_FLOW_LARGE_COUNTER + static int16_t iTempBlowerFlowForSmallSmooth[SMOOTH_BLOWER_FLOW_SMALL_COUNTER]; + static int16_t iTempBlowerFlowForLargeSmooth[SMOOTH_BLOWER_FLOW_LARGE_COUNTER]; + static u8 ucIndexSmallBlowerFlowSmooth=0; + static u8 ucIndexLargeBlowerFlowSmooth=0; + + static int16_t idConductancedtSmooth[SMOOTH_BLOWER_FLOW_SMALL_COUNTER]; + #endif // (SDP600_USED_I2C1_BUS) || (X201641_USED_I2C1_BUS) +#endif // C_M3_DEVICETEST_TARGET + + + +// ****************** PROXIMAL PRESSURE SENSOR MANAGEMENT ********************** +#ifndef C_M3_DEVICETEST_TARGET + #define SMOOTH_PPROX_PRESSURE_COUNTER 40 + static u8 ucIndexPproxPressureSmooth=0; + static u16 uiProximalPressureTemp[SMOOTH_PPROX_PRESSURE_COUNTER]; +#endif // C_M3_DEVICETEST_TARGET + + + +// ********************* MEASURES MANAGEMENT ********************************** +#ifndef C_M3_DEVICETEST_TARGET + // ---- Current measurement + static u32 ulSumCurrentADCMesFiltered=0; + static u32 ulCounterADC_FilteredBlowerCurrentMes=0; + + // ---- Temperature measurement + static u32 ulADCSumBlowerTemperature=0; + static u16 uiTemperatureSamplesCounter=0; + + #ifdef TEMPERATURE_TRENDS + #ifdef USE_FLOW_COMPUTER + #define FLOW_COMPUTER_CYCLE_DETECTION_TIMER 10 // 100ms + static u8 ucFlowComputerCycle=EXPIRATION_CYCLE; + static u16 uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; + #else + #define TIME_OUT_TEMPERATURE_MEASUREMENT 6000 // 60s + static u16 uiTimeOutTemperatureMeasurement=0; + #endif // #ifdef USE_FLOW_COMPUTER + static u32 ulADCSumTemperaturePhaseA=0; + static u16 uiADCTemperaturePhaseA; + static u32 ulADCSumTemperaturePhaseB=0; + static u16 uiADCTemperaturePhaseB; + static u32 ulADCSumTemperaturePhaseC=0; + static u16 uiADCTemperaturePhaseC; + #endif + + // ---- Blower Speed measurment + static u32 ulSumTachoTicks=0; + static u32 ulCounterAverageMotorSpeed=0; + + // --- Blower current Bessel filter + /*static u16 uiCurrentADCMesFilteredPrev2; + static u16 uiCurrentADCMesFilteredPrev1; + static u16 uiCurrentADCMesPrev2; + static u16 uiCurrentADCMesPrev1; + static u16 uiCurrentADCMesFiltered;*/ + + // --- Motor voltage + static u32 ulSumADC_MotorVoltage; + static u32 ulCounterADC_MotorVoltage; + + // --- Temporary measurements + static u16 uiPproxMax; + static u16 uiVtiTemp; + static u16 uiVteTemp; + static u16 uiTiMesTemp; + static u16 uiTeMesTemp; +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET + static u8 ucVentilationCycleCopy=INSPIRATION_CYCLE; + static int32_t lSumVti=0; + static int32_t lSumVte=0; + static u8 ucCounterAlarmVteMin=0; + static u8 ucCounterLPAlarm=0; +#endif // C_M3_DEVICETEST_TARGET + + +#define RCC_APB2RSTR (*(volatile uint32_t *)0x4002100c) + + +// ***************** Functions ********************************************** +int16_t ComputeFlowInLitersPerMin(u16 uFlowRAW, bool bPositiveFlow); +void ComputeBlowerPower(void); +u16 ComputeTemperature(u16 uiADCMotorTemp, u16 *puiTempLUT, u16 uiTemperatureGain); + + +/******************************************************************************* +* Function Name : ADC1_init +* Description : Init ADC1 +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ADC1_init(void) +{ + // First perform De_init + DMA_CCR1 &= (uint32_t)(~0x1); // channel 1 disable + DMA_CCR1 = 0; // Reset Channelx control register + DMA_CNTDR1 = 0; // Reset Channelx remaining bytes register + DMA_CPAR1 = 0; // Reset Channelx peripheral address register + DMA_CMAR1 = 0; // Reset Channelx memory address register + DMA_IFCR1 |= DMA_Channel1_IT_Mask; // Reset interrupt pending bits + // end de-init + + // Initialise DMA #1 + DMA_CPAR1 = (uint32_t)(ADC1_BASE + 0x4c); // base adress of ADC1 ADC_DR register + + DMA_CMAR1 = (unsigned long)(&uiADC_Value[0]); + DMA_CNTDR1 = NUMBER_ADC_CONVERSION; // numbers of data to be transfered + + DMA_CCR1 = (3<<12) + (1<<10) + (1<<8) + (1<<7) + (1<<5) /*+ (1<<1)*/; // very high priority, mem size 16 bits, periph size 16 bits, mem increase,/* circular enabled*/, /*transfer complete IT*/ + DMA_CCR1 |= 1; // channel 1 enable + + + + // De-init of the ADC 1 + RCC_APB2RSTR |= RCC_APB2Periph_ADC1; // enable + RCC_APB2RSTR &= ~RCC_APB2Periph_ADC1; // disable + // end De-init of the ADC 1 + + // Select channels of the regular group + #ifdef TEMPERATURE_TRENDS + ADC1_SQR1 = ((NUMBER_ADC_CONVERSION-1)<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; + ADC1_SQR2 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + TEMP_PHASE_C; + ADC1_SQR3 = (TEMP_PHASE_B<<25) + (TEMP_PHASE_A<<20) + (FREE_MEAS_CHANNEL<<15) + (CURRENT_MEAS_CHANNEL<<10) + (ALIM_24V_MEAS_CHANNEL<<5) + PPROX_MEAS_CHANNEL; + #else + ADC1_SQR1 = ((NUMBER_ADC_CONVERSION-1)<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; + ADC1_SQR2 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (FREE_MEAS_CHANNEL<<10) + (FREE_MEAS_CHANNEL<<5) + FREE_MEAS_CHANNEL; + ADC1_SQR3 = (FREE_MEAS_CHANNEL<<25) + (FREE_MEAS_CHANNEL<<20) + (FREE_MEAS_CHANNEL<<15) + (CURRENT_MEAS_CHANNEL<<10) + (ALIM_24V_MEAS_CHANNEL<<5) + PPROX_MEAS_CHANNEL; + #endif + + // 21 micros ADC conversion time + ADC1->SMPR2= (7<<27) + (7<<24) + (7<<21) + (7<<18) + (7<<15) + (7<<12) + (7<<9) + (7<<6) + (7<<3) + 7; + ADC1->SMPR1= (7<<21) + (7<<18) + (7<<15) + (7<<12) + (7<<9) + (7<<6) + (7<<3) + 7; + + ADC1_CR1 = (1<<8); // Scan mode enabled + ADC1_CR2 = (1<<8); // DMA mode enabled + + ADC1_CR2 |= 1; // start ADC1 - power-on + + // Delay at least 1uSec for ADC calibration/stabilisation. See ADC documentation + // Stabilization time > 1uS for ADC, between power-on and start of conversion + // Give it 10uSecs just to be sure. + Delay100NS(100); + + // Calibration of ADC1 + ADC1_CR2 |= (1<<3); // reset calibration registers + ADC1_CR2 |= (1<<2); // Enable calibration + while ((ADC1_CR2 & (1<<2)) == (1<<2)); // Wait end of calibration + + ADC1_CR2 |= 1; // start ADC1 - start conversions +} + + +/******************************************************************************* +* Function Name : CheckAlimMotorVoltage +* Description : Check the voltage range of the 24V power supply +* Input : None +* Output : None +* Return : OPSTATUS_OK or OPSTATUS_FAIL +*******************************************************************************/ +opstatus_t CheckAlimMotorVoltage(void) +{ + if (uiDCinADCMeas<271 || uiDCinADCMeas>2090) + return(OPSTATUS_FAIL); // <12V or >24V + return(OPSTATUS_OK); +} + + +/******************************************************************************* +* Function Name : Compute24VMeasure +* Description : Compute the 24V measure +* Input : None +* Output : None +* Return : OPSTATUS_OK or OPSTATUS_FAIL +*******************************************************************************/ +#ifndef C_M3_DEVICETEST_TARGET +void Compute24VMeasure(void) +{ + u32 ulTemp; + u16 uiADC_BlowerVoltage; + + if (bMemoStartVentilation==TRUE) + uiADC_BlowerVoltage=uiAverageADC_MotorVoltage; + else + uiADC_BlowerVoltage=uiDCinADCMeas; + + ulTemp=((u32)uiADC_BlowerVoltage*100)/1452; + ulTemp+=100; + uiTechnicalDataMes[MOTOR_VOLTAGE_TEC_MES]=(u16)ulTemp; + uiMotorVoltageMes=(u16)ulTemp; +} +#endif + +void GetFirstMotorVoltageReading(void) +{ + uiAverageADC_MotorVoltage=uiDCinADCMeas; +} +/******************************************************************************* +* Function Name : ComputeBlowerPower +* Description : Compute the power of the blower +* Input : None +* Output : None +* Return : OPSTATUS_OK or OPSTATUS_FAIL +*******************************************************************************/ +void ComputeBlowerPower(void) +{ + uiTechnicalDataMes[MOTOR_POWER_TEC_MES]=((u32)uiMotorVoltageMes*uiBlowerCurrentMes)/10; +} + +/******************************************************************************* +* Function Name : SpeedMeasurement +* Description : Return blower speed +* Input : Tacho counter +* Output : None +* Return : Blower speed in RPM +*******************************************************************************/ +u16 SpeedMeasurement(u16 uiTachoCounter) +{ + u16 uiSpeedTemp=65500; + + if (uiTachoCounter>915) + uiSpeedTemp=(u16)(60000000UL/uiTachoCounter); + + return(uiSpeedTemp); +} + + +/******************************************************************************* +* Function Name : ReadADCInputs +* Description : Read all ADC input (function calls every 1ms) +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ReadADCInputs(void) +{ + //u32 ulTerm1, ulTerm2, ulTerm3, ulTerm4, ulTerm5; + + // ADC Pprox measurement + uiProximalPressureADCMes=uiADC_Value[ADC_PPROX_MES]; + + // ADC DCin measurement + uiDCinADCMeas=uiADC_Value[ADC_DCIN_MES]; + + // ADC Blower current measurement + ComputeADCBlowerCurrent(FALSE); + + // ADC Free measurement + uiADCBlowerTemperatureMeas=uiADC_Value[ADC_FREE_MES]; + + #ifdef TEMPERATURE_TRENDS + uiADCTemperaturePhaseA=uiADC_Value[ADC_TEMP_PHASE_A]; + uiADCTemperaturePhaseB=uiADC_Value[ADC_TEMP_PHASE_B]; + uiADCTemperaturePhaseC=uiADC_Value[ADC_TEMP_PHASE_C]; + #endif + + // 2nd order Bessel Filter (Fcut-out=36Hz, sample rate=1KHz) + /*ulTerm1=(919UL*uiADCBlowerCurrent)>>6; + ulTerm2=(919UL*uiCurrentADCMesPrev1)>>5; + ulTerm3=(919UL*uiCurrentADCMesPrev2)>>6; + ulTerm4=(1427UL*uiCurrentADCMesFilteredPrev1)>>1; + ulTerm5=259UL*uiCurrentADCMesFilteredPrev2; + + uiCurrentADCMesFiltered=(ulTerm1+ulTerm2+ulTerm3+ulTerm4-ulTerm5)>>9; + uiCurrentADCMesFilteredPrev2=uiCurrentADCMesFilteredPrev1; + uiCurrentADCMesFilteredPrev1=uiCurrentADCMesFiltered; + uiCurrentADCMesPrev2=uiCurrentADCMesPrev1; + uiCurrentADCMesPrev1=uiADCBlowerCurrent;*/ + + + // 2nd order Bessel Filter (Fcut-out=150Hz, sample rate=1KHz) + /*ulTerm1=(1929UL*uiADCBlowerCurrent)>>1; + ulTerm2=(1929UL*uiCurrentADCMesPrev1); + ulTerm3=(1929UL*uiCurrentADCMesPrev2)>>1; + ulTerm4=(1095UL*uiCurrentADCMesFilteredPrev1)>>1; + ulTerm5=(2479UL*uiCurrentADCMesFilteredPrev2)>>3; + + uiCurrentADCMesFiltered=(ulTerm1+ulTerm2+ulTerm3+ulTerm4-ulTerm5)>>12; + uiCurrentADCMesFilteredPrev2=uiCurrentADCMesFilteredPrev1; + uiCurrentADCMesFilteredPrev1=uiCurrentADCMesFiltered; + uiCurrentADCMesPrev2=uiCurrentADCMesPrev1; + uiCurrentADCMesPrev1=uiADCBlowerCurrent;*/ + + // --- Start new conversions + ADC1->CR2 |= 1; +} + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ComputeMeasurements +* Description : Compute different measures +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeMeasurements(void) +{ + // ---------------------- Measure Current (A) ---------------------------- + uiBlowerCurrentMes=ComputeBlowerCurrentInAmper(uiADCBlowerCurrent); + + // -------------------- Compute motor voltage (V) ------------------------ + Compute24VMeasure(); + ComputeBlowerPower(); + + // ---------------------- Others measurements ---------------------------- + if (bMemoStartVentilation==TRUE) + { + // --- Motor speed (RPM) (every 10ms) + uiBlowerSpeedMes=SpeedMeasurement(uiTachoTimeTicks); + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET +#ifdef TEMPERATURE_TRENDS +/******************************************************************************* +* Function Name : ComputeAverageOnMeasurements +* Description : Average differents mesures : MUST BE CALLED EVERY 10ms +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeAverageOnMeasurements(void) +{ + #ifdef USE_FLOW_COMPUTER + // ----------- USE THE FLOW COMPUTER TO DETECT CYCLE ---------------- + u16 uiDummy; + opstatus_t opstatus; + + // Read new flow from flow computer every 10ms + opstatus=SS_Xgetw(flc, &uiDummy); + if (opstatus==OPSTATUS_OK) + { + // Update flow/pressure displayed + uiBlowerFlow=iFlowFromFlowComputer*10; + uiPoutPressureMes=uiPressureFromFlowComputer; + + // Comm with flow computer OK !! + #ifdef DATA_LOGGING + if (bRecordTemperatureTrendsAllowed==FALSE) + { + bRecordTemperatureTrendsAllowed=TRUE; + uiTrendsSampleTime=RECORD_TRENDS_SAMPLE_TIME; + } + #endif // DATA_LOGGING + + // inspiration/expiration cycle detection + if (ucFlowComputerCycle==EXPIRATION_CYCLE) + { + // Inspiration detection + if (iFlowFromFlowComputer>50) // 5l/min + { + uiFlowComputerCycleModificationTimer--; + if (uiFlowComputerCycleModificationTimer==0) + { + ucFlowComputerCycle=INSPIRATION_CYCLE; + + // Compute temperature of the previous inspiratory cycle + if (uiTemperatureSamplesCounter!=0) + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); + uiADCAverageTemperaturePhaseA=ulADCSumTemperaturePhaseA/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseB=ulADCSumTemperaturePhaseB/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseC=ulADCSumTemperaturePhaseC/uiTemperatureSamplesCounter; + } + ulADCSumBlowerTemperature=0; + ulADCSumTemperaturePhaseA=0; + ulADCSumTemperaturePhaseB=0; + ulADCSumTemperaturePhaseC=0; + uiTemperatureSamplesCounter=0; + } + } + else + uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; + } + else + { + // Record temperature as long as the flow is positive + if (iFlowFromFlowComputer>(-10)) // >-1l/min + { + ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; + ulADCSumTemperaturePhaseA+=uiADCTemperaturePhaseA; + ulADCSumTemperaturePhaseB+=uiADCTemperaturePhaseB; + ulADCSumTemperaturePhaseC+=uiADCTemperaturePhaseC; + uiTemperatureSamplesCounter++; + } + + // Expiration detection + if (iFlowFromFlowComputer<(-50)) // <-5l/min + { + uiFlowComputerCycleModificationTimer--; + if (uiFlowComputerCycleModificationTimer==0) + ucFlowComputerCycle=EXPIRATION_CYCLE; + } + else + uiFlowComputerCycleModificationTimer=FLOW_COMPUTER_CYCLE_DETECTION_TIMER; + } + } + else if (opstatus==OPSTATUS_FAIL) + { + // Comm Failure with flow computer => no data recorded + uiBlowerFlow=0; + uiPoutPressureMes=0; + + #ifdef DATA_LOGGING + bRecordTemperatureTrendsAllowed=FALSE; + #endif + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=0; + } + #else + // ----------- USE THE 24V MEASURE TO DETECT CYCLE ---------------- + if (uiDCinADCMeas>500) + { + // Inspiration + ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; + ulADCSumTemperaturePhaseA+=uiADCTemperaturePhaseA; + ulADCSumTemperaturePhaseB+=uiADCTemperaturePhaseB; + ulADCSumTemperaturePhaseC+=uiADCTemperaturePhaseC; + uiTemperatureSamplesCounter++; + uiTimeOutTemperatureMeasurement=TIME_OUT_TEMPERATURE_MEASUREMENT; + #ifdef DATA_LOGGING + bRecordTemperatureTrendsAllowed=TRUE; + #endif + } + else if (uiTimeOutTemperatureMeasurement!=0) + { + // Expiration + uiTimeOutTemperatureMeasurement--; + if (uiTemperatureSamplesCounter!=0) + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); + uiADCAverageTemperaturePhaseA=ulADCSumTemperaturePhaseA/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseB=ulADCSumTemperaturePhaseB/uiTemperatureSamplesCounter; + uiADCAverageTemperaturePhaseC=ulADCSumTemperaturePhaseC/uiTemperatureSamplesCounter; + } + ulADCSumBlowerTemperature=0; + ulADCSumTemperaturePhaseA=0; + ulADCSumTemperaturePhaseB=0; + ulADCSumTemperaturePhaseC=0; + uiTemperatureSamplesCounter=0; + } + else + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=0; + + ulADCSumBlowerTemperature=0; + ulADCSumTemperaturePhaseA=0; + ulADCSumTemperaturePhaseB=0; + ulADCSumTemperaturePhaseC=0; + uiTemperatureSamplesCounter=0; + + #ifdef DATA_LOGGING + bRecordTemperatureTrendsAllowed=FALSE; + #endif + } + #endif // #ifdef USE_FLOW_COMPUTER +} +#endif // #ifdef TEMPERATURE_TRENDS +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +/******************************************************************************* +* Function Name : ComputeADCBlowerCurrent +* Description : Compute the average current during a PWM cycle (20micros) +* Input : bRecordCurrentOffset +* Output : None +* Return : None +*******************************************************************************/ +void ComputeADCBlowerCurrent(bool bRecordCurrentOffset) +{ + if (bRecordCurrentOffset==TRUE) + { + uiADCOffsetBlowerCurrent=uiADCBlowerCurrent=uiADC_Value[ADC_CURRENT_MES]; + } + else + { + uiADCBlowerCurrent=uiADC_Value[ADC_CURRENT_MES]; + } +} + + +/******************************************************************************* +* Function Name : ComputeBlowerCurrentInAmper +* Description : Return blower current value in cAmper (ex: 100=1.00A) +* Input : ADC value +* Output : None +* Return : Blower current in cAmper (ex: 100=1.00A) +*******************************************************************************/ +int16_t ComputeBlowerCurrentInAmper(u16 uiADCBlowerCurrentLocal) +{ + int32_t lTempValue; + + // Computation using MOT_CUR_MEAS2 + lTempValue=(int32_t)uiADCBlowerCurrentLocal-(int32_t)uiADCOffsetBlowerCurrent; + lTempValue*=1000; + lTempValue/=uiTechnicalDataSet[GAIN_BLOWER_CURRENT_TEC]; + return(lTempValue); +} + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : LaunchFlowReadingOnI2CBus +* Description : Open and Read the flow sensor(s) on the I2C bus +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void LaunchFlowReadingOnI2CBus(void) +{ + opstatus_t byOpStatus; + u16 uiSensorErr; + + if (fOpenI2C1SDP600Sensors==FALSE || fOpenI2C2SDP600Sensors==FALSE || + fOpenI2C1X201641Sensors==FALSE || fOpenI2C2X201641Sensors==FALSE) + { + byOpStatus=SS_Xopen(I2C_SDP600); + if (byOpStatus==OPSTATUS_FAIL) + uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; + + byOpStatus=SS_Xopen(I2C_X201641); + if (byOpStatus==OPSTATUS_FAIL) + uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; + + ucReadingFlowSensor=STOP_READING_FLOW_SENSORS; + } + else if (ucReadingFlowSensor==STOP_READING_FLOW_SENSORS) + { + ucReadingFlowSensor=START_READING_FLOW_SENSORS; + } + else if (ucReadingFlowSensor==READING_FLOW_SENSORS) + { + // Reading SDP600 Flow sensors + if (ucStatusSDP600==FLOW_SENSOR_READING) + { + byOpStatus=SS_Xgetw(I2C_SDP600, &uiSensorErr); + if (byOpStatus==OPSTATUS_OK) + ucStatusSDP600=FLOW_SENSOR_OK; + else if (byOpStatus==OPSTATUS_FAIL) + ucStatusSDP600=FLOW_SENSOR_FAIL; + } + + // Reading X201641 Flow sensors + if (ucStatusX201641==FLOW_SENSOR_READING) + { + byOpStatus=SS_Xgetw(I2C_X201641, &uiSensorErr); + if (byOpStatus==OPSTATUS_OK) + ucStatusX201641=FLOW_SENSOR_OK; + else if (byOpStatus==OPSTATUS_FAIL) + ucStatusX201641=FLOW_SENSOR_FAIL; + } + + // End of flow measurement? + if (ucStatusSDP600!=FLOW_SENSOR_READING && ucStatusX201641!=FLOW_SENSOR_READING) + { + if (ucStatusSDP600==FLOW_SENSOR_OK && ucStatusX201641==FLOW_SENSOR_OK) + { + ucCounterFlowErrorMeasurement=0; + #ifdef TIME_MEASUREMENT + GPIOB->BRR = GPIO_Pin_5; + #endif + } + else + { + // Error counters + uiTotalCounterFlowErrorMeasurement++; + ucCounterFlowErrorMeasurement++; + if (ucCounterFlowErrorMeasurement>=NUMBER_I2C_REBOOT) + { + //ulErrorCounter|=uiSensorErr; + uiFlagsAlarm[ALARM_FLAGS2]|=FLOW_SENSOR_FAILURE_ALARM_MASK; + } + } + + // Next Sensors to measure + ucReadingFlowSensor=READING_NO_SENSOR; + ucStatusSDP600=FLOW_SENSOR_READING; + ucStatusX201641=FLOW_SENSOR_READING; + } + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ComputeFlowMeasurement +* Description : Conpute inspiratory and erxpiratory flow measurements +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeFlowMeasurement(void) +{ + #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) + int32_t lValue; + u16 uiValue; + #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW + u32 ulValue; + #endif + #endif + + if (ucReadingFlowSensor==START_READING_FLOW_SENSORS) + { + ucReadingFlowSensor=READING_FLOW_SENSORS; + } + else if (ucReadingFlowSensor==READING_NO_SENSOR) + { + ucReadingFlowSensor=READING_FLOW_SENSORS; + + // **** Reading of the Inspiratory RAW Flow + #if defined(SDP600_USED_I2C1_BUS) || defined(X201641_USED_I2C1_BUS) + #ifdef SDP600_USED_I2C1_BUS + SDP600_ReadADCFlowValue(I2C1, SDP600_BLOWER_FLOW_SENSOR, &uiValue); + #endif + #ifdef X201641_USED_I2C1_BUS + X201641_ReadADCFlowValue(I2C1, X201641_BLOWER_FLOW_SENSOR, &uiValue); + #endif + if (uiValue==uiTechnicalDataSet[FLOWI_OFFSET_TEC]) + { + uiBlowerFlowRAWMes=0; + iBlowerFlowMes=0; + } + else if (uiValue>uiTechnicalDataSet[FLOWI_OFFSET_TEC]) + { + uiBlowerFlowRAWMes=uiValue-uiTechnicalDataSet[FLOWI_OFFSET_TEC]; + iBlowerFlowMes=ComputeFlowInLitersPerMin(uiBlowerFlowRAWMes, FALSE); + } + else + { + uiBlowerFlowRAWMes=uiTechnicalDataSet[FLOWI_OFFSET_TEC]-uiValue; + iBlowerFlowMes=ComputeFlowInLitersPerMin(uiBlowerFlowRAWMes, TRUE); + } + + // Smoothing RWA data signals + #ifdef DISPLAY_AVERAGE_BLOWER_RAW_FLOW + uiBlowerRAWFlowTemp[ucIndexBlowerRAWFlowSmooth]=uiBlowerFlowRAWMes; + ulValue=0; + for (uiValue=0; uiValue<SMOOTH_BLOWER_RAW_FLOW_COUNTER; uiValue++) + ulValue+=uiBlowerRAWFlowTemp[uiValue]; + uiBlowerFlowRAWSmoothingMes=ulValue/SMOOTH_BLOWER_RAW_FLOW_COUNTER; + ucIndexBlowerRAWFlowSmooth++; + if (ucIndexBlowerRAWFlowSmooth>=SMOOTH_BLOWER_RAW_FLOW_COUNTER) + ucIndexBlowerRAWFlowSmooth=0; + + // Average of the RAW data signal + ulSumBlowerFlowRAWMes+=uiBlowerFlowRAWSmoothingMes; + uiBlowerRAWFlowSamplesCounter--; + if (uiBlowerRAWFlowSamplesCounter==0) + { + uiAverageBlowerFlowRAWMes=ulSumBlowerFlowRAWMes/BLOWER_RAW_FLOW_SAMPLES_NUMBER; + ulSumBlowerFlowRAWMes=0; + uiBlowerRAWFlowSamplesCounter=BLOWER_RAW_FLOW_SAMPLES_NUMBER; + } + #endif // DISPLAY_AVERAGE_BLOWER_RAW_FLOW + + + // **** Reading of the Inspiratory Flow in l/min + /*#ifdef SDP600_USED_I2C1_BUS + SDP600_CalculFlowValue(I2C1, SDP600_BLOWER_FLOW_SENSOR, &iBlowerFlowMes); + #endif + #ifdef X201641_USED_I2C1_BUS + X201641_CalculFlowValue(I2C1, X201641_BLOWER_FLOW_SENSOR, &iBlowerFlowMes); + #endif*/ + iTempBlowerFlowForSmallSmooth[ucIndexSmallBlowerFlowSmooth]=iBlowerFlowMes; + iTempBlowerFlowForLargeSmooth[ucIndexLargeBlowerFlowSmooth]=iBlowerFlowMes; + + // Small Smoothing of the inspiratory flow signal + lValue=0; + for (uiValue=0; uiValue<SMOOTH_BLOWER_FLOW_SMALL_COUNTER; uiValue++) + lValue+=iTempBlowerFlowForSmallSmooth[uiValue]; + iBlowerFlowSmoothingMes=lValue/(int16_t)SMOOTH_BLOWER_FLOW_SMALL_COUNTER; + ucIndexSmallBlowerFlowSmooth++; + if (ucIndexSmallBlowerFlowSmooth>=SMOOTH_BLOWER_FLOW_SMALL_COUNTER) + ucIndexSmallBlowerFlowSmooth=0; + + // Large Smoothing of the inspiratory flow signal + lValue=0; + for (uiValue=0; uiValue<SMOOTH_BLOWER_FLOW_LARGE_COUNTER; uiValue++) + lValue+=iTempBlowerFlowForLargeSmooth[uiValue]; + iBlowerFlowSmoothingMesForTrigger=lValue/(int16_t)SMOOTH_BLOWER_FLOW_LARGE_COUNTER; + ucIndexLargeBlowerFlowSmooth++; + if (ucIndexLargeBlowerFlowSmooth>=SMOOTH_BLOWER_FLOW_LARGE_COUNTER) + ucIndexLargeBlowerFlowSmooth=0; + + // Flow for Optima Comm + uiBlowerFlow=iBlowerFlowMes; + uiBlowerFlowSmoothingMes=iBlowerFlowSmoothingMes; + uiBlowerFlowTriggerMes=iBlowerFlowSmoothingMesForTrigger; + #endif // (SDP600_USED_I2C1_BUS) || (X201641_USED_I2C1_BUS) + } + +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +double powApprox(double a, double x) +{ + union + { + double d; + int A[2]; + } Z = { a }; + Z.A[1] = (int)(x * (Z.A[1] - 1072632447) + 1072632447); + Z.A[0] = 0; + return Z.d; +} +/******************************************************************************* +* Function Name : ComputeConductance +* Description : Compute Conductance +* Input : Pressure, Flow +* Output : Conductance +* Return : None +*******************************************************************************/ +float prevConductance = 0.0f; +u8 bufferIndex = 0; +bool filled = FALSE; +int16_t littleSum = 0; + +void ComputeConductance(void) +{ + float pressure = iProximalPressureMes/10.0f; + float flow = iBlowerFlowSmoothingMes/100.0f/60.0f; + float density = 1.225f; + float viscosity = 0.00018f; + float calcConductance = 0.0f; + + if(pressure != 0) + { + calcConductance = (100000)*((powApprox((flow*0.001f),1.75)*powApprox(density,0.75)*powApprox(viscosity,0.25)/(pressure / 10.0f)* 98.0638f)); + calcConductance = calcConductance * 1000.0f; + if(calcConductance < 60000 && calcConductance > -60000) + { + uiConductanceCalc = (int16_t)calcConductance; + } + } +// int16_t tempValue = idConductancedtSmooth[bufferIndex]; +// idConductancedtSmooth[bufferIndex]= (int16_t)(calcConductance - prevConductance);//1000; +// littleSum += idConductancedtSmooth[bufferIndex]; +// bufferIndex++; +// if(bufferIndex > SMOOTH_BLOWER_FLOW_LARGE_COUNTER) +// { +// bufferIndex = 0; +// if(!filled) +// { +// filled = TRUE; +// } +// } +// +// if(filled) +// { +// littleSum -= tempValue; +// uidConductanceCalcdt = littleSum/SMOOTH_BLOWER_FLOW_LARGE_COUNTER; +// } + uidConductanceCalcdt = (int16_t)(calcConductance - prevConductance); + prevConductance = calcConductance; +} +/******************************************************************************* +* Function Name : ComputeProximalPressureMeasurements +* Description : Compute Proximal pressure measurements +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeProximalPressureMeasurements(void) +{ + u32 ulValue; + u16 uiValue; + + iProximalPressureMes=((100L*((int16_t)uiProximalPressureADCMes-(int16_t)uiTechnicalDataSet[PPROX_OFFSET_TEC]))/(int16_t)uiTechnicalDataSet[PPROX_GAIN_TEC]); + if (iProximalPressureMes>0) + uiProximalPressureMes=(u16)iProximalPressureMes; + else + uiProximalPressureMes=0; + uiNegativeProximalPressureMes=iProximalPressureMes; + + // Smoothing proximal pressure + uiProximalPressureTemp[ucIndexPproxPressureSmooth]=uiProximalPressureMes; + ulValue=0; + for (uiValue=0; uiValue<SMOOTH_PPROX_PRESSURE_COUNTER; uiValue++) + ulValue+=uiProximalPressureTemp[uiValue]; + uiProximalPressureSmoothingMes=ulValue/SMOOTH_PPROX_PRESSURE_COUNTER; + + ucIndexPproxPressureSmooth++; + if (ucIndexPproxPressureSmooth>=SMOOTH_PPROX_PRESSURE_COUNTER) + ucIndexPproxPressureSmooth=0; +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ComputeOffsetProximalPressureSensor +* Description : Compute offset of the proximal pressure sensor +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ComputeOffsetProximalPressureSensor(void) +{ + u32 ulOffsetSum=0; + u16 i; + + for (i=0; i<64; i++) + { + ulOffsetSum+=uiADC_Value[ADC_PPROX_MES]; + uiTempoSysTick=5; + while (uiTempoSysTick!=0){} + } + uiTechnicalDataSet[PPROX_OFFSET_TEC]=ulOffsetSum>>6; +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : VentilationMonitoringAndAlarms +* Description : Compute measurements and alarms during ventilation +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void VentilationMonitoringAndAlarms(void) +{ + u16 uiTotalTimeMes; + + if (bMemoStartVentilation==TRUE && uiTechnicalDataSet[DEVICE_MODE_TEC]==VENTILATION_MODE) + { + if (ucVentilationCycle==INSPIRATION_CYCLE) + { + // ***************** INSPIRATION ****************** + if (ucVentilationCycleCopy==EXPIRATION_CYCLE) + { + // --- Beginning of inspiration + ucVentilationCycleCopy=INSPIRATION_CYCLE; + SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_ON); + + // Update Vte measurement + uiVentilationMeasures[VTE_MES]=uiVteTemp; + + // Update Te measurement + uiVentilationMeasures[TE_MES]=uiTeMesTemp; + + // Update Average ADC Motor Voltage + if (ulCounterADC_MotorVoltage!=0) + uiAverageADC_MotorVoltage=ulSumADC_MotorVoltage/ulCounterADC_MotorVoltage; + + // Update Current measurement + if (ulCounterADC_FilteredBlowerCurrentMes!=0) + uiBreathBlowerCurrentMes=ComputeBlowerCurrentInAmper(ulSumCurrentADCMesFiltered/ulCounterADC_FilteredBlowerCurrentMes); + ulSumCurrentADCMesFiltered=0; ulCounterADC_FilteredBlowerCurrentMes=0; + + // Update average blower speed + if (ulCounterAverageMotorSpeed!=0) + uiAverageBlowerSpeedMes=SpeedMeasurement(ulSumTachoTicks/ulCounterAverageMotorSpeed); + ulSumTachoTicks=0; + ulCounterAverageMotorSpeed=0; + + // Update average motor temperature during inspiration + if (uiTemperatureSamplesCounter!=0) + { + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(ulADCSumBlowerTemperature/uiTemperatureSamplesCounter); + if (uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]>890) + uiFlagsAlarm[ALARM_FLAGS2]|=MOTOR_TEMPERATURE_ALARM_MASK; + else if (uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]<810) + uiFlagsAlarm[ALARM_FLAGS2]&=(~MOTOR_TEMPERATURE_ALARM_MASK); + } + ulADCSumBlowerTemperature=0; uiTemperatureSamplesCounter=0; + + // --- Pmax=0 + uiPproxMax=0; + + // --- Vti=0 + lSumVti=0; + uiRecordVtiMes=uiVentilationMeasures[VTI_MES]; + + // --- Dislay Breath rate + uiTotalTimeMes=uiVentilationMeasures[TI_MES]+uiVentilationMeasures[TE_MES]; + if (uiTotalTimeMes>0) + uiVentilationMeasures[BREATH_RATE_MES]=600000/uiTotalTimeMes; + + // --- Ti=0 + uiTiMesTemp=0; + + // --- Max flow + iBlowerFlowSmoothingMaxMes=0; + + // --- Alarm Vte Min + if (uiVentilationMeasures[VTE_MES]<uiVentilationSet[VTE_MIN_ALARM_SET] && enVentilationMode!=CPAP_MODE) + { + ucCounterAlarmVteMin++; + if (ucCounterAlarmVteMin>=5) + { + ucCounterAlarmVteMin=5; + uiFlagsAlarm[ALARM_FLAGS1]|=LOW_VTE_ALARM_MASK; + } + } + else + { + ucCounterAlarmVteMin=0; + uiFlagsAlarm[ALARM_FLAGS1]&=(~LOW_VTE_ALARM_MASK); + } + } + else //if (ucVentilationCycle==EXPIRATION_CYCLE) + { + // --- During inspiration + + // --- Motor Speed + ulSumTachoTicks+=uiTachoTimeTicks; + ulCounterAverageMotorSpeed++; + + // --- Blower Current + ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; + ulCounterADC_FilteredBlowerCurrentMes++; + + // --- Inc Pmax + if (uiProximalPressureMes>uiPproxMax) + uiPproxMax=uiProximalPressureMes; + + // --- Inc max flow + if (iBlowerFlowSmoothingMes>iBlowerFlowSmoothingMaxMes) + iBlowerFlowSmoothingMaxMes=iBlowerFlowSmoothingMes; + + // --- Inc Vti + if (iBlowerFlowMes>30) + lSumVti+=iBlowerFlowMes; + uiVtiTemp=(u32)lSumVti/6000; + + // --- Inc Ti + uiTiMesTemp++; + + // --- Motor temperature + ulADCSumBlowerTemperature+=uiADCBlowerTemperatureMeas; + uiTemperatureSamplesCounter++; + + // --- Alarm Pmax + if (uiProximalPressureMes>uiVentilationSet[HIGH_PRESSURE_ALARM_SET] && enVentilationMode!=CPAP_MODE) + { + uiFlagsAlarm[ALARM_FLAGS1]|=HIGH_PRESSURE_ALARM_MASK; + fAlarmPmax=TRUE; + } + + // --- Alarm Vti Max + if ((uiVtiTemp>uiVentilationSet[VTI_MAX_ALARM_SET] && enVentilationMode==PS_MODE) || + (uiVtiTemp>uiVentilationSet[VTI_MAX_ALARM_SET] && enVentilationMode==APCV_MODE)) + { + uiFlagsAlarm[ALARM_FLAGS1]|=HIGH_VTI_ALARM_MASK; + fAlarmVtiMax=TRUE; + } + } + } + else + { + // ***************** EXPIRATION ****************** + if (ucVentilationCycleCopy==INSPIRATION_CYCLE) + { + // --- Beginning of Expiration + ucVentilationCycleCopy=EXPIRATION_CYCLE; + SS_Xputdw(act, EV_CTL|FLAG_ACTIONER_OFF); + + // Update Pprox max measurement + uiVentilationMeasures[PPROX_MAX_MES]=uiPproxMax; + + // Update Vti measurement + uiVentilationMeasures[VTI_MES]=uiVtiTemp; + + // Update Ti measurement + uiVentilationMeasures[TI_MES]=uiTiMesTemp; + + // --- Motor Speed + ulSumTachoTicks+=uiTachoTimeTicks; + ulCounterAverageMotorSpeed++; + + // --- Blower Current + ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; + ulCounterADC_FilteredBlowerCurrentMes++; + + // --- Vte=0 + lSumVte=0; + + // --- Te=0 + uiTeMesTemp=0; + + // --- Alarm Low Pressure + if ((uiVentilationMeasures[PPROX_MAX_MES]<(uiVentilationSet[PS_SET]-5) && enVentilationMode==PS_MODE) || + (uiVentilationMeasures[PPROX_MAX_MES]<(uiVentilationSet[PI_SET]-5) && enVentilationMode==APCV_MODE) || + (uiVentilationMeasures[PPROX_MAX_MES]<uiVentilationSet[LOW_PRESSURE_ALARM_SET] && enVentilationMode==AVC_MODE)) + { + ucCounterLPAlarm++; + if (ucCounterLPAlarm>=4) + { + ucCounterLPAlarm=4; + uiFlagsAlarm[ALARM_FLAGS1]|=LOW_PRESSURE_ALARM_MASK; + } + } + else + { + ucCounterLPAlarm=0; + uiFlagsAlarm[ALARM_FLAGS1]&=(~LOW_PRESSURE_ALARM_MASK); + } + + // --- Clear Alarm High pressure + if (fAlarmPmax==FALSE) + uiFlagsAlarm[ALARM_FLAGS1]&=(~HIGH_PRESSURE_ALARM_MASK); + fAlarmPmax=FALSE; + + // --- Clear Alarm Vti Max + if (fAlarmVtiMax==FALSE) + uiFlagsAlarm[ALARM_FLAGS1]&=(~HIGH_VTI_ALARM_MASK); + fAlarmVtiMax=FALSE; + } + else + { + // --- During Expiration + + // --- Motor Speed + ulSumTachoTicks+=uiTachoTimeTicks; + ulCounterAverageMotorSpeed++; + + // --- Blower Current + ulSumCurrentADCMesFiltered+=uiADCBlowerCurrent; + ulCounterADC_FilteredBlowerCurrentMes++; + + // --- Inc Vte + if (iBlowerFlowMes<(-30)) + lSumVte+=iBlowerFlowMes; + if (lSumVte<0) + uiVteTemp=(u32)(lSumVte/(-6000)); + else + uiVteTemp=0; + + // --- Inc Te + uiTeMesTemp++; + if (uiTeMesTemp>60000) uiTeMesTemp=60000; + + // --- Average motor voltage + if (uiTeMesTemp==100) + { + ulSumADC_MotorVoltage=0; + ulCounterADC_MotorVoltage=0; + } + else if (uiTeMesTemp>100) + { + ulSumADC_MotorVoltage+=uiDCinADCMeas; + ulCounterADC_MotorVoltage++; + } + } + } + } + else // if (bMemoStartVentilation==TRUE && uiTechnicalDataSet[DEVICE_MODE_TEC]==VENTILATION_MODE) + { + #ifndef TEMPERATURE_TRENDS + uiTechnicalDataMes[MOTOR_TEMPERATURE_TEC_MES]=ComputeMotorTemperature(uiADCBlowerTemperatureMeas); + #endif + } +} +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +#ifndef C_M3_DEVICETEST_TARGET +/******************************************************************************* +* Function Name : ClearVentilationAlarm +* Description : Clear all ventilation Alarms +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ClearAllVentilationAlarms(void) +{ + u8 i; + u8 ucAlarmFlag; + + for (i=0; i<SIZE_BLOWER_ALARM; i++) + { + ucAlarmFlag=stBlowerAlarmStatus[i].ucAlarmFlag; + if (stBlowerAlarmStatus[i].bVentilationAlarm==TRUE && (ucAlarmFlag==ALARM_FLAGS1 || ucAlarmFlag==ALARM_FLAGS2)) + uiFlagsAlarm[ucAlarmFlag]&=(~stBlowerAlarmStatus[i].uiAlarmMask); + } +} + + +/******************************************************************************* +* Function Name : ClearAlarm +* Description : Clear a specific alarm +* Input : Mask of the alarm +* Output : None +* Return : None +*******************************************************************************/ +void ClearAlarm(u8 ucAlarmFlag, u16 uiMask) +{ + uiFlagsAlarm[ucAlarmFlag]&=(~uiMask); +} + + +/******************************************************************************* +* Function Name : ClearAllMeasures +* Description : Clear all ventilation measures +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +void ClearAllMeasures(void) +{ + u8 i; + + // Reset measures except alarms + for (i=0; i<SIZE_LRM_GROUP; i++) + { + if (i!=ALARM_ID1_MES && i!=ALARM_ID2_MES)// && i!=ALARM_ID3_MES && i!=ALARM_ID4_MES) + uiVentilationMeasures[i]=0; + } + + // Reset others measures + uiBlowerSpeedMes=0; uiAverageBlowerSpeedMes=0; // Speed=0 RPM + ulSumTachoTicks=0; ulCounterAverageMotorSpeed=0; + uiBreathBlowerCurrentMes=0; // Blower current=0 A + ulSumCurrentADCMesFiltered=0; ulCounterADC_FilteredBlowerCurrentMes=0; + bDisplayInspiratoryTrigger=FALSE; + #ifdef MOTOR_LIFE_TESTING + uiAverateMotorTempMes=0; + #endif // #ifdef MOTOR_LIFE_TESTING + + // Init temporary variables + ucVentilationCycleCopy=INSPIRATION_CYCLE; + uiPproxMax=0; + uiVtiTemp=0; + uiTiMesTemp=0; + ucCounterLPAlarm=0; + fAlarmPmax=FALSE; + fAlarmVtiMax=FALSE; + ucCounterAlarmVteMin=0; +} + + +/******************************************************************************* +* Function Name : ReadStopVentilationAlarmNumber +* Description : Read the alarm number which stops the ventilation +* Input : None +* Output : None +* Return : alarm number +*******************************************************************************/ +u8 ReadStopVentilationAlarmNumber(void) +{ + u16 uiMask; + u8 i; + u8 ucAlarmNumber=SIZE_BLOWER_ALARM; + + // Check Alarm which stops ventilation + if (uiFlagsAlarm[ALARM_FLAGS1]!=0 || + uiFlagsAlarm[ALARM_FLAGS2]!=0) + /*uiFlagsAlarm[ALARM_FLAGS3]!=0 || + uiFlagsAlarm[ALARM_FLAGS4]!=0)*/ + { + for (i=0; i<SIZE_BLOWER_ALARM; i++) + { + if (stBlowerAlarmStatus[i].bForceVentilToStop==TRUE) + { + uiMask=stBlowerAlarmStatus[i].uiAlarmMask; + if ((uiFlagsAlarm[stBlowerAlarmStatus[i].ucAlarmFlag]&uiMask)==uiMask) + { + ucAlarmNumber=i; + break; + } + } + } + } + return(ucAlarmNumber); +} + + +/******************************************************************************* +* Function Name : UpdateAlarmsMeasureID +* Description : Update the alarms ventilation measure variables +* Input : None +* Output : None +* Return : alarm number +*******************************************************************************/ +#ifdef USE_OPTIMACOMM +void UpdateAlarmsMeasureID(void) +{ + uiVentilationMeasures[ALARM_ID1_MES]=uiFlagsAlarm[ALARM_FLAGS1]; + uiVentilationMeasures[ALARM_ID2_MES]=uiFlagsAlarm[ALARM_FLAGS2]; +} +#endif // #ifdef USE_OPTIMACOMM +#endif // #ifndef C_M3_DEVICETEST_TARGET + + +/******************************************************************************* +* Function Name : ComputeMotorTemperature +* Description : Return temperature (in degres C) +* Input : uiADCMotorTemp : ADC value +* Output : None +* Return : None +*******************************************************************************/ +u16 ComputeMotorTemperature(u16 uiADCMotorTemp) +{ + u16 uiTemp, uiTempDec; + u32 ulTemp; + + for (uiTemp=0; uiTemp<121; uiTemp++) + { + if (uiADCMotorTemp>=uiADCMotorTempTable[uiTemp]) + break; + } + + if (uiADCMotorTemp<uiADCMotorTempTable[120]) + return(1200); + else if (uiADCMotorTemp>=uiADCMotorTempTable[0]) + return(0); + else if (uiADCMotorTemp==uiADCMotorTempTable[uiTemp]) + ulTemp=uiTemp*10; + else + { + uiTempDec=((uiADCMotorTempTable[uiTemp-1]-uiADCMotorTemp)*10)/(uiADCMotorTempTable[uiTemp-1]-uiADCMotorTempTable[uiTemp]); + ulTemp=((uiTemp-1)*10)+uiTempDec; + } + + ulTemp*=1000; + ulTemp/=uiTechnicalDataSet[GAIN_BLOWER_TEMP_TEC]; + return((u16)ulTemp); +} + + +/******************************************************************************* +* Function Name : ComputeFlowInLitersPerMin +* Description : Compute the flow in l/min +* Input : uFlowRAW : flow digital value, bPositiveFlow= TRUE if positive flow +* Output : None +* Return : signed Flow in l/min +*******************************************************************************/ +int16_t ComputeFlowInLitersPerMin(u16 uiFlowRAW, bool bPositiveFlow) +{ + u16 uiIndex; + int16_t iFlow; + u32 a; + int32_t b; + int32_t y; + + for (uiIndex=0; uiIndex<stLUTFlowSensor.uiLUT_TableSize; uiIndex++) + { + if (uiFlowRAW==stLUTFlowSensor.uiFlowSensorTicks[uiIndex]) + { + iFlow=(int16_t)stLUTFlowSensor.uiFlowValue[uiIndex]; + break; + } + else if (uiFlowRAW<stLUTFlowSensor.uiFlowSensorTicks[uiIndex]) + { + if (uiIndex==0) + { + iFlow=(int16_t)(((u32)uiFlowRAW*stLUTFlowSensor.uiFlowValue[uiIndex])/stLUTFlowSensor.uiFlowSensorTicks[uiIndex]); + } + else + { + a=(100UL*(stLUTFlowSensor.uiFlowValue[uiIndex]-stLUTFlowSensor.uiFlowValue[uiIndex-1]))/(stLUTFlowSensor.uiFlowSensorTicks[uiIndex]-stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]); + b=((int32_t)stLUTFlowSensor.uiFlowValue[uiIndex-1]*100)-((int32_t)stLUTFlowSensor.uiFlowSensorTicks[uiIndex-1]*a); + y=((int32_t)a*(int32_t)uiFlowRAW)+b; + iFlow=(int16_t)(y/100); + } + break; + } + else + { + iFlow=(int16_t)stLUTFlowSensor.uiFlowValue[uiIndex]; + } + } + + if (bPositiveFlow==FALSE) + iFlow*=(-1); + + return(iFlow); +} + +/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ + + +