AnsweredAssumed Answered

Sonar (HCSR04) on STM32F3-discovery

Question asked by 4.ks on Feb 28, 2015
Latest reply on Feb 28, 2015 by Clive One

Hello, I am now trying to use two ultrasonic sensors, HCSR 04 on STM32F303VC to measure different distance from two different positions. I’m able to use only one ultrasonic sensor, which can give me the distance (PB4 as trigger and PD4 as echo), while another sensor it give me a constant value only (PB4 as trigger and PD7 as echo). I would like to ask:

       
  1. What’s wrong with my coding?
  2.    
  3. How to enable multiple input capture at the same time.
  4.    
  5. Why is the TIM_GetCapture1 get value from TIM2_CH2?

So, here is my coding. Thanks in advanced.

001./* #includes -------------------------------------------------*/
002.#include "main.h"                           //main library to include for device drivers, peripheral drivers, etc.
003. 
004./* #global variables -----------------------------------------*/
005.GPIO_InitTypeDef        GPIO_InitStructure;             //structure used for setting up a GPIO port
006.RCC_ClocksTypeDef       RCC_Clocks;         //structure used for setting up the SysTick Interrupt
007. 
008.// Unused global variables that have to be included to ensure correct compiling */
009.// ###### DO NOT CHANGE ######
010.// ===============================================================================
011.__IO uint32_t TimingDelay = 0;                      //used with the Delay function
012.__IO uint8_t DataReady = 0;
013.__IO uint32_t USBConnectTimeOut = 100;
014.__IO uint32_t UserButtonPressed = 0;
015.__IO uint8_t PrevXferComplete = 1;
016.// ===============================================================================
017. 
018.char str[];
019. 
020.int main(void){
021. 
022.    uint32_t distance, distance1;                           //declase a 32-bit unsigned int to hold the distance value
023.    uint32_t mm, mm1;                           //32-bit unsigned int to hold the distance value in mm
024.    unsigned int dec, frac, dec1, frac1;                        //used for converting the integer distance to a float value for printing
025. 
026.    /* Set the SysTick Interrupt to occur every 1ms) */
027.    RCC_GetClocksFreq(&RCC_Clocks);
028.    if (SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000))
029.        while(1);                       //will end up in this infinite loop if there was an error with Systick_Config
030. 
031.    HC_SR04_Init();                         //initialize the HC-SR04 ultrasonic sensor - see the function definition below
032.    init_USART2(115200);
033.    int timerValue = TIM_GetCounter(TIM2);
034. 
035.    /* Main program loop */
036.    while (1){
037.        distance = (TIM_GetCapture1(TIM2)/72);          //read the TIM2 value and divide by 72 (72Mhz); the result is in us.
038.        distance1 = (TIM_GetCapture2(TIM2)/72);
039.        if (timerValue % 10000){
040.            //HC-SR04 formula: distance (in m) = pulse in seconds * 340 / 2
041.            mm = distance * 340 / 2;                //mm is in micro meters (because distance is in us), e.g. if distance = 728us, then mm = 123760um
042.            mm1 = distance1 * 340 / 2;
043.            dec = mm / 1000;                    //calculate the integer part, e.g. 123
044.            dec1 = mm1 / 1000;
045.            frac = mm - (dec * 1000);               //calculate the fraction part, e.g. 760
046.            frac1 = mm1 - (dec1 * 1000);
047.            sprintf(str,"%d.%d mm %d.%d mm\r\n " , dec, frac, dec1, frac1);             //%03d prints a integer value in a field of 3 characters with leading 0's
048.            printUART2(str);
049.        }
050.    }
051.}
052. 
053. 
054. 
055. 
056. 
057.void HC_SR04_Init(void){
058. 
059.    GPIO_InitTypeDef        GPIO_InitStructure;                         //structure for GPIO setup
060.    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;                      //structure for TIM Time Base
061.    TIM_OCInitTypeDef       TIM_OCInitStructure;                        //structure for TIM Output Compare
062.    TIM_ICInitTypeDef       TIM_ICInitStructure;                        //structure for TIM Input Compare
063. 
064.    /* ===== Configure the TRIG pin =====*/
065. 
066. 
067.  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);                   //enable the AHB Peripheral Clock to use GPIOB
068.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);                 //enable the TIM16 clock
069. 
070.    /* Pin configuration */
071.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;                             //configure PB4 in alternate function pushpull mode
072.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
073.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
074.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
075.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
076.  GPIO_Init(GPIOB, &GPIO_InitStructure);
077.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_1);              //connect the pin to the desired peripherals' Alternate Function (AF) - TIM16 (GPIO_AF_1)
078. 
079.    /* Time base configuration */
080.    //The MCU on the STM32F3-Discovery board is clocked at 72Mhz and we need a 16.667Hz timebase (60ms period)
081.    //Update_event = TIM_CLK /((PSC + 1)*(ARR   + 1)*(RCR + 1))
082.    //16.667 = 72000000/((71  + 1)*(60000 + 1)*(0   + 1))
083.  TIM_TimeBaseStructure.TIM_Prescaler = 71;                                 //PSC value; meanse that TIM register will be incremented every 1us (72000000 / (71+1) = 1000000Hz = 1us
084.  TIM_TimeBaseStructure.TIM_Period = 60000;                                 //ARR value; create a time period of 60ms (1us * 60000 = 60ms)
085.  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
086.  TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);
087. 
088.    /* Output Control (OC) configuration - PWM1 Mode configuration: Channel1 */
089.  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                         //configure the PWM
090.  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
091.  TIM_OC1Init(TIM16, &TIM_OCInitStructure);                                 //for other channels this would be changed to TIM_OC2Init..., or TIM_OC3Init etc.
092. 
093.  TIM_CtrlPWMOutputs(TIM16, ENABLE);                                        //enable the PWM output
094.  TIM_Cmd(TIM16, ENABLE);                                                   //enable TIM16
095. 
096.    //set the pulse width to 10us (10 * 1us = 10us as described in the the timebase section)
097.  TIM_SetCompare1(TIM16, 10);                                               //for other channels this would be changed to TIM_SetCompare2..., or TIM_SetCompare3 etc.
098. 
099. 
100. 
101.    /* ===== Configure the ECHO pin =====
102.    PD4 will be used as the ECHO pin in this example.  It will be used in PWM INPUT mode and will use a counter
103.    tied to a timer to determine the pulse width of the signal from the HC-SR04 which represent the distance.
104.    PD4 is shared with TIM2_CH2 and USART2_RTS (see the STM32F3-Discovery User Manual p23).  We will use TIM2 in
105.    this example, seeing that TIM2 is a general purpose timer (easy to use) and is 32-bits (to hold a large value
106.    for long pulses).  Also see Chpt 17 on General Purpose Timers (TIM2/3/4) in the STM32F303xx Reference Manual
107.    RM0316) for more detail on the use of TIM2 as PWM INPUT mode.  The TIM2 register value will be updated every
108.    60ms with a new value for the resultant distance.  A read from the TIM2 register will thus provide the latest
109.    distance measured.  Not software code is required to trigger the sensor and to measure the pulse, it is all
110.    done by using a PWM output (TRIG) and a PWM input (ECHO) and using the associated hardware peripherals.
111. 
112.    Please note that any other free pin that shares a TIM could be used on the STM32F3-Discovery board.  Just
113.    make sure that the pin is not used by any of the onboard peripherals (p21-29 in the User Manual).
114.    */
115.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);                      //enable the TIM2 clock
116.  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);                       //enable the AHB Peripheral Clock to use GPIOD
117. 
118.    /* Pin configuration */
119.    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4;                             //configure PD4 in alternate function pushpull mode
120.    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
121.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
122.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
123.    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
124.    GPIO_Init(GPIOD, &GPIO_InitStructure);
125.    GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_2);                        //connect the pin to the desired peripherals' Alternate Function (AF) - TIM2 (GPIO_AF_2)
126. 
127.    /* Input Control (IC) configuration - PWM1 Mode configuration: Channel1 */
128.    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;                            //configre TIM2 for input-PWM mode
129.    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
130.    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
131.    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
132.    TIM_ICInitStructure.TIM_ICFilter = 0x0;
133.    TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
134. 
135.    /* Pin configuration */
136.    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_7;                             //configure PD7 in alternate function pushpull mode
137.    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
138.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
139.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
140.    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
141.    GPIO_Init(GPIOD, &GPIO_InitStructure);
142.    GPIO_PinAFConfig(GPIOD, GPIO_PinSource7,GPIO_AF_2);                     //connect the pin to the desired peripherals' Alternate Function (AF) - TIM2 (GPIO_AF_2)
143. 
144.    /* Input Control (IC) configuration - PWM1 Mode configuration: Channel1 */
145.    TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;                            //configre TIM2 for input-PWM mode
146.    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
147.    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
148.    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
149.    TIM_ICInitStructure.TIM_ICFilter = 0x0;
150.    TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
151. 
152.    TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
153.    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
154.    TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
155. 
156.    TIM_Cmd(TIM2, ENABLE);                                                  //enable TIM2
157. 
158. 
159.}
160. 
161.// -------------------------------------------------------------------------------
162. 
163.// Function to insert a timing delay of nTime
164.// ###### DO NOT CHANGE ######
165.void Delay(__IO uint32_t nTime){
166.  TimingDelay = nTime;
167. 
168.  while(TimingDelay != 0);
169.}
170. 
171.// Function to Decrement the TimingDelay variable.
172.// ###### DO NOT CHANGE ######
173.void TimingDelay_Decrement(void){
174.  if (TimingDelay != 0x00)  {
175.    TimingDelay--;
176.  }
177.}
178. 
179.// Unused functions that have to be included to ensure correct compiling
180.// ###### DO NOT CHANGE ######
181.// =======================================================================
182.uint32_t L3GD20_TIMEOUT_UserCallback(void)
183.{
184.  return 0;
185.}
186. 
187.uint32_t LSM303DLHC_TIMEOUT_UserCallback(void)
188.{
189.  return 0;
190.}
191.// =======================================================================
void init_USART2(long baudrate){


      USART_InitTypeDef USART_InitStructure;                                       // this is for the GPIO pins used as TX and R
      GPIO_InitTypeDef GPIO_InitStructure;                                             // this is for the USART1 initilization
      NVIC_InitTypeDef NVIC_InitStructure;                                         // this is used to configure the NVIC (nested vector interrupt controller)


      /* Configure USART1 pins:  Rx and Tx ----------------------------*/
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_5 | GPIO_Pin_6;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_Init(GPIOD, &GPIO_InitStructure);


      GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_7);
      GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_7);


      /* Configure USART1 pins:  --------------------------------------*/
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


      USART_DeInit(USART2);
      USART_InitStructure.USART_BaudRate = baudrate;
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_Parity = USART_Parity_No;
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_Init(USART2,&USART_InitStructure);


      USART_Cmd(USART2, ENABLE);
}


void printUART2 (char *buffer){
     while(*buffer){
          while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
          USART_SendData(USART2, *buffer++);
     }
}


Outcomes