Skip to main content
mauro2
Associate II
January 31, 2016
Question

pulse sensor

  • January 31, 2016
  • 5 replies
  • 1790 views
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.
    This topic has been closed for replies.

    5 replies

    Tesla DeLorean
    Guru
    January 31, 2016
    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 VenmoUp vote any posts that you find helpful, it shows what's working..
    mauro2
    mauro2Author
    Associate II
    January 31, 2016
    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.

    Tesla DeLorean
    Guru
    January 31, 2016
    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 VenmoUp vote any posts that you find helpful, it shows what's working..
    mauro2
    mauro2Author
    Associate II
    February 1, 2016
    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
    Tesla DeLorean
    Guru
    February 1, 2016
    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 VenmoUp vote any posts that you find helpful, it shows what's working..