Introduction: Ultrasonic Sensor With Haptic Feedback

Our goal is to develop an ultrasonic sensor with haptic feedback for people, similar to the 'lane assist' feature in automobiles. We use a microcontroller coded in CircuitPython to take an input from the ultrasonic sensor, then using a programmed threshold, we activate the haptic sensor. We are utilizing this ultrasonic-haptic method for helping visually impaired and blind individuals in stage performances to help position them in the appropriate place and be in sync with the rest of the performers inconspicuously so the audience do not see who is visually impaired. This method holds immense potential for various other practical implementations.

You can use this technology to serve as an obstacle avoidance system for autonomous go karts, ensure seamless navigation through spaces, make smart homes becoming more accessible, with doorways equipped to notify inhabitants of approaching individuals, personalize educational tools to shopping assistance devices - the possibilities are boundless. We hope that this instructable provides clear instructions for anyone to build an ultrasonic-haptic device. There are many comments in the code, which will help you change any parameters to suit your needs.

Note: this project needs just one soldering step to connect the haptic motor to the motor controller board.

Supplies

Step 1: Build the Circuit

Connecting the ultrasonic sensor to microcontroller

RCWL-1601 has 4 connections - VCC, Trigger, Echo, and GND. Trigger and Echo pins need to be connected to the Feather through a 10KΩ pull-up resistor so that these pins are not left in a floating state. You can learn more about pull- up resistors here.

  1. Connect VCC from RCWL-1601 to the 3V pin on the Adafruit Feather M4 board.
  2. Connect GND from RCWL-1601 to the Adafruit Feather M4 board.
  3. Connect Trigger pin of RCWL-1601 to one end of a 10KΩ resistor and connect this end of the resistor to pin 5 on the Adafruit Feather M4 board.
  4. Connect the other end of the resistor to the VCC.
  5. Connect Echo pin of RCWL-1601 to one end of a 10KΩ resistor and connect this end of the resistor to pin 6 on the Adafruit Feather M4 board.
  6. Connect the other end of the resistor to the VCC.


Connecting the haptic motor to microcontroller

DRV2605L first needs to be connected to the haptic motor. Solder the red wire of the haptic motor to the positive terminal on this board and solder the blue wire of the haptic motor to the negative terminal on this board. We are using the I2C protocol to communicate with the Feather so the connections are straightforward.

  1. Connect VIN from DRV2605L to the 3V pin on the Adafruit Feather M4 board.
  2. Connect GND from DRV2605L to the Adafruit Feather M4 board.
  3. Connect SCL pin of DRV2605L to SCL on Adafruit Feather M4 board.
  4. Connect SDA pin of DRV2605L to SDA on Adafruit Feather M4 board.

Step 2: CircuitPython Code

CircuitPython Installation

Please check out this link for Circuit Python installation.

https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython


DRV 2605 Haptic Driver Library installation

First make sure you are running the latest version of Adafruit CircuitPython for your board.

Adafruit's introduction guide has a great page on how to install the library bundle for both express and non-express boards. Next you'll need to install the necessary libraries to use the haptic motor driver. Carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle. Since the memory is limited on the microcontroller, you only need to transfer 'adafruit_drv2605.mpy' file into the lib folder on CircuitPython Drive in your microcontroller board.


Mu Editor Installation

For this project our IDE was Mu editor, we recommend you also use this IDE since it's simple and powerful. https://codewith.mu/en/download

After installing the Mu Editor, connect to the board's serial REPL through the USB-USB-C cable, so you are at the CircuitPython >>> prompt.


Explanation of Code

The CircuitPython code utilizes various libraries to control an RCWL-1601 ultrasonic sensor and a DRV2605 haptic feedback motor through both configuring the digital pins (for the ultrasonic sensor) and through I2C bus (for the haptic motor controller). Though the ultrasonic sensor can be connected to an I2C bus, there is a known issue that it can lock up the I2C bus. The ultrasonic sensor's trigger and echo pins are configured on the microcontroller and in our case we connected these pins to D5 and D6 respectively. The code triggers the sensor, measures the time it took for echo pulse, and calculates the distance based on the speed of sound. If the measured distance is within two feet or beyond four feet, it activates haptic feedback with a specific effect ID (chosen from among 123 built-in vibration effect ids) using the DRV2605 motor driver. The program continuously operates in an infinite loop, printing the measured distance and triggering haptic feedback when applicable.

# Import necessary libraries
# These libraries provide essential tools for managing time, accessing pin definitions, reading digital pulses, and controlling haptic feedback motors.
import time
import board
import digitalio
import adafruit_drv2605

# Configure HC-SR04 sensor pins
# Define trigger and echo pins on the microcontroller to interface with the HC-SR04 ultrasonic sensor.
trig_pin = board.D5 # The 'trig_pin' is set to D5, representing the trigger pin of the ultrasonic sensor.
echo_pin = board.D6 # The 'echo_pin' is set to D6, representing the echo pin of the ultrasonic sensor.
# Prepare to listen to the ultrasonic sensor's echo pin
# We use the 'DigitalInOut' tool to listen for signals (high or low) coming from the echo pin.
sonar = digitalio.DigitalInOut(echo_pin)
#'sonar' is set up to tell us if the echo pin is sending a strong signal (high) or not (low).
# This helps us measure distances because the sensor sends a signal, and 'sonar' lets us know when it comes back.

# Set up the echo pin as an input
# We are telling our sonar to listen attentively by setting the direction of the echo pin (D6) as 'INPUT'.
sonar.direction = digitalio.Direction.INPUT
# sonar is ready to notice any signals (changes from high to low or vice versa) coming from the echo pin.

# Initialize I2C bus and DRV2605 module
# Create an I2C communication bus and initialize the DRV2605 haptic feedback motor driver using that bus.
i2c = board.I2C() # 'i2c' is an I2C communication bus used for communication with the DRV2605.
drv = adafruit_drv2605.DRV2605(i2c) # 'drv' is an instance of the DRV2605 driver, enabling control over haptic feedback.

# Configure digital output for trigger pin
# Create a digital output object for the trigger pin and set it as an output. This pin is used to trigger the ultrasonic sensor.
trig = digitalio.DigitalInOut(trig_pin) # 'trig' is a digital output object created for the trigger pin.
trig.direction = digitalio.Direction.OUTPUT # The trigger pin is configured as an output.

# Main loop for running haptic feedback when an object is within two feet
# This loop continuously triggers the ultrasonic sensor to measure distance and activates haptic feedback if an object is within two feet.
effect_id = 119 # 'effect_id' represents the feedback effect ID to be played by the haptic motor.
while True: # Infinite loop for continuous operation.

  # Trigger the ultrasonic sensor to measure distance
  trig.value = True # Setting the trigger pin high initiates the ultrasonic sensor's pulse transmission.
  time.sleep(0.001) # A brief pause (1 millisecond) to allow the sensor's pulse to propagate.
  trig.value = False # Setting the trigger pin low stops the pulse transmission.

  # Measure distance using the ultrasonic sensor
  while sonar.value == False: # Wait for the echo pin to go high.
    pulse_start = time.monotonic() # Record the start time before the echo pin goes high.
  while sonar.value == True: # Wait for the echo pin to go low.
    pulse_end = time.monotonic() # Record the end time before the echo pin goes low.

  pulse_duration = pulse_end - pulse_start # Calculate the duration of the pulse in seconds.
  distance = (pulse_duration * 34300) / 2 # Use the pulse duration to calculate the distance in centimeters (speed of sound = 34300 cm/s).
  print("Distance: {0} cm".format(distance)) # Print the measured distance.

  # Check if the distance is within two feet
  if (0 < distance < 60 or distance > 120): # Check if the distance is within the specified range (0 to 60.96 cm).
    # Trigger haptic feedback with the specified effect ID
    print("Within two feet or 4 feet. Playing effect #{0}".format(effect_id)) # Display a message indicating the object is within two feet.
    drv.sequence[0] = adafruit_drv2605.Effect(effect_id) # Set the haptic feedback effect.
    drv.play() # Play the haptic feedback effect.
    time.sleep(0.5) # Wait for a short duration (0.5 seconds).
    drv.stop() # Stop the haptic feedback.

  # Pause for 1 second before the next iteration
  time.sleep(1) # Wait for 1 second before taking the next distance measurement.

Step 3: Test

This a video of our ultrasonic sensor that drives the haptic motor when there is an obstacle within 60 cm and beyond 120 cm.

Anything Goes Contest

Participated in the
Anything Goes Contest