User Tools

Site Tools


Oak: Using an Ultrasonic Sensor



In this lesson, we will connect an ultrasonic sensor to the Oak. An ultrasonic sensor, using the properties of sound, not only detects an object, but also detects how far away the object is. The sensor generates a high frequency sound, then listens for an echo received back to the sensor. The time interval from send to receive allows you to calculate the distance.


Part Quantity Identification
Oak with soldered headers 1
Ultrasonic Sensor1HC-SR04
Level Shifter*1TXB0108
Jumper wires11

*Note: The HC-SR04 sensor is a 5v sensor, while the Oak is 3.3v. We will be using a bi-directional level shifter for compatibility. Given the plethora of micro electronic devices, and the race to use less and less power, it's not unusual to have a need for level shifting. Alternatively, a voltage divider may be used to drop the echo signal down from 5V to 3.3V.

Particle.publish will be used to send the sensor data to the cloud. To view the data, you will need your free Particle account. You most likely created one when you first set up your Oak. If you don't have one already get yours here:


Level Shifting

Level shifters are devices / chips that resolve mixed voltage incompatibility between different parts of a system that operate in multiple voltage domains. Bi-directional shifters, such as the one used here will convert voltages in both directions, and do this automatically, protecting your devices all the way around. The TXB0108 model contains an Output Enable Control (labeled OE on the device), that when left LOW, the TXB translator buffer will be disabled and the outputs are put into a high impedance state for increased power savings. In this state, output leakage will be less than ±2 mA. When the OE is HIGH (in this example the VCC power from the Oak), the outputs are put in a low impedance state.


pulseIn() can be thought of as a specific timer. pulseIn() takes at least 2 parameters, and up to 3, which are: pin, HIGH or LOW, and timeout. pulseIn() reads the pulse width value for the designated pin during a signal HIGH or LOW condition (designated by the state parameter). Pulse width value is the length of time the pin’s voltage remains HIGH or LOW.

For example, when the state parameter is set to HIGH, the pulseIn() function waits for the pin’s voltage change to HIGH and measures the length of time the pin’s voltage remains HIGH until it changes to LOW. The length of time is measured in millisecond. The maximum pulse width is 71 minutes. If nothing is detected within the specified time-out period, the function abandons the read attempt and returns 0.


The cloud offers many features that Oak users can take advantage of, some of which are quite in depth, and allow various devices to “communicate” with each other by passing information (like Particle.variable). If you just need something simple, such as a notification when something has happened, Particle.publish() may be what your looking for.

Particle.publish() can either be public (available to anyone who has the event name and uses Particle.subscribe) or private (only visible to you, your devices, etc).

Particle.publish() takes the name of the event, the data (char or String), TTL (length of time the data is good for), and if its private.


The HC-SR04 has 4 pins: VCC, Trig, Echo, and Gnd. The particular bi-directional level shifter being used in this example has 20 pins, we will be using 8 of them. The connections get a little tricky, be sure to refer to the schematic above.

  • Connect the Oak VCC to level shifter VCCA + OE
  • Connect Oak GND to level shifter GND
  • Connect Oak Pin 2 to level shifter A1
  • Connect Oak Pin 4 to level shifter A2
  • Connect Oak VIN to level shifter VCCB
  • Connect Level Shifter VCCB to sensor VCC
  • Level shifter B1 to sensor Echo
  • Level shifter B2 to sensor Trig
  • Level shifter GND to sensor GND


Here's a picture of the actual setup.

Alternative Circuit: Voltage Divider

If you don't have a level shifter, it is advised that you acquire one; they're handy to have around when working with 3.3V microdevices such as the Oak. That said, you can build this circuit using a voltage divider to drop the echo signal from 5V to 3.3V to interface with the Oak. It is not necessary to level shift the trigger signal. In the following circuit, we'll use Oak pin 2 to trigger the range finder, and pin 4 to read the echo.

   Oak           HC-SR04
  -----          -------
   VIN ----------- Vcc
    P2 ----------- TRIG
    P4 ---+--1K--- ECHO
          2K                 (Any pair of 500-20k Ohm resistors with roughly 2:1 ratio will work)
   GND ---+------- GND


Alternative build option using voltage divider instead of level shifter


The first part of our sketch is the variable declaration:

 HC-SR04 with TCB0108 level shifter
 Oak VCC to level shifter VCCA + OE
 Oak GND to level shifter GND
 Oak Pin 2 to level shifter A1
 Oak Pin 4 to level shifter A2
 Oak VIN to level shifter VCCB
 Level Shifter VCCB to sensor VCC
 Level shifter B1 to sensor Echo
 Level shifter B2 to sensor Trig
 Level shifter GND to sensor GND

int trigPin = 2; // Trigger Pin
int echoPin = 4; // Echo Pin
int LEDPin = 1; // Onboard LED

long Time_Echo_us; 
long inches; 

char post_Distance[8]; //particle post variable

Next we tell the Oak what the pins will be doing in the setup section:

void setup() {
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 pinMode(LEDPin, OUTPUT); // Use onboard LED for visual feedback

Now the loop portion. First we tell the sensor to send a sound:

void loop() {

 //Make sure the trigger pin is off
 digitalWrite(trigPin, LOW); 

//tell the sensor to send its pulse 
 digitalWrite(trigPin, HIGH);
 //end trigger
 digitalWrite(trigPin, LOW);

Then listen for the echo:

 // pulseIn HIGH starts measuring the time until it hears the echo
 Time_Echo_us = pulseIn(echoPin, HIGH);  
 // Calculate distance to object. Divide by 2 because echo time is roundtrip
 inches = (Time_Echo_us/2) / 74;

Now that we have our data, let's use it:

//Send distance to cloud for viewing by Particle dashboard, and OakTerm
 sprintf(post_Distance, "%03d", inches); //convert int to string for Particle.publish
  Particle.publish("distance:", post_Distance);
Use onboard LED for visual feedback, adjust values based on what you see via Particle.publish
Could attach an RGB LED to change colors based on distance           
 if((inches < 36) && (inches > 1)) {   // limit the distance from the sensor's overall range
digitalWrite(LEDPin, HIGH); 
 else { 
 digitalWrite(LEDPin, LOW); 


You did it. You properly connected, and used an ultrasonic sensor to your Oak, and sent the data to the cloud. Make sure that you log in, and visit your Oak's logs at If you have registered multiple Oaks (why wouldn't you have more than one?), be sure to view the logs for the correct Oak.

Look into other Particle functions at your disposal, such as Particle.variable, that allow you to post your variable, and even access it with another (read 2nd or 3rd oak) device.

What can you use an ultrasonic sensor for?

  • Trigger a buzzer when someone / something walks past
  • Use a sensor on a servo to create a map
oak/tutorials/ultrasonic_2.txt · Last modified: 2017/01/09 23:55 by Rover#18