CQ Publishing
/
tg_201410s6_Plethysmographs
トランジスタ技術2014年10月号第6章のソフトウェア
Embed:
(wiki syntax)
Show/hide line numbers
PulseRate.cpp
Go to the documentation of this file.
00001 /** 00002 * @file PulseRate.cpp 00003 * @brief Calculate pulse waveform and pulse rate 00004 * @date 2014.08.08 00005 * @version 1.0.0 00006 */ 00007 #include "PulseRate.h" 00008 00009 /** Constructor 00010 * @param sensor Pin for A/D converter 00011 * @param sync_led Pin for synchronous LED 00012 * @param beep Pin for piezo sounder 00013 */ 00014 PulseRate::PulseRate(PinName sensor, PinName sync_led, PinName beep) : 00015 _sensor(sensor), _sync_led(sync_led), _beep(beep) { 00016 00017 _sync_led = LED_OFF; 00018 _val = 0; 00019 _wave_flag = false; 00020 _pr_flag = false; 00021 _sampling_num = 0; 00022 _mv_idx = 0; 00023 _beep.period(1.0/BEEP_FREQ); 00024 } 00025 00026 /** Start interval timer 00027 */ 00028 void PulseRate::start_sampling() { 00029 _sampling.attach(this, &PulseRate::interval_timer, SAMPLING_RATE); 00030 } 00031 00032 /** Get waveform data 00033 * @param &num Sampling number 00034 * @param &wave_val Waveform value 00035 * @retval true Ready for data 00036 * @retval false Not ready 00037 */ 00038 bool PulseRate::get_wave(uint32_t &num, int32_t &wave_val) { 00039 if(_wave_flag) { 00040 _wave_flag = false; 00041 num = _sampling_num; 00042 wave_val = _val; 00043 return true; 00044 } else { 00045 return false; 00046 } 00047 } 00048 00049 /** Gat pulse rate 00050 * @param &pr Pulse rate 00051 * @retval true Ready for data 00052 * @retval false Not ready 00053 */ 00054 bool PulseRate::get_pr_val(uint32_t &pr) { 00055 if(_pr_flag) { 00056 _pr_flag = false; 00057 pr = _pr; 00058 return true; 00059 } else { 00060 return false; 00061 } 00062 } 00063 00064 /** Interval timer 00065 */ 00066 void PulseRate::interval_timer() { 00067 00068 /* Pulse waveform */ 00069 _val = ((int32_t)(_sensor.read_u16()) - AD_OFFSET); /* Get AD value */ 00070 _val = hpf(_val); /* High pass filter (Comment out if not necessary) */ 00071 _sampling_num = (_sampling_num + 1) % SPL_NUM; /* Update sampling number */ 00072 _wave_flag = true; /* Set ready flag for pulse waveform */ 00073 00074 /* Pulse rate */ 00075 if(detect_peak(_val)) { /* If detecting pulse */ 00076 calc_pr(); /* Calculate pulse rate including flag set */ 00077 } 00078 00079 /* Control LED and Beep */ 00080 if(_pr_flag) { 00081 _sync_led = LED_ON; 00082 _beep.write(BEEP_LOUD); 00083 } else { 00084 _sync_led = LED_OFF; 00085 _beep.write(0); 00086 } 00087 } 00088 00089 /** Fixed point high pass filter 00090 * @param val Input value 00091 * @return Output value 00092 * 00093 * A/D value of mbed is Q6 format. 00094 * Please shift in advance if necessary. 00095 */ 00096 int32_t PulseRate::hpf(int32_t val) { 00097 int32_t reg, ret_val; 00098 int64_t temp_val; 00099 00100 temp_val = (int64_t)COEF_AH * (int64_t)_reg_hpf; 00101 reg = val + (int32_t)(temp_val >> 30); 00102 ret_val = reg - _reg_hpf; 00103 temp_val = (int64_t)COEF_BH * (int64_t)ret_val; 00104 ret_val = (int32_t)(temp_val >> 30); 00105 _reg_hpf = reg; 00106 return ret_val; 00107 } 00108 00109 /** Detect pulse peak 00110 * @param &val Waveform data value 00111 * @retval true Detected pulse peak 00112 * @retval false No detection 00113 */ 00114 bool PulseRate::detect_peak(int32_t val) { 00115 int i; 00116 bool retVal = false; 00117 00118 /* Calculate differential of input value */ 00119 _mv_buf[_mv_idx] = val - _prev_val; 00120 _prev_val = val; 00121 _mv_idx = (_mv_idx + 1) % MV_LENGTH; 00122 00123 /* Calculate moving averaging */ 00124 _detect_val = 0; 00125 for(i=0; i<MV_LENGTH; i++) 00126 { 00127 _detect_val += _mv_buf[i]; 00128 } 00129 _detect_val = _detect_val / MV_LENGTH; 00130 00131 /* Calculate exponential decline for threshold line */ 00132 _threshold_val = (int32_t)((double)_prev_th_val * TH_COEF); 00133 00134 if(_detect_val >= _threshold_val) { 00135 /* If exceeding threshold */ 00136 if(_prev_dt_val < _prev_th_val){ 00137 /* If previous value is under threshold and over ignore value */ 00138 if((_detect_val > PEAK_MIN) && (_pr_counter >= PR_INT_MIN)) { 00139 /* Detecting peak!!! */ 00140 retVal = true; 00141 } 00142 } 00143 /* Previous threshold value is set to input value */ 00144 _prev_th_val = _detect_val; 00145 } else { 00146 /* Previous threshold value is set to decline value */ 00147 _prev_th_val = _threshold_val; 00148 } 00149 /* Update previous input value */ 00150 _prev_dt_val = _detect_val; 00151 00152 /* Increment pulse rate counter */ 00153 _pr_counter++; 00154 00155 return retVal; 00156 } 00157 00158 /** Calculate pulse rate 00159 */ 00160 void PulseRate::calc_pr() { 00161 int i; 00162 00163 /* If pulse rate counter is within maximum value */ 00164 if(_pr_counter <= PR_INT_MAX) { 00165 /* Calculate moving averaging */ 00166 _pr_buf[_pr_idx] = _pr_counter; 00167 _pr_idx = (_pr_idx + 1) % PR_LENGTH; 00168 _pr = 0; 00169 for(i=0; i<PR_LENGTH; i++) 00170 { 00171 _pr += _pr_buf[i]; 00172 } 00173 /* Set pulse rate value */ 00174 _pr = PR_1MIN_SPL * PR_LENGTH / _pr; 00175 } else { 00176 /* Pulse rate is set to invalid value */ 00177 _pr = 0; 00178 } 00179 _pr_counter = 0; 00180 00181 /* Set pulse rate flag */ 00182 _pr_flag = true; 00183 }
Generated on Wed Jul 13 2022 19:52:00 by 1.7.2