Microcontroller Unit Lab 6
Ultra-Sonic Range Finder
Using USB Serial Communications Port Output
Summary
Use a microcontoller to trigger sound pulses and use the echo time to
calculate distance then output via USB Serial Communication.
Pt. 1 USB Serial Communications Setup & Test
Pt. 2 Add a button - print a message on the usb com port terminal when it is pressed.
Pt. 3 Connect the ultrasonic module. The button should trigger a measurement. Time the echo pulse using CPU sleep, system clock and loops.
Pt. 4 Adjust the distance calculation using measured distances. Create a function for later re-use
Pt. 5 Create a function for later re-use. For instance, getUltrasonicDist() which returns a float or double.
Required Equipment and Supplies
- HCSR04 ultrasonic range finder - datasheet
- Rasperry Pi Pico with Headers - pinout diagram
- Momentary Switch (Push Button) [x1]
- USB Micro Cable
- Breadboard
- Cables and 22ga wire as needed
Wiring
- The HCSR04 does not use much powers, you may power everything from the USB cable.
- Use the Vsys pin to supply your breadboard power rail from the Pi Pico.
- The HCSR04 has only four wires to connect. Gnd, ECHO TRIG and Vcc.
- The ECHO is an ouput from the sensor should connect to a GP Input on the microcontroller.
optional: An oscilloscope probe can be connected to see the signal directly if you wish, as shown below.
- The TRIG is an input to the sensor should connect to a GP Output on the microcontroller.

Control Signal
The HCSR04 works by echo location. It sends sound pulses then uses a logic signal to communicate the time of flight of sound pulses.
- A logic pulse with a width of at least 10 us is given to the TRIG pin
- A short delay occurs while the sensor activates and sends 8 high frequency clicks. The sensor sends no signals during this.
- The sensor then pulls the ECHO pin to logic high. ECHO remains high until the sensor hears the echo or a time-out occurs.
- The duration of the high signal on ECHO indicates how long sound was travelling. A longer delay means farther distance travelled.
- The distance is traversed twice because sound must leave the sensor and travel back to it after reflecting off a surface.
Pt. 1 - Setting Up Serial Debugging
- Add the following lines of code to the CMakeLists.txt file of any project where you wish to use USB stdio messages.
#USB com enable
pico_enable_stdio_usb(${program_name} 1)
pico_enable_stdio_uart(${program_name} 0)
- Call the following function in main() some time before your primary loop. After this point printf() and puts() will send text to the a USB serial communcations port.
stdio_init_all();
- To test the USB com port, call printf() with a 'hello world' message followed by a delay using sleep_ms() with an appropriate time - maybe 500 ms.
- Compile the code using cmake and make then flash the pi pico as usual.
- To view the text output from the pico, open Serial Port Terminal (GTKterm). Under Configuration - Port select /dev/ttyACM0. If that port is not visible, the pico may not be communicating. You should be able to see your message printing at a half second interval or so.


Example Code For Pt. 5
...
/// Macros required by ultrasonic funciton below
#define USONIC_TRIG 19
#define USONIC_ECHO 20
#define BUTTON_MEASURE 16
#define SPEED_OF_SOUND_CM_PER_US 0.0334f
...
void ultasonic_pin_setup(){
gpio_init(USONIC_TRIG);
gpio_set_dir(USONIC_TRIG, GPIO_OUT);
gpio_init(USONIC_ECHO);
gpio_set_dir(USONIC_ECHO, GPIO_IN);
}
/// Returns distance in cm
float ultrasonic_get_dist(){
//1. send the trigger pulse
gpio_put(USONIC_TRIG, 1);
sleep_us(20);
gpio_put(USONIC_TRIG, 0);
//.2 measure the echo
//TODO: allow for timeout
float timeout_us = 0;
while(gpio_get(USONIC_ECHO) == 0) {
sleep_us(20);
timeout_us += 20;
if(timeout_us > 40000) return -1; //consider 40ms timeout
} //polling loop, CPU blocking
// Echo line is now high
float echo_time_us = 0;
while(gpio_get(USONIC_ECHO) == 1) {
sleep_us(20);
echo_time_us += 20;
if(echo_time_us > 40000) break;
} //polling loop, CPU blocking
//Echo line now low again
//CONVERT
float dist_cm = (SPEED_OF_SOUND_CM_PER_US * echo_time_us)/2.0f;
// divide by 2 because an echo travels the distance twice.
return dist_cm;
}