LAB: Input Capture - Ultrasonic
Date: 2024-10-10
Author/Partner:
Github: repository link
Demo Video: Youtube link
PDF version:
Introduction
In this lab, you are required to create a simple program that uses input capture mode to measure the distance using an ultrasonic distance sensor. The sensor also needs trigger pulses that can be generated by using the timer output.
You must submit
LAB Report (*.pdf & *.md)
Zip source files(main*.c, ecRCC.h, ecGPIO.h, ecSysTick.c etc...).
Only the source files. Do not submit project files
Requirement
Hardware
MCU
NUCLEO-F411RE
Actuator/Sensor/Others:
HC-SR04
breadboard
Software
Keil uVision, CMSIS, EC_HAL library
Tutorial: USART with Serial Monitor TeraTerm
Understand how to use serial monitor (TeraTerm) to display charicters(string) on PC sent from MCU.
Tutorial: STM-Arduino
We are going to create a simple program that measure distance by using ultrasonic sensor ‘HC-SR04’ and print out result through UART communication.
Procedure
Create a new project under the directory
\EC\LAB\TIMER_ICAP
Open Arduino IDE and Create a new program named as ‘TU_arduino_TIMER_ICAP.ino’.
Write the following code.
upload and run.
const int trigPin = 10; // Trigger pin : PWM out
const int echoPin = 7; // Echo pin : Interrupt in
unsigned long duration;
float distance;
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);
}
void loop() {
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
delayMicroseconds(10);
duration = pulseIn(echoPin, HIGH);
distance = (float)duration / 58.0;
Serial.printf("duration : %d Distance : ", duration);
Serial.print(distance);
Serial.println(" [cm]");
delay(500);
}
Click on Upload button.
Open ‘Tera Term’ and make New Connection.
Ultrasonic sensor ‘HC-SR04’ get trigger signal as 10[us] pwm through trig pin which generate on D10 pin. Also, you should capture the echo signal on D7 pin and measure its pulse-width to calculate the distance.

Press the reset button(black) and verify the operation. The distance between ultrasonic sensor and obstacle will be shown in Tera Term.

Click on Upload button.
Press the reset button(black) and verify the operation. The distance between ultrasonic sensor and obstacle will be shown in Tera Term.
Problem 1: Create HAL library
Create HAL library
Declare and Define the following functions in your library. You must update your header files located in the directory EC \lib\
.
Download Library Header Files
ecCAP2.h
/* Input Capture*/
// ICn selection according to CHn
#define FIRST 1
#define SECOND 2
// Edge Type
#define IC_RISE 0
#define IC_FALL 1
#define IC_BOTH 2
// IC Number
#define IC_1 1
#define IC_2 2
#define IC_3 3
#define IC_4 4
void ICAP_pinmap(PinName_t pinName, TIM_TypeDef **TIMx, int *chN);
void ICAP_init(PinName_t pinName);
void ICAP_setup(PinName_t pinName, int ICn, int edge_type);
void ICAP_counter_us(PinName_t pinName, int usec);
uint32_t ICAP_capture(TIM_TypeDef* TIMx, uint32_t ICn);
Problem 2: Ultrasonic Distance Sensor (HC-SR04)
The HC-SR04 ultrasonic distance sensor. This economical sensor provides 2cm to 400cm of non-contact measurement functionality with a ranging accuracy that can reach up to 3mm. Each HC-SR04 module includes an ultrasonic transmitter, a receiver and a control circuit.

The HC-SR04 Ultrasonic Range Sensor Features:
Input Voltage: 5V
Current Draw: 20mA (Max)
Digital Output: 5V
Digital Output: 0V (Low)
Sensing Angle: 30° Cone
Angle of Effect: 15° Cone
Ultrasonic Frequency: 40kHz
Range: 2cm - 400cm
Procedure
1. Create a new project under the directory \repos\EC\LAB\LAB_TIMER_ICAP
The project name is “LAB_TIMER_ICAP”.
Create a new source file named as “LAB_TIMER_ICAP.c”
You MUST write your name on the source file inside the comment section.
2. Include your updated library in \repos\EC\lib\
to your project.
Now, your ecSTM32F4v2.h
should be updated with
// EC course Library
#include "ecPinNames.h"
#include "ecRCC2.h"
#include "ecGPIO2.h"
#include "ecEXTI2.h"
#include "ecSysTick2.h"
#include "ecTIM2.h"
#include "ecPWM2.h"
#include "ecICAP2.h"
#include "ecUART2_simple.h"
3. Connect the HC-SR04 ultrasonic distance sensor to MCU pins(PA6 - trigger, PB6 - echo), VCC and GND
Measurement of Distance
The program needs to
Generate a trigger pulse as PWM to the sensor.
Receive echo pulses from the ultrasonic sensor
Measure the distance by calculating pulse-width of the echo pulse.
Display measured distance in [cm] on serial monitor of Tera-Term for
(a) 10mm (b) 50mm (c) 100mm
Configuration
PLL (84MHz)
PA6 (TIM3_CH1)
PB6 (TIM4_CH1)
AF, Push-Pull, No Pull-up Pull-down, Fast
AF, No Pull-up Pull-down
PWM period: 50msec pulse width: 10usec
Counter Clock : 0.1MHz (10us) TI4 -> IC1 (rising edge) TI4 -> IC2 (falling edge)
Circuit Diagram
You need to include the circuit diagram

Discussion
There can be an over-capture case, when a new capture interrupt occurs before reading the CCR value. When does it occur and how can you calculate the time span accurately between two captures?
Answer discussion questions
In the tutorial, what is the accuracy when measuring the period of 1Hz square wave? Show your result.
Answer discussion questions
Code
Your code goes here: ADD Code LINK such as github
Explain your source code with necessary comments.
// YOUR MAIN CODE ONLY
// YOUR CODE
Example Code
/**
******************************************************************************
* @author SSSLAB
* @Mod 2023-10-31 by YKKIM
* @brief Embedded Controller: LAB - Timer Input Capture
* - with Ultrasonic Distance Sensor
*
******************************************************************************
*/
#include "stm32f411xe.h"
#include "math.h"
#include "ecSTM32F4v2.h"
uint32_t ovf_cnt = 0;
float distance = 0;
float timeInterval = 0;
float time1 = 0;
float time2 = 0;
#define TRIG PA_6
#define ECHO PB_6
void setup(void);
int main(void){
setup();
while(1){
distance = (float) timeInterval * 340.0 / 2.0 / 10.0; // [mm] -> [cm]
printf("%f cm\r\n", distance);
delay_ms(500);
}
}
void TIM4_IRQHandler(void){
if(is_UIF(TIM4)){ // Update interrupt
__________ // overflow count
clear_UIF(TIM4); // clear update interrupt flag
}
if(is_CCIF(TIM4, 1)){ // TIM4_Ch1 (IC1) Capture Flag. Rising Edge Detect
time1 = __________; // Capture TimeStart
clear_CCIF(TIM4, 1); // clear capture/compare interrupt flag
}
else if(__________){ // TIM4_Ch2 (IC2) Capture Flag. Falling Edge Detect
time2 = __________; // Capture TimeEnd
timeInterval = __________; // (10us * counter pulse -> [msec] unit) Total time of echo pulse
ovf_cnt = 0; // overflow reset
clear_CCIF(TIM4,2); // clear capture/compare interrupt flag
}
}
void setup(){
RCC_PLL_init();
SysTick_init();
UART2_init();
// PWM configuration ---------------------------------------------------------------------
__________; // PA_6: Ultrasonic trig pulse
PWM_period_us(TRIG, 50000); // PWM of 50ms period. Use period_us()
PWM_pulsewidth_us(TRIG, 10); // PWM pulse width of 10us
// Input Capture configuration -----------------------------------------------------------------------
__________; // PB_6 as input caputre
ICAP_counter_us(ECHO, 10); // ICAP counter step time as 10us
ICAP_setup(ECHO, 1, IC_RISE); // TIM4_CH1 as IC1 , rising edge detect
__________; // TIM4_CH2 as IC2 , falling edge detect
}
Results
Experiment images and results
Show experiment images /results
Add demo video link
Reference
Complete list of all references used (github, blog, paper, etc)
Troubleshooting
(Option) You can write Troubleshooting section
Last updated
Was this helpful?