IWR1642运行driver vital signals demo没有数据波形

Other Parts Discussed in Thread: IWR1642BOOST

运行vital_signal_gui后没有数据波形,cmd的运行结果如下所示

请问是什么原因,如何解决?

  • 你好,

    你能提供一下你修改的部分代码么?
  • 修改过的函数代码如下,将未初始化的变量初始化
    void MmwDemo_interFrameProcessing(MmwDemo_DSS_DataPathObj *obj)
    {
    //Vital Signs Demo Processing Chain

    gFrameCount++; // Increment the Global Frame Count
    static uint16_t frameCountLocal = 0; // Local circular count
    uint16_t loopIndexBuffer = 0; // Index that loops over the buffers

    /* Obtain GUI-related Flags sent through the CLI */
    VitalSignsDemo_GuiMonSel *pGuiMonSel;
    pGuiMonSel = (VitalSignsDemo_GuiMonSel *) &(obj->cliCfg->vitalSigns_GuiMonSel);

    /* Variables for Impulse Noise Removal */
    static float dataCurr = 0;
    static float dataPrev2 = 0;
    static float dataPrev1 = 0;

    /* Variables for Clutter Removal */
    float maxValClutter = 0;
    uint16_t guiFlag_ClutterRemoval = pGuiMonSel->guiFlag_ClutterRemoval;
    uint16_t rangeBinMaxClutter = 0;

    /* Variables for Phase Unwrapping */
    static float phasePrevFrame = 0; // Phase value of Previous frame (For phase unwrapping)
    static float diffPhaseCorrectionCum = 0; // Phase correction *** (For phase unwrapping)
    static float phaseUsedComputationPrev = 0; // Phase values used for the Previous frame
    float phaseUsedComputation = 0; // Unwrapped Phase value used for computation

    /* Variables for Detecting Motion Corrupted Segments */
    uint16_t guiFlag_MotionDetection = obj->cliCfg->motionDetectionParamsCfg.enabled; // GUI Flag. Set from the configuration File
    uint16_t guiFlag_GainControl = obj->cliCfg->motionDetectionParamsCfg.gainControl; // GUI Flag. Set from the configuration File
    uint16_t indexMotionDetection = 0; // Temporary Index
    float sumEnergy = 0; // Energy in the data-segment checked for presence of large-scale motion

    /* Vital Signs Waveform */
    float outputFilterBreathOut = 0; // Breathing waveform after the IIR-Filter
    float outputFilterHeartOut = 0; // Cardiac waveform after the IIR-Filter

    /* Variables for FFT-based Spectral Estimation */
    uint16_t pPeakSortOutIndex[MAX_NUM_PEAKS_SPECTRUM] = {0}; // Sorted Peaks in the Spectrum
    uint16_t numPeaks_BreathSpectrum = 0; // Number of Peaks in the Breathing Spectrum
    uint16_t numPeaks_heartSpectrum = 0; // Number of Peaks in the Cardiac Spectrum
    uint16_t maxIndexHeartBeatSpect = 0, maxIndexBreathSpect = 0; // Indices corresponding to the max peak in the Breathing and Cardiac Spectrum
    uint16_t maxIndexHeartBeatSpect_4Hz = 0; // Indices corresponding to the max peak from [1.6 - 4.0] Hz
    float breathingRateEst_FFT = 0, heartRateEst_FFT = 0; // Vital Signs Estimate based on the FFT
    float heartRateEst_FFT_4Hz = 0; // Vital Signs Estimate based on the FFT

    /* Confidence Metric associated with the estimates */
    float confidenceMetricBreath[MAX_NUM_PEAKS_SPECTRUM] = {0}; // Confidence Metric associated with each Breathing Spectrum Peak
    float confidenceMetricHeart[MAX_NUM_PEAKS_SPECTRUM] = {0}; // Confidence Metric associated with each Cardiac Spectrum Peak
    float confidenceMetricBreathOut = 0, confidenceMetricHeartOut = 0; // Confidence Metric associated with the estimates
    float confidenceMetricHeartOut_4Hz = 0; // Confidence Metric for the 1st Heart beat Harmonic
    float confidenceMetricHeartOut_xCorr = 0; // Confidence Metric for the Autocorrelation
    float confidenceMetricBreathOut_xCorr = 0; // Confidence Metric for the Autocorrelation based breathing-rate estimate
    float peakValueBreathSpect = 0;

    /* Variables for peak-counting */
    uint16_t pPeakLocsHeart[MAX_PEAKS_ALLOWED_WFM] = {0}; // Peak locations (indices) of the Cardiac Waveform
    uint16_t pPeakLocsBreath[MAX_PEAKS_ALLOWED_WFM] = {0}; // Peak locations (indices) of the Breathing Waveform
    uint16_t pPeakLocsValid[MAX_PEAKS_ALLOWED_WFM] = {0}; // Peak locations after only retaining the valid peaks
    uint16_t numPeaksBreath = 0, numPeaksHeart = 0; // Number of peaks in the time-domain filtered waveform
    float breathingRateEst_peakCount = 0, heartRateEst_peakCount = 0; // Vital Signs Estimate based on peak-Interval
    float heartRateEst_peakCount_filtered = 0; // Heart-rate peak-interval based estimate after filtering

    /* Exponential smoothing filter */
    static float breathWfmOutUpdated = 0;
    static float heartWfmOutUpdated = 0; // Updated values after exponential smoothing
    float breathWfmOutPrev = 0, heartWfmOutPrev = 0; // Exponential smoothing values at time instance (t-1)
    float sumEnergyBreathWfm = 0, sumEnergyHeartWfm = 0; // These values are used to make a decision if the energy in the waveform is sufficient for it to be classfied as a valid waveform

    /* Variables for Auto-Correlation */
    float heartRateEst_xCorr = 0; // Heart-rate estimate from the Autocorrelation Method
    float breathRateEst_xCorr = 0; // Breathing-rate estimate from the Autocorrelation Method

    /* For FIR Filtering */
    static float pDataIn[FIR_FILTER_SIZE] = {0};

    /* Variables for Extracting the Range-FFT output */
    uint16_t rangeBinIndex = 0; // Range-bin Index
    float rangeBinPhase = 0; // Phase of the Range-bin selected for processing
    static uint16_t rangeBinIndexPhase = 0; // Index of the Range Bin for which the phase is computed
    uint16_t rangeBinMax = 0; // Index of the Strongest Range-Bin

    uint16_t indexTemp = 0, indexNumPeaks = 0; // Temporary Indices
    int16_t temp_real = 0, temp_imag = 0; // Temporary variables storing the Real and Imaginary part of a range-bin in the Range-FFT Output
    float absVal = 0; // Absolute value based on the Real and Imaginary values
    float maxVal = 0; // Maximum Value of the Range-Bin in the current range-profile

    if (pGuiMonSel->guiFlag_Reset == 1) // Refresh Pushbutton on the GUI Pressed
    {
    gFrameCount = 1;
    pGuiMonSel->guiFlag_Reset = 0;
    breathWfmOutUpdated = 0;
    heartWfmOutUpdated = 0;
    }

    if (RANGE_BIN_TRACKING)
    {
    frameCountLocal = gFrameCount % RESET_LOCAL_COUNT_VAL;
    }
    else
    {
    frameCountLocal = gFrameCount;
    }

    rangeBinMax = 0;
    maxVal = 0;
    rangeBinMaxClutter = 0;
    maxValClutter = 0;

    // tempPtr points towards the RX-Channel to process
    cmplx16ReIm_t *tempPtr = obj->fftOut1D + (obj->rxAntennaProcess - 1)*obj->numRangeBins;
    // tempPtr points towards rangeBinStartIndex
    tempPtr += (obj->rangeBinStartIndex) ;

    for (rangeBinIndex = obj->rangeBinStartIndex; rangeBinIndex <= obj->rangeBinEndIndex; rangeBinIndex++)
    {
    // Points towards the real part of the current range-bin i.e. rangeBinIndex
    temp_real = (int16_t) tempPtr->real;
    obj->pRangeProfileCplx[rangeBinIndex - obj->rangeBinStartIndex].real = temp_real;

    // Points towards the imaginary part of the current range-bin i.e. rangeBinIndex
    temp_imag = (int16_t) tempPtr->imag;
    obj->pRangeProfileCplx[rangeBinIndex - obj->rangeBinStartIndex].imag = temp_imag;

    // Move the pointer towards the next range-bin
    tempPtr ++;


    if (guiFlag_ClutterRemoval == 1)
    {
    // Clutter Removed Range Profile
    float tempReal_Curr,tempImag_Curr;
    float alphaClutter = 0.01;
    float currVal;

    tempReal_Curr = (float) temp_real;
    tempImag_Curr = (float) temp_imag;
    uint16_t currRangeIndex;
    currRangeIndex = rangeBinIndex - obj->rangeBinStartIndex;

    obj->pTempReal_Prev[currRangeIndex] = alphaClutter*tempReal_Curr + (1-alphaClutter)*obj->pTempReal_Prev[currRangeIndex];
    obj->pTempImag_Prev[currRangeIndex] = alphaClutter*tempImag_Curr + (1-alphaClutter)*obj->pTempImag_Prev[currRangeIndex];

    currVal = sqrt((tempReal_Curr - obj->pTempReal_Prev[currRangeIndex])*(tempReal_Curr - obj->pTempReal_Prev[currRangeIndex]) + (tempImag_Curr - obj->pTempImag_Prev[currRangeIndex])*(tempImag_Curr - obj->pTempImag_Prev[currRangeIndex]));
    obj->pRangeProfileClutterRemoved[rangeBinIndex - obj->rangeBinStartIndex] = currVal;

    // Based on the Max value Range-bin
    if (currVal > maxValClutter)
    {
    maxValClutter = currVal;
    rangeBinMaxClutter = rangeBinIndex;
    }
    }
    else
    {
    // Magnitude of the current range-bin
    absVal = (float) temp_real * (float) temp_real + (float) temp_imag * (float) temp_imag;
    // Maximum value range-bin of the current range-profile
    if (absVal > maxVal)
    {
    maxVal = absVal;
    rangeBinMax = rangeBinIndex;
    }
    }
    // If the Refresh button in the GUI is pressed
    if (frameCountLocal == 1)
    {
    if (guiFlag_ClutterRemoval == 1)
    {
    rangeBinIndexPhase = rangeBinMaxClutter;
    }
    else
    {
    rangeBinIndexPhase = rangeBinMax;
    }
    }
    if (rangeBinIndex == (rangeBinIndexPhase))
    {
    rangeBinPhase = atan2(temp_imag, temp_real);
    }
    } // For Loop ends

    // Phase-Unwrapping
    obj->unwrapPhasePeak = unwrap(rangeBinPhase, phasePrevFrame, &diffPhaseCorrectionCum);
    phasePrevFrame = rangeBinPhase;

    #ifdef TEST_TONE // Generates a Test-Tone

    float testTone_ampBreath_mm = 1.0;
    float testTone_freqBreath_Hz = 0.45;
    float testTone_ampHeart_mm = 0.01;
    float testTone_freqHeart_Hz = 1.8;

    obj->unwrapPhasePeak = (4 * PI_/WAVELENGTH_MM) *(
    (testTone_ampBreath_mm * sin(2*PI_*testTone_freqBreath_Hz* gFrameCount/obj->samplingFreq_Hz))+
    (testTone_ampHeart_mm * sin(2*PI_*testTone_freqHeart_Hz*gFrameCount/obj->samplingFreq_Hz))
    );
    // +0.5*(testTone_ampBreath_mm *sin(2*PI_*(2*testTone_freqBreath_Hz)* gFrameCount/obj->samplingFreq_Hz)); // Harmonic signal
    #endif

    // Computes the phase differences between successive phase samples
    if(FLAG_COMPUTE_PHASE_DIFFERENCE)
    {
    phaseUsedComputation = obj->unwrapPhasePeak - phaseUsedComputationPrev;
    phaseUsedComputationPrev = obj->unwrapPhasePeak;
    }
    else
    {
    phaseUsedComputation = obj->unwrapPhasePeak;
    }

    // Removes impulse like noise from the waveforms
    if (FLAG_REMOVE_IMPULSE_NOISE)
    {
    dataPrev2 = dataPrev1;
    dataPrev1 = dataCurr;
    dataCurr = phaseUsedComputation;
    phaseUsedComputation = filter_RemoveImpulseNoise(dataPrev2, dataPrev1, dataCurr, obj->noiseImpulse_Thresh);
    }

    // IIR Filtering
    outputFilterBreathOut = filter_IIR_BiquadCascade(phaseUsedComputation, obj->pFilterCoefsBreath, obj->pScaleValsBreath, obj->pDelayBreath, IIR_FILTER_BREATH_NUM_STAGES);
    outputFilterHeartOut = filter_IIR_BiquadCascade(phaseUsedComputation, obj->pFilterCoefsHeart_4Hz, obj->pScaleValsHeart_4Hz, obj->pDelayHeart, IIR_FILTER_HEART_NUM_STAGES);

    // Copies the "Breathing Waveform" in a circular Buffer
    for (loopIndexBuffer = 1; loopIndexBuffer < obj->circularBufferSizeBreath; loopIndexBuffer++)
    {
    obj->pVitalSigns_Breath_CircularBuffer[loopIndexBuffer - 1] = obj->pVitalSigns_Breath_CircularBuffer[loopIndexBuffer];
    }
    obj->pVitalSigns_Breath_CircularBuffer[obj->circularBufferSizeBreath - 1] = outputFilterBreathOut;

    // Detection of Motion corrupted Segments
    if (guiFlag_MotionDetection == 1)
    {
    // Update the Motion Removal Circular Buffer
    for (loopIndexBuffer = 1; loopIndexBuffer < obj->motionDetection_BlockSize; loopIndexBuffer++)
    {
    obj->pMotionCircularBuffer[loopIndexBuffer - 1] = obj->pMotionCircularBuffer[loopIndexBuffer] ;
    }
    obj->pMotionCircularBuffer[obj->motionDetection_BlockSize-1] = outputFilterHeartOut;
    indexMotionDetection = gFrameCount % obj->motionDetection_BlockSize;

    // Only perform these steps for every obj->motionDetection_BlockSize sample
    if (indexMotionDetection == 0)
    {
    // Check if the current segment is "Noisy"
    sumEnergy = 0;
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->motionDetection_BlockSize; loopIndexBuffer++)
    {
    sumEnergy += (obj->pMotionCircularBuffer[loopIndexBuffer]*obj->pMotionCircularBuffer[loopIndexBuffer]);
    }

    if (sumEnergy > obj->motionDetection_Thresh)
    {
    obj->motionDetected = 1; // Temporary variable to send to the GUI
    }
    else
    {
    obj->motionDetected = 0; // Temporary variable to send to the GUI
    }

    // If NO motion detected in the current segment
    if ( obj->motionDetected == 0)
    {
    uint16_t tempEndIndex;
    // Shift the current contents of the circular Buffer
    for (loopIndexBuffer = obj->motionDetection_BlockSize; loopIndexBuffer < obj->circularBufferSizeHeart; loopIndexBuffer++)
    {
    obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer - obj->motionDetection_BlockSize] = obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer] ;
    }
    // Copy the current data segment to the end of the Circular Buffer
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->motionDetection_BlockSize; loopIndexBuffer++)
    {
    tempEndIndex = obj->circularBufferSizeHeart - obj->motionDetection_BlockSize;
    obj->pVitalSigns_Heart_CircularBuffer[ tempEndIndex + loopIndexBuffer] = obj->pMotionCircularBuffer[loopIndexBuffer] ;
    }
    }
    }
    }
    // If Motion DETECTED then don't UPDATE or SHIFT the values in the buffer
    else // Regular processing
    {
    // Copies the "Cardiac Waveform" in a circular Buffer
    for (loopIndexBuffer = 1; loopIndexBuffer < obj->circularBufferSizeHeart; loopIndexBuffer++)
    {
    obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer - 1] = obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer];
    }
    obj->pVitalSigns_Heart_CircularBuffer[obj->circularBufferSizeHeart - 1] = outputFilterHeartOut;
    }

    /* Spectral Estimation based on the Inter-Peaks Distance */
    numPeaksHeart = find_Peaks(obj->pVitalSigns_Heart_CircularBuffer, float_type, pPeakLocsHeart,obj->pPeakValues, 0, obj->circularBufferSizeHeart - 1);
    if (numPeaksHeart != 0)
    {
    numPeaksHeart = filterPeaksWfm(pPeakLocsHeart, pPeakLocsValid, numPeaksHeart, obj->peakDistanceHeart_Min, obj->peakDistanceHeart_Max);
    }
    heartRateEst_peakCount = CONVERT_HZ_BPM * ((numPeaksHeart * obj->samplingFreq_Hz) / obj->circularBufferSizeHeart);

    for (loopIndexBuffer = 1; loopIndexBuffer < FIR_FILTER_SIZE; loopIndexBuffer++)
    {
    pDataIn[loopIndexBuffer - 1] = pDataIn[loopIndexBuffer];
    }
    pDataIn[FIR_FILTER_SIZE - 1] = heartRateEst_peakCount;
    heartRateEst_peakCount_filtered = filter_FIR(pDataIn, obj->pFilterCoefs, FIR_FILTER_SIZE);

    numPeaksBreath = find_Peaks(obj->pVitalSigns_Breath_CircularBuffer, int32_type, pPeakLocsBreath, obj->pPeakValues, 0, obj->circularBufferSizeBreath - 1);
    if (numPeaksBreath != 0)
    {
    numPeaksBreath = filterPeaksWfm(pPeakLocsBreath, pPeakLocsValid, numPeaksBreath, obj->peakDistanceBreath_Min, obj->peakDistanceBreath_Max);
    }

    breathingRateEst_peakCount = CONVERT_HZ_BPM * ((numPeaksBreath * obj->samplingFreq_Hz) / obj->circularBufferSizeHeart);
    heartRateEst_peakCount = CONVERT_HZ_BPM * ((numPeaksHeart * obj->samplingFreq_Hz) / obj->circularBufferSizeBreath);

    // Input to the FFT needs to be complex
    memset((uint8_t *)obj->pVitalSignsBuffer_Cplx, 0, obj->breathingWfm_Spectrum_FftSize * sizeof(cmplx32ReIm_t));
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->circularBufferSizeBreath; loopIndexBuffer++)
    {
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].real = (int32_t) obj->scale_breathingWfm*obj->pVitalSigns_Breath_CircularBuffer[loopIndexBuffer];
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].imag=0;
    }

    // Input is overwritten by the DSP_fft32x32 function
    DSP_fft32x32(
    (int32_t *)obj->pVitalSignsSpectrumTwiddle32x32,
    obj->breathingWfm_Spectrum_FftSize,
    (int32_t *) obj->pVitalSignsBuffer_Cplx,
    (int32_t *) obj->pVitalSigns_SpectrumCplx);

    MmwDemo_magnitudeSquared(
    obj->pVitalSigns_SpectrumCplx,
    obj->pVitalSigns_Breath_AbsSpectrum,
    obj->breathingWfm_Spectrum_FftSize);

    memset((uint8_t *)obj->pVitalSignsBuffer_Cplx, 0, obj->heartWfm_Spectrum_FftSize * sizeof(cmplx32ReIm_t));

    // Pre-Processing Steps for the Cardiac Waveform
    // Perform Automatic Gain Control if enabled from the GUI
    if (guiFlag_GainControl == 1)
    {
    computeAGC ( obj->pVitalSigns_Heart_CircularBuffer, obj->circularBufferSizeHeart, obj->motionDetection_BlockSize, obj->motionDetection_Thresh);
    }

    if (guiFlag_MotionDetection == 1)
    {
    outputFilterHeartOut = obj->pMotionCircularBuffer[obj->motionDetection_BlockSize-1];
    }
    else
    {
    outputFilterHeartOut = obj->pVitalSigns_Heart_CircularBuffer[obj->circularBufferSizeHeart-1];
    }

    // Perform Autocorrelation on the Waveform
    if (PERFORM_XCORR)
    {
    float temp;
    // Perform Autocorrelation on the Cardiac-Waveform
    uint16_t xCorr_numPeaks;
    uint16_t maxIndex_lag;
    computeAutoCorrelation ( obj->pVitalSigns_Heart_CircularBuffer, obj->circularBufferSizeHeart , obj->pXcorr, obj->xCorr_minLag, obj->xCorr_maxLag);
    xCorr_numPeaks = find_Peaks(obj->pXcorr, float_type, obj->pPeakIndex, obj->pPeakValues, obj->xCorr_minLag, obj->xCorr_maxLag);
    maxIndex_lag = computeMaxIndex((float*) obj->pXcorr, obj->xCorr_minLag, obj->xCorr_maxLag);
    temp = (float) (1.0)/(maxIndex_lag/obj->samplingFreq_Hz);
    heartRateEst_xCorr = (float) CONVERT_HZ_BPM *temp;

    if (xCorr_numPeaks == 0 )
    {
    confidenceMetricHeartOut_xCorr = 0;
    }
    else
    {
    confidenceMetricHeartOut_xCorr = obj->pXcorr[maxIndex_lag];
    }

    // Auto-correlation on the Breathing Waveform
    computeAutoCorrelation ( obj->pVitalSigns_Breath_CircularBuffer, obj->circularBufferSizeBreath,
    obj->pXcorr, obj->xCorr_Breath_minLag, obj->xCorr_Breath_maxLag);
    xCorr_numPeaks = find_Peaks(obj->pXcorr, float_type, obj->pPeakIndex, obj->pPeakValues, obj->xCorr_Breath_minLag, obj->xCorr_Breath_maxLag);
    maxIndex_lag = computeMaxIndex((float*) obj->pXcorr, obj->xCorr_Breath_minLag, obj->xCorr_Breath_maxLag);
    temp = (float) (1.0)/(maxIndex_lag/obj->samplingFreq_Hz);
    breathRateEst_xCorr = (float) CONVERT_HZ_BPM *temp;

    if (xCorr_numPeaks == 0 )
    {
    confidenceMetricBreathOut_xCorr = 0;
    }
    else
    {
    confidenceMetricBreathOut_xCorr = obj->pXcorr[maxIndex_lag];
    }
    }

    // Apply Window on the Cardiac Waveform prior to FFT-based spectral estimation
    // and copies the Pre-processed data to pCircularBufferHeart
    if (FLAG_APPLY_WINDOW)
    {
    uint16_t index_win;
    uint16_t index_WinEnd;

    float tempFloat;
    index_WinEnd = obj->circularBufferSizeHeart - 1;
    for (index_win = 0; index_win < DOPPLER_WINDOW_SIZE; index_win++)
    {
    tempFloat = obj->pDopplerWindow[index_win];
    obj->pVitalSignsBuffer_Cplx[index_win].real = (int32_t) obj->scale_heartWfm * tempFloat * obj->pVitalSigns_Heart_CircularBuffer[index_win];
    obj->pVitalSignsBuffer_Cplx[index_WinEnd].real = (int32_t) obj->scale_heartWfm * tempFloat * obj->pVitalSigns_Heart_CircularBuffer[index_WinEnd];
    obj->pVitalSignsBuffer_Cplx[index_win].imag = 0;
    obj->pVitalSignsBuffer_Cplx[index_WinEnd].imag = 0;
    index_WinEnd --;
    }
    for (loopIndexBuffer = DOPPLER_WINDOW_SIZE; loopIndexBuffer < obj->circularBufferSizeHeart - DOPPLER_WINDOW_SIZE ; loopIndexBuffer++)
    {
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].real = (int32_t) (obj->scale_heartWfm)*obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer];
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].imag = 0;
    }
    }
    else
    {
    for (loopIndexBuffer = 0; loopIndexBuffer < obj->circularBufferSizeHeart; loopIndexBuffer++)
    {
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].real = (int32_t) (obj->scale_heartWfm)*obj->pVitalSigns_Heart_CircularBuffer[loopIndexBuffer];
    obj->pVitalSignsBuffer_Cplx[loopIndexBuffer].imag=0;
    }
    }

    // FFT of the Cardiac Waveform
    DSP_fft32x32(
    (int32_t *)obj->pVitalSignsSpectrumTwiddle32x32,
    obj->heartWfm_Spectrum_FftSize,
    (int32_t *) obj->pVitalSignsBuffer_Cplx,
    (int32_t *) obj->pVitalSigns_SpectrumCplx);

    MmwDemo_magnitudeSquared(
    obj->pVitalSigns_SpectrumCplx,
    obj->pVitalSigns_Heart_AbsSpectrum,
    obj->heartWfm_Spectrum_FftSize);

    // Pick the Peaks in the Breathing Spectrum
    numPeaks_BreathSpectrum = find_Peaks(obj->pVitalSigns_Breath_AbsSpectrum, float_type, obj->pPeakIndex, obj->pPeakValues,
    obj->breath_startFreq_Index, obj->breath_endFreq_Index);
    indexNumPeaks = (numPeaks_BreathSpectrum < MAX_NUM_PEAKS_SPECTRUM) ? numPeaks_BreathSpectrum : MAX_NUM_PEAKS_SPECTRUM;

    if (indexNumPeaks != 0)
    {
    heapsort_index(obj->pPeakValues, numPeaks_BreathSpectrum, obj->pPeakIndexSorted);
    for(indexTemp = 0; indexTemp < indexNumPeaks; indexTemp++ )
    {
    pPeakSortOutIndex[indexTemp] = obj->pPeakIndex [obj->pPeakIndexSorted[numPeaks_BreathSpectrum-indexTemp-1] ];
    confidenceMetricBreath[indexTemp] = computeConfidenceMetric(obj->pVitalSigns_Breath_AbsSpectrum,
    obj->confMetric_spectrumBreath_IndexStart,
    obj->confMetric_spectrumBreath_IndexEnd,
    pPeakSortOutIndex[indexTemp],
    obj->confMetric_numIndexAroundPeak_breath);
    }
    maxIndexBreathSpect = pPeakSortOutIndex[0]; // The maximum peak
    confidenceMetricBreathOut = confidenceMetricBreath[0];
    }
    else
    {
    maxIndexBreathSpect = computeMaxIndex((float*) obj->pVitalSigns_Breath_AbsSpectrum, obj->breath_startFreq_Index, obj->breath_endFreq_Index);
    confidenceMetricBreathOut = computeConfidenceMetric(obj->pVitalSigns_Breath_AbsSpectrum,
    0,
    PHASE_FFT_SIZE/4,
    maxIndexBreathSpect,
    obj->confMetric_numIndexAroundPeak_breath);
    }
    peakValueBreathSpect = obj->pVitalSigns_Breath_AbsSpectrum[maxIndexBreathSpect]/(10*obj->scale_breathingWfm);

    // Pick the Peaks in the Heart Spectrum [1.6 - 4.0 Hz]
    numPeaks_heartSpectrum = find_Peaks(obj->pVitalSigns_Heart_AbsSpectrum, uint32_type, obj->pPeakIndex, obj->pPeakValues,
    obj->heart_startFreq_Index_1p6Hz, obj->heart_endFreq_Index_4Hz);
    indexNumPeaks = (numPeaks_heartSpectrum < MAX_NUM_PEAKS_SPECTRUM) ? numPeaks_heartSpectrum : MAX_NUM_PEAKS_SPECTRUM;
    if (indexNumPeaks != 0)
    {
    heapsort_index(obj->pPeakValues, numPeaks_heartSpectrum, obj->pPeakIndexSorted);
    for(indexTemp = 0; indexTemp < indexNumPeaks; indexTemp++ )
    {
    pPeakSortOutIndex[indexTemp] = obj->pPeakIndex [obj->pPeakIndexSorted[numPeaks_heartSpectrum-indexTemp-1] ];
    }
    maxIndexHeartBeatSpect_4Hz = pPeakSortOutIndex[0]; // The maximum peak
    confidenceMetricHeartOut_4Hz = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    obj->confMetric_spectrumHeart_IndexStart_1p6Hz,
    obj->confMetric_spectrumHeart_IndexStart_4Hz,
    maxIndexHeartBeatSpect_4Hz,
    obj->confMetric_numIndexAroundPeak_heart);
    }
    else
    {
    maxIndexHeartBeatSpect_4Hz = computeMaxIndex((float*) obj->pVitalSigns_Heart_AbsSpectrum, obj->heart_startFreq_Index_1p6Hz, obj->heart_endFreq_Index_4Hz);
    confidenceMetricHeartOut_4Hz = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    0,
    PHASE_FFT_SIZE/4,
    maxIndexHeartBeatSpect_4Hz,
    obj->confMetric_numIndexAroundPeak_heart);
    }
    heartRateEst_FFT_4Hz = (float) CONVERT_HZ_BPM * maxIndexHeartBeatSpect_4Hz * (obj->freqIncrement_Hz);

    // If a peak is within [1.6 2.0] Hz then check if a harmonic is present is the cardiac spectrum region [0.8 - 2.0] Hz
    if (heartRateEst_FFT_4Hz < MAX_HEART_RATE_BPM)
    {
    for (indexTemp =1; indexTemp<numPeaks_heartSpectrum;indexTemp++)

    if(abs(heartRateEst_FFT_4Hz - CONVERT_HZ_BPM *(obj->freqIncrement_Hz)*pPeakSortOutIndex[indexTemp]) < HEART_HAMRONIC_THRESH_BPM)
    {
    heartRateEst_FFT_4Hz = CONVERT_HZ_BPM *(obj->freqIncrement_Hz)*pPeakSortOutIndex[indexTemp];
    break;
    }
    }

    // Pick the Peaks in the Cardiac Spectrum
    numPeaks_heartSpectrum = find_Peaks(obj->pVitalSigns_Heart_AbsSpectrum, float_type, obj->pPeakIndex, obj->pPeakValues, obj->heart_startFreq_Index, obj->heart_endFreq_Index);
    indexNumPeaks = (numPeaks_heartSpectrum < MAX_NUM_PEAKS_SPECTRUM) ? numPeaks_heartSpectrum : MAX_NUM_PEAKS_SPECTRUM;

    if (indexNumPeaks != 0)
    {
    heapsort_index(obj->pPeakValues, numPeaks_heartSpectrum, obj->pPeakIndexSorted);
    for(indexTemp = 0; indexTemp < indexNumPeaks; indexTemp++ )
    {
    pPeakSortOutIndex[indexTemp] = obj->pPeakIndex [obj->pPeakIndexSorted[numPeaks_heartSpectrum-indexTemp-1] ];
    confidenceMetricHeart[indexTemp] = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    obj->confMetric_spectrumHeart_IndexStart,
    obj->confMetric_spectrumHeart_IndexEnd,
    pPeakSortOutIndex[indexTemp],
    obj->confMetric_numIndexAroundPeak_heart);
    }
    maxIndexHeartBeatSpect = pPeakSortOutIndex[0]; // The maximum peak
    confidenceMetricHeartOut = confidenceMetricHeart[0];
    }
    else
    {
    maxIndexHeartBeatSpect = computeMaxIndex((float*) obj->pVitalSigns_Heart_AbsSpectrum, obj->heart_startFreq_Index, obj->heart_endFreq_Index);
    confidenceMetricHeartOut = computeConfidenceMetric(obj->pVitalSigns_Heart_AbsSpectrum,
    0,
    PHASE_FFT_SIZE/4,
    maxIndexHeartBeatSpect,
    obj->confMetric_numIndexAroundPeak_heart);
    }

    // Remove the First Breathing Harmonic (if present in the cardiac Spectrum)
    if(FLAG_HARMONIC_CANCELLATION)
    {
    float diffIndex = abs(maxIndexHeartBeatSpect - BREATHING_HARMONIC_NUM*maxIndexBreathSpect);
    if ( diffIndex*(obj->freqIncrement_Hz)*CONVERT_HZ_BPM < BREATHING_HAMRONIC_THRESH_BPM ) // Only cancel the 2nd Breathing Harmonic
    {
    maxIndexHeartBeatSpect = pPeakSortOutIndex[1]; // Pick the 2nd Largest peak in the cardiac-spectrum
    confidenceMetricHeartOut = confidenceMetricHeart[1];
    }
    }

    heartRateEst_FFT = (float) CONVERT_HZ_BPM * maxIndexHeartBeatSpect * (obj->freqIncrement_Hz);
    breathingRateEst_FFT = (float) CONVERT_HZ_BPM * maxIndexBreathSpect * (obj->freqIncrement_Hz);

    #ifdef HARMONICS_ENERGY
    float heartRateEst_HarmonicEnergy;
    float breathRateEst_HarmonicEnergy;
    uint16_t maxIndexHeartBeatSpect_temp;
    uint16_t maxIndexBreathSpect_temp;

    memset((void *)obj->pDataOutTemp, 0, obj->heartWfm_Spectrum_FftSize*sizeof(float));
    computeEnergyHarmonics (obj->pVitalSigns_Heart_AbsSpectrum,
    obj->pDataOutTemp,
    obj->confMetric_spectrumHeart_IndexStart,
    obj->confMetric_spectrumHeart_IndexEnd,
    obj->confMetric_numIndexAroundPeak_heart);
    maxIndexHeartBeatSpect_temp = computeMaxIndex(obj->pDataOutTemp,
    obj->confMetric_spectrumHeart_IndexStart,
    obj->confMetric_spectrumHeart_IndexEnd);
    heartRateEst_HarmonicEnergy = (float) CONVERT_HZ_BPM * maxIndexHeartBeatSpect_temp * (obj->freqIncrement_Hz);


    memset((void *)obj->pDataOutTemp, 0, obj->heartWfm_Spectrum_FftSize*sizeof(float));
    computeEnergyHarmonics (obj->pVitalSigns_Breath_AbsSpectrum,
    obj->pDataOutTemp,
    obj->confMetric_spectrumBreath_IndexStart,
    obj->confMetric_spectrumBreath_IndexEnd,
    obj->confMetric_numIndexAroundPeak_breath);
    maxIndexBreathSpect_temp = computeMaxIndex(obj->pDataOutTemp,
    obj->confMetric_spectrumBreath_IndexStart,
    obj->confMetric_spectrumBreath_IndexEnd);
    breathRateEst_HarmonicEnergy = (float) CONVERT_HZ_BPM * maxIndexBreathSpect_temp * (obj->freqIncrement_Hz);

    #endif

    // Median Value for Heart Rate and Breathing Rate based on 'MEDIAN_WINDOW_LENGTH' previous estimates
    if(FLAG_MEDIAN_FILTER)
    {
    for (loopIndexBuffer = 1; loopIndexBuffer < MEDIAN_WINDOW_LENGTH; loopIndexBuffer++)
    {
    obj->pBufferHeartRate[loopIndexBuffer - 1] = obj->pBufferHeartRate[loopIndexBuffer];
    obj->pBufferBreathingRate[loopIndexBuffer - 1] = obj->pBufferBreathingRate[loopIndexBuffer];
    obj->pBufferHeartRate_4Hz[loopIndexBuffer - 1] = obj->pBufferHeartRate_4Hz[loopIndexBuffer];
    }
    obj->pBufferHeartRate[MEDIAN_WINDOW_LENGTH - 1] = heartRateEst_FFT;
    obj->pBufferBreathingRate[MEDIAN_WINDOW_LENGTH - 1] = breathingRateEst_FFT;
    obj->pBufferHeartRate_4Hz[MEDIAN_WINDOW_LENGTH - 1] = heartRateEst_FFT_4Hz;

    heapsort_index(obj->pBufferHeartRate, MEDIAN_WINDOW_LENGTH, obj->pPeakSortTempIndex);
    heartRateEst_FFT = obj->pBufferHeartRate[ obj->pPeakSortTempIndex[MEDIAN_WINDOW_LENGTH/2+1]];

    heapsort_index(obj->pBufferHeartRate_4Hz, MEDIAN_WINDOW_LENGTH, obj->pPeakSortTempIndex);
    heartRateEst_FFT_4Hz = obj->pBufferHeartRate_4Hz[ obj->pPeakSortTempIndex[MEDIAN_WINDOW_LENGTH/2+1]];

    heapsort_index(obj->pBufferBreathingRate, MEDIAN_WINDOW_LENGTH, obj->pPeakSortTempIndex);
    breathingRateEst_FFT = obj->pBufferBreathingRate[ obj->pPeakSortTempIndex[MEDIAN_WINDOW_LENGTH/2+1]];
    }

    // Exponential Smoothing
    breathWfmOutPrev = breathWfmOutUpdated;
    breathWfmOutUpdated = (obj->alpha_breathing)*(outputFilterBreathOut*outputFilterBreathOut) + (1 - (obj->alpha_breathing))*breathWfmOutPrev; // Exponential Smoothing
    sumEnergyBreathWfm = breathWfmOutUpdated*10000;

    heartWfmOutPrev = heartWfmOutUpdated;
    heartWfmOutUpdated = (obj->alpha_heart)*(outputFilterHeartOut*outputFilterHeartOut) + (1 - (obj->alpha_heart))*heartWfmOutPrev; // Exponential Smoothing
    sumEnergyHeartWfm = heartWfmOutUpdated*10000;

    // Output Values
    obj->VitalSigns_Output.unwrapPhasePeak_mm = obj->unwrapPhasePeak;
    obj->VitalSigns_Output.outputFilterBreathOut = outputFilterBreathOut;
    obj->VitalSigns_Output.outputFilterHeartOut = outputFilterHeartOut;
    obj->VitalSigns_Output.rangeBinIndexPhase = rangeBinIndexPhase; //frameCountLocal;
    obj->VitalSigns_Output.maxVal = maxVal;
    obj->VitalSigns_Output.sumEnergyHeartWfm = sumEnergyHeartWfm;
    obj->VitalSigns_Output.sumEnergyBreathWfm = sumEnergyBreathWfm*peakValueBreathSpect;

    obj->VitalSigns_Output.confidenceMetricBreathOut = confidenceMetricBreathOut;
    obj->VitalSigns_Output.confidenceMetricHeartOut = confidenceMetricHeartOut; // Confidence Metric associated with the estimates
    obj->VitalSigns_Output.confidenceMetricHeartOut_4Hz = confidenceMetricHeartOut_4Hz;
    obj->VitalSigns_Output.confidenceMetricHeartOut_xCorr = confidenceMetricHeartOut_xCorr;

    obj->VitalSigns_Output.breathingRateEst_FFT = breathingRateEst_FFT;
    obj->VitalSigns_Output.breathingRateEst_peakCount = breathingRateEst_peakCount;
    obj->VitalSigns_Output.heartRateEst_peakCount_filtered = heartRateEst_peakCount_filtered;
    obj->VitalSigns_Output.heartRateEst_xCorr = heartRateEst_xCorr;
    obj->VitalSigns_Output.heartRateEst_FFT_4Hz = heartRateEst_FFT_4Hz;
    obj->VitalSigns_Output.heartRateEst_FFT = heartRateEst_FFT;

    obj->VitalSigns_Output.processingCyclesOut = obj->timingInfo.interFrameProcCycles/DSP_CLOCK_MHZ;
    obj->VitalSigns_Output.rangeBinStartIndex = obj->rangeBinStartIndex;
    obj->VitalSigns_Output.rangeBinEndIndex = obj->rangeBinEndIndex;
    obj->VitalSigns_Output.motionDetectedFlag = obj->motionDetected;
    obj->VitalSigns_Output.breathingRateEst_xCorr = breathRateEst_xCorr; //breathRateEst_HarmonicEnergy;
    obj->VitalSigns_Output.confidenceMetricBreathOut_xCorr = confidenceMetricBreathOut_xCorr; //breathRateEst_HarmonicEnergy;
    obj->VitalSigns_Output.breathingRateEst_harmonicEnergy = breathRateEst_HarmonicEnergy; //heartRateEst_HarmonicEnergy;
    obj->VitalSigns_Output.heartRateEst_harmonicEnergy = heartRateEst_HarmonicEnergy;

    }
  • 你好,

    我刚才在一块IWR1642BOOST上尝试了vital sign的demo,做的修改就是你贴的代码部分,可以正常工作。

    还请你再确认一下你的编译环境/SDK/lab代码/路径等是否正确。
  • 你好,

    如果你使用的是CCS下载可执行文件,请确保你烧写的ccs_debug.bin是mmwave sdk 2.0.0.4版本里的。
  • 将修改过的vita signal demo例程 重新用官方例程覆盖跑一遍,数据波形正常了