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);
}
}
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.
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