Heart Rate sensor

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Heart Rate sensor

321 Views
rb05
Contributor I

Hi there, i am using the following code to obtain the adc value from a circuit and convert it into a heart rate value, however i am not getting any adc value. I'm using the FRDM MXCN947 board and using P0_28 for my adc pin, is my pin configuration within the code wrong?

 

 

#include "fsl_debug_console.h"

#include "fsl_lpadc.h"

#include "fsl_spc.h"

#include "fsl_vref.h"

#include "clock_config.h"

#include "pin_mux.h"

#include "board.h"

 

#include <stdbool.h>

#include <stdint.h>

#include <stdio.h>

 

#define DEMO_LPADC_BASE ADC0

#define DEMO_LPADC_USER_CHANNEL 0U // P0_28 → ADC0 channel 2

#define DEMO_LPADC_USER_CMDID 1U

 

#define SAMPLE_INTERVAL_US 5000U // 5 ms

#define BEAT_DEBOUNCE_MS 300U

#define ADC_RESULT_SHIFT 3U // 12-bit conversion shift

 

volatile uint32_t g_millis = 0;

 

// SysTick for millisecond timing

void SysTick_Handler(void) {

g_millis++;

}

 

uint32_t millis(void) {

return g_millis;

}

 

void InitADC(void) {

// Clock setup

CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1U);

CLOCK_AttachClk(kFRO_HF_to_ADC0);

CLOCK_EnableClock(kCLOCK_Adc0);

 

// Enable VREF bias

SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref);

 

vref_config_t vrefConfig;

VREF_GetDefaultConfig(&vrefConfig);

vrefConfig.bufferMode = kVREF_ModeBandgapOnly;

VREF_Init(VREF0, &vrefConfig);

 

// ADC config

lpadc_config_t adcConfig;

LPADC_GetDefaultConfig(&adcConfig);

adcConfig.enableAnalogPreliminary = true;

LPADC_Init(DEMO_LPADC_BASE, &adcConfig);

 

// ADC command

lpadc_conv_command_config_t cmdConfig;

LPADC_GetDefaultConvCommandConfig(&cmdConfig);

cmdConfig.channelNumber = DEMO_LPADC_USER_CHANNEL;

LPADC_SetConvCommandConfig(DEMO_LPADC_BASE, DEMO_LPADC_USER_CMDID, &cmdConfig);

 

// Trigger

lpadc_conv_trigger_config_t trigConfig;

LPADC_GetDefaultConvTriggerConfig(&trigConfig);

trigConfig.targetCommandId = DEMO_LPADC_USER_CMDID;

trigConfig.enableHardwareTrigger = false;

LPADC_SetConvTriggerConfig(DEMO_LPADC_BASE, 0U, &trigConfig);

}

 

int main(void) {

BOARD_InitPins();

BOARD_BootClockFRO12M();

BOARD_InitDebugConsole();

 

SysTick_Config(SystemCoreClock / 1000U); // 1ms tick

InitADC();

 

PRINTF("Heartbeat sensor started. Place your finger on the sensor.\r\n");

 

float dcOffset = 0.0f;

const float alpha = 0.995f;

bool beatDetected = false;

uint32_t lastBeatTime = 0;

int bpm = 0;

 

while (1) {

// Trigger ADC

LPADC_DoSoftwareTrigger(DEMO_LPADC_BASE, 1U << 0); // Trigger 0

 

// Add a small delay to allow conversion to complete

SDK_DelayAtLeastUs(10, SystemCoreClock); // Adjust delay if needed

 

lpadc_conv_result_t result;

if (!LPADC_GetConvResult(DEMO_LPADC_BASE, &result, true)) {

PRINTF("No ADC result ready\r\n");

} else {

PRINTF("ADC result = %u\r\n", result.convValue >> 3);

}

 

uint16_t rawValue = result.convValue >> ADC_RESULT_SHIFT;

float sample = (float)rawValue;

 

// Filter DC offset

dcOffset = alpha * dcOffset + (1.0f - alpha) * sample;

float acSignal = sample - dcOffset;

 

uint32_t now = millis();

float threshold = 200.0f; // Adjust based on your circuit output

 

// Beat detection

if (!beatDetected && acSignal > threshold) {

if ((now - lastBeatTime) > BEAT_DEBOUNCE_MS) {

uint32_t interval = now - lastBeatTime;

lastBeatTime = now;

if (interval > 0) {

bpm = 60000 / interval;

PRINTF("Beat detected! BPM = %d\r\n", bpm);

}

}

beatDetected = true;

}

 

if (beatDetected && acSignal < threshold * 0.5f) {

beatDetected = false;

}

 

SDK_DelayAtLeastUs(SAMPLE_INTERVAL_US, SystemCoreClock);

}

}

 

Labels (1)
0 Kudos
Reply
1 Reply

308 Views
Pablo_Ramos
NXP Employee
NXP Employee

Hi @rb05,

My recommendation would it be to first try the ADC conversion with the SDK example lpadc_interrupt_cm33_core0.

For P0_28 the channel for ADC0 is channel 20 as you can see on Table 359. ADC analog channel input connections.

Pablo_Ramos_0-1746044703862.png

Also, you need to enable the channel B for ADC0 and set the sample channel mode in order to enable the conversion of channel B. You can find this on the lpadc_conv_command_config_t struct

Pablo_Ramos_1-1746044726102.png

 

0 Kudos
Reply