LightWorks
Newbie level 5
Hi All,
Since this is my first post, I'm expecting a decent support from the forum members :-D
before I write my question, I would like to ensure you that I went through the Reference manual, datasheet, and text book (Embedded Systems with ARM Cortex-M Microcontrollers in Assembly Language and C - 2nd Edition), so I'm really doing my best here. However, I'm still unable to make this sensor work.
What I'm trying to do here is to measure the distance by sending a 10us pulse to Trigger-pin in order to start emitting a 40kHz square wave, which should be detected back and enable interrupt whenever a rising or falling edge gets detected. The time it takes between rising and falling edge will decide the distance, after dividing that time with 58 (given in the sensor datasheet) to give distance in centimeters. I have added a short code to enable the LED connected to PB7 whenever the distance is 100cm or less.
Now here is the code I've written. you will notice that the novice coding style, that's fine, I'm self-learning, still on my way there. I could use any advice in that regard too.
The code is built with no errors nor warnings.
Unfortunately the LED never turns On whether there's a close object or not.
here are the troubleshooting that I've done:
- in the debugger, the variable "Distance" value never changes, i.e. = 0
- I tried to measure the voltage at the Trigger pin using a simple multimeter, but I don't think it's fast enough to show 10us square wave..so basically it shows solid 0.00 on the trigger pin
- made some changes on the code, but still won't work.
Things that I'm not sure about (and would love to have an explanation to) are:
- Where/when is the right place to set/reset the variables "PulseSent" and "PulseEnd" ? as I feel these two variables has a major role on why it's not working.
- The function "TIM2_Enable" is used for both configuring TIM2 as well as sending the 10us Pulse. Is this ok, or should I separate them into 2 different functions?
Your support will be appreciated..
Regards,
Since this is my first post, I'm expecting a decent support from the forum members :-D
before I write my question, I would like to ensure you that I went through the Reference manual, datasheet, and text book (Embedded Systems with ARM Cortex-M Microcontrollers in Assembly Language and C - 2nd Edition), so I'm really doing my best here. However, I'm still unable to make this sensor work.
What I'm trying to do here is to measure the distance by sending a 10us pulse to Trigger-pin in order to start emitting a 40kHz square wave, which should be detected back and enable interrupt whenever a rising or falling edge gets detected. The time it takes between rising and falling edge will decide the distance, after dividing that time with 58 (given in the sensor datasheet) to give distance in centimeters. I have added a short code to enable the LED connected to PB7 whenever the distance is 100cm or less.
Now here is the code I've written. you will notice that the novice coding style, that's fine, I'm self-learning, still on my way there. I could use any advice in that regard too.
Code:
#include <stdio.h>
#include "stm32l1xx.h" // Keil::Device:Startup
// switch from HSE to HSI clock 16MHz
void HSI_config(){
RCC->CR |= RCC_CR_HSION; // Turn on HSI (16MHz)
while( (RCC->CR & RCC_CR_HSIRDY) == 0); // Wait until HSI is ready
RCC->CFGR &= ~RCC_CFGR_SW_HSI; // Select HSI as system clock
RCC->CFGR |= RCC_CFGR_SW_HSI;
while( (RCC->CFGR & RCC_CFGR_SWS)!=RCC_CFGR_SWS_HSI ); // Wait till HSI
}
// Configure GPIO Port B
void GPIO_config(){
RCC->AHBRSTR |= RCC_AHBRSTR_GPIOBRST; // Reset GPIOB clock
RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOBRST; // Clear Reset
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Enable GPIOB clock
//PB6 Echo Pin
GPIOB->MODER &= ~(0x03 << (2*6)); // Clear bit 12 & 13 Alternate function mode
GPIOB->MODER |= 0x02 << (2*6); // set as Alternate function mode
GPIOB->OSPEEDR &= ~(0x03<< (2*6)); // 40 MHz speed
GPIOB->OSPEEDR |= 0x03<< (2*6); // 40 MHz speed
GPIOB->PUPDR &= ~(1<<6); // NO PULL-UP PULL-DOWN
GPIOB->OTYPER &= ~(1<<6); // PUSH-PULL
GPIOB->AFR[0] |= 0x2 << (4*6); // set PB pin 6 as AF2 (TIM4_CH1)
//PB10 Pluse Generating Pin
GPIOB->MODER &= ~(0x03 << (2*10)); // Clear bit 12 & 13 Alternate function mode
GPIOB->MODER |= 0x02 << (2*10); // set as Alternate function mode
GPIOB->OSPEEDR &= ~(0x03<< (2*10)); // 40 MHz speed
GPIOB->OSPEEDR |= 0x03<< (2*10); // 40 MHz speed
GPIOB->PUPDR &= ~(1<<10); // NO PULL-UP PULL-DOWN
GPIOB->OTYPER &= ~(1<<10); // PUSH-PULL
GPIOB->AFR[1] |= 0x1 << (4*2); // set PB pin 10 as AF1 (TIM2_CH3)
//PB7 LED ON/OFF
GPIOB->MODER |= GPIO_MODER_MODER7_0; // General purpose output mode
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7; // Max High speed 50MHz
}
// CONFIGURE TIM4 FOR RECEIVING INPUT SIGNAL
void TIM4_Enable(){
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // ENABLE TIM4 CLOCK
TIM4->PSC = 15; // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK
TIM4->ARR = 0XFFFF; // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER
TIM4->CCMR1 &= ~TIM_CCMR1_CC1S; // CLEAR CAPTURE/COMPARE REGISTER
TIM4->CCMR1 |= 0X1; // SELECT CH1 INPUTE CAPTURE
TIM4->CCMR1 &= ~TIM_CCMR1_IC1F; // DISABLE DIGITAL FILTERING
TIM4->CCER |= (1<<1 | 1<<3); // SELECT BOTH RISING AND FALLING EDGE DETECTION CC1P & CC1NP
TIM4->CCMR1 &= ~(TIM_CCMR1_IC1PSC); // INPUT PRESCALER 0 TO CAPTURE EACH VALID EDGE
TIM4->CCER |= TIM_CCER_CC1E; // ENABLE COUNTER CAPTURE
TIM4->DIER |= TIM_DIER_UIE; // UPDATE INTERRUPT ENABLE
TIM4->DIER |= TIM_DIER_CC1IE; // ENABLE CH1 CAPTURE/COMPARE INTERRUPT
NVIC_SetPriority(TIM4_IRQn, 1); // SET PRIORITY TO 1
NVIC_EnableIRQ(TIM4_IRQn); //ENABLE TIM4 INTERRUPT IN NVIC
}
// CONFIGURE TIM2 FOR SENDING OUTPUT SIGNAL
void TIM2_Enable(){
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // ENABLE TIM2 CLOCK
TIM2->PSC = 15; // SET APPROPRAIT PRESCALER TO SLOW DOWN THE CLOCK
TIM2->ARR = 0XFFFF; // SET MAX PULSE WIDTH OF 65536us FOR 16-BIT TIMER
TIM2->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // 111: PWM mode 1
TIM2->CCMR2 |= TIM_CCMR2_OC3PE; // CH3 Output Preload Enable
TIM2->CR1 |= TIM_CR1_ARPE; // Auto-reload Prelaod Enable
TIM2->CCER |= TIM_CCER_CC3E; // Enable Output for CH3
TIM2->EGR |= TIM_EGR_UG; // Force Update
TIM2->SR &= ~TIM_SR_UIF; // Clear the Update Flag
TIM2->DIER |= TIM_DIER_UIE; // Enable Interrupt on Update
TIM2->CR1 |= TIM_CR1_DIR; // Set downcounting counter direction
TIM2->CR1 |= TIM_CR1_CEN; // Enable Counter
}
//Initialize the float variables.
volatile uint16_t timespan = 0; // Total pulse width
volatile uint16_t lastcounter = 0; // Timer counter value of the last event
volatile uint16_t newcounter = 0; // Timer counter value of the current event
volatile int overflow = 0; // Count the number of overflows
volatile int PulseEnd = 0; // Declare end of pulse
void Echo_TIM4_IRQHandler(){
if ((TIM4->SR & TIM_SR_UIF) != 0){ // Check the update even flag
overflow = overflow + 1; // if UIF = 1, increment overflow counter
TIM4->SR &= ~TIM_SR_UIF; // clear UIF
}
if ((TIM4->SR & TIM_SR_CC1IF) != 0){ // Check capture event flag
newcounter = TIM4->CCR1; // read capture value, store as newcounter
timespan = (newcounter - lastcounter)+(65536 * overflow); // calculate the total pulse width
lastcounter = newcounter; // save the value of newcounter as lastcounter to be used for the next cycle
overflow = 0; // clear overflow counter
PulseEnd = 1;
}
}
void setSysTick(void){
// ---------- SysTick timer (1ms) -------- //
if (SysTick_Config(SystemCoreClock / 1000)) {
// Capture error
while (1){};
}
}
volatile uint32_t msTicks; //counts 1ms timeTicks
void SysTick_Handler(void) {
msTicks++;
}
static void Delay(__IO uint32_t dlyTicks){
uint32_t curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks);
}
int main(void){
float Distance = 0.0f; // actual distance in cm
int PulseSent = 0;
HSI_config();
setSysTick();
GPIO_config();
TIM4_Enable();
Echo_TIM4_IRQHandler();
while(1){
if (Pulsesent == 0) {
(Pulsesent = 1);
TIM2_Enable();
}
if(PulseSent && PulseEnd){
PulseSent = 0;
PulseEnd = 0;
if(overflow == 1){
timespan = 0;
}
else {
Distance = (timespan / 58) ;
}
Delay(1);
}
if (Distance <= 100){
GPIOB->BSRRL = (1<<7);
}
else {
GPIOB->BSRRH = (1<<7);
}
}
}
The code is built with no errors nor warnings.
Unfortunately the LED never turns On whether there's a close object or not.
here are the troubleshooting that I've done:
- in the debugger, the variable "Distance" value never changes, i.e. = 0
- I tried to measure the voltage at the Trigger pin using a simple multimeter, but I don't think it's fast enough to show 10us square wave..so basically it shows solid 0.00 on the trigger pin
- made some changes on the code, but still won't work.
Things that I'm not sure about (and would love to have an explanation to) are:
- Where/when is the right place to set/reset the variables "PulseSent" and "PulseEnd" ? as I feel these two variables has a major role on why it's not working.
- The function "TIM2_Enable" is used for both configuring TIM2 as well as sending the 10us Pulse. Is this ok, or should I separate them into 2 different functions?
Your support will be appreciated..
Regards,