cancel
Showing results for 
Search instead for 
Did you mean: 

pulse sensor

mauro2
Associate II
Posted on January 31, 2016 at 09:54

I'm trying to use this

http://pulsesensor.com/

with stm32f10x uC.

I'm not having much luck, so I just want to ask if there is someone who have some experience with this sensor and that can tell me how to set properly the adc of the uC.

I'm using the stm32f10x_adc library but I am a little confused about how to configure adc.

thanks.
5 REPLIES 5
Posted on January 31, 2016 at 15:34

May be you can scope this a bit?

a) What sample rate does it require?

b) How large a set of samples do you need for processing?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mauro2
Associate II
Posted on January 31, 2016 at 17:12

a) the sample rate should be 500 Hz

b) i don't know exactly, but probably i need a number of samples large enough to describe a cardiac cycle that lasts about 1 second.

Posted on January 31, 2016 at 18:58

Quick blind example

// STM32 VLDiscovery (STM32F1) ADC+DMA+TIM 500 Hz - sourcer32@gmail.com
#include ''stm32f10x.h''
#define SAMPLES (500 * 2) // 2x buffers of 1 second
volatile uint16_t ADC_RegularConvertedValueTab[SAMPLES];
/******************************************************************************/
void RCC_Configuration(void)
{
RCC_ADCCLKConfig(RCC_PCLK2_Div2);
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable GPIOs and ADC1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |
RCC_APB2Periph_ADC1, ENABLE);
/* Enable TIM3 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
}
/******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PC.00 (ADC Channel10) as analog input */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/******************************************************************************/
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
uint32_t Prescaler, Period;
/* Both these must ultimately fit in 16-bit, ie 1..65536 */
Prescaler = (SystemCoreClock / 1000000); // System -> 1 MHz
Period = (1000000 / 500); // 1 MHz -> 500 Hz
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(Prescaler - 1);
TIM_TimeBaseStructure.TIM_Period = (uint16_t)(Period - 1);
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // Where do those stairs go? They go up!
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Not used
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // Not used
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* T3_TRGO = Update selection */
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
/* TIM3 counter enable */
TIM_Cmd(TIM3, ENABLE);
}
/******************************************************************************/
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_RegularConvertedValueTab;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = SAMPLES;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
/******************************************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE; /* Single Channel */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; /* Clock Triggered */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel(s) configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
/******************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
TIM_Configuration();
DMA_Configuration();
ADC_Configuration();
while(1)
{
}
/* does not exit - kind of important */
return(1);
}
/******************************************************************************/
void DMA1_Channel1_IRQHandler(void) // Called at 1 Hz
{
if (DMA_GetITStatus(DMA1_IT_HT1)) // Ping
{
DMA_ClearITPendingBit(DMA1_IT_HT1);
// Do something with first second
}
if (DMA_GetITStatus(DMA1_IT_TC1)) // Pong
{
DMA_ClearITPendingBit(DMA1_IT_TC1);
// Do something with second second
}
}
/******************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/******************************************************************************/

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mauro2
Associate II
Posted on February 01, 2016 at 15:17

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6j7&d=%2Fa%2F0X0000000bu2%2FLLevxOYBTTKSeiC_p_CmF9Xq7G4idMdVF9yjmXP1Ub4&asPdf=false
Posted on February 01, 2016 at 18:02

Yes, it means the channel is available on all three ADC, there are different combinations and subsets.

I would test by pulling the pin to the high and low rails and making sure I could see full range values. Is PA0 available in an unfettered way on you board? Not a user button or something?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..