Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Colonel Panic
Published

Haptic Vision Assist

Simple, affordable, and effective mobility assistance for visually impaired users using micro-controllers, infrared lasers, and haptics.

IntermediateFull instructions provided4 hours664

Things used in this project

Hardware components

M5StickC ESP32-PICO Mini IoT Development Board
M5Stack M5StickC ESP32-PICO Mini IoT Development Board
×3
Time-of-Flight (ToF) VL53L0X Laser Ranging Unit (MCP4725/)
M5Stack Time-of-Flight (ToF) VL53L0X Laser Ranging Unit (MCP4725/)
×3
HAT-Vibrator
M5Stack HAT-Vibrator
×3
Unbuckled Grove Cable 1m/2m/50cm/20cm/10cm
M5Stack Unbuckled Grove Cable 1m/2m/50cm/20cm/10cm
×3
Lego technics ball joints (adjustable)
×1
Ceramic magnetic disks, sticker adhesive
×1
Magnetic usb-c charging cables
×1
Adjustable padded Lanyard
×1
Assorted bulk lego technics pieces
×1

Software apps and online services

m5stack uiflow

Story

Read more

Schematics

Module and sensor

Module and sensor

Code

Abdomen/Lower module (Micropython Version)

MicroPython
Detects obstacles on either side of the user and vibrates the module according to distance. If an edge/decline is detected, the vibration module returns a series of on/off vibrational pulses.
from m5stack import *
from m5ui import *
from uiflow import *
import time
import i2c_bus
from easyIO import *
import unit
import hat


setScreenColor(0x111111)
tof_0 = unit.get(unit.TOF, unit.PORTA)

hat_vibrator_0 = hat.get(hat.VIBRATOR)

distance = None
calibrate = None
batt = None



label1 = M5TextBox(7, 99, "label1", lcd.FONT_DejaVu40, 0xFFFFFF, rotate=0)


# Describe this function...
def hip_distance():
  global distance, calibrate, batt, i2c0
  distance = tof_0.distance
  if calibrate == None:
    if distance==distance < 400:
      hat_vibrator_0.set_duty(100)
    elif distance==distance < 800:
      hat_vibrator_0.set_duty(80)
    elif distance==distance < 1200:
      hat_vibrator_0.set_duty(60)
    elif distance==distance < 1600:
      hat_vibrator_0.set_duty(40)
    elif distance==distance < 1800:
      hat_vibrator_0.set_duty(30)
    elif distance==distance < 2000:
      hat_vibrator_0.set_duty(20)
    else:
      hat_vibrator_0.turn_off()
  elif calibrate != None:
    if distance==distance >= calibrate + 101:
      hat_vibrator_0.set_duty(100)
      wait_ms(100)
      hat_vibrator_0.set_duty(0)
      wait_ms(50)
    elif distance==distance < 400:
      hat_vibrator_0.set_duty(100)
    elif distance==distance < 800:
      hat_vibrator_0.set_duty(80)
    elif distance==distance < 1200:
      hat_vibrator_0.set_duty(60)
    elif distance==distance < 1600:
      hat_vibrator_0.set_duty(40)
    elif distance==distance < 1800:
      hat_vibrator_0.set_duty(30)
    elif distance==distance < 2000:
      hat_vibrator_0.set_duty(20)
    else:
      hat_vibrator_0.turn_off()

# Describe this function...
def one_pulse():
  global distance, calibrate, batt, i2c0
  hat_vibrator_0.set_duty(50)
  wait_ms(100)
  hat_vibrator_0.turn_off()
  wait_ms(50)

# Describe this function...
def two_pulse():
  global distance, calibrate, batt, i2c0
  hat_vibrator_0.set_duty(50)
  wait_ms(100)
  hat_vibrator_0.turn_off()
  wait_ms(50)
  hat_vibrator_0.set_duty(50)
  wait_ms(100)
  hat_vibrator_0.turn_off()
  wait_ms(50)


def buttonA_pressFor():
  global distance, calibrate, batt, i2c0
  hat_vibrator_0.turn_off()
  label1.setColor(0xcc33cc)
  calibrate = distance
  axp.setLcdBrightness(100)
  speaker.tone(800, 200)
  speaker.tone(1200, 200)
  axp.setLcdBrightness(0)
  pass
btnA.pressFor(0.8, buttonA_pressFor)

def buttonB_wasPressed():
  global distance, calibrate, batt, i2c0
  hat_vibrator_0.turn_off()
  if batt==batt < 10:
    hat_vibrator_0.turn_off()
    speaker.setVolume(25)
    speaker.tone(900, 200)
  elif batt==batt < 20:
    one_pulse()
  elif batt==batt < 30:
    two_pulse()
  elif batt==batt < 40:
    one_pulse()
    two_pulse()
  elif batt==batt < 50:
    two_pulse()
    two_pulse()
  elif batt==batt < 60:
    two_pulse()
    two_pulse()
    one_pulse()
  elif batt==batt < 70:
    two_pulse()
    two_pulse()
    two_pulse()
  elif batt==batt < 80:
    two_pulse()
    two_pulse()
    two_pulse()
    one_pulse()
  elif batt==batt < 90:
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
  elif batt==batt < 95:
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
    one_pulse()
  elif batt==batt <= 100:
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
  else:
    hat_vibrator_0.turn_off()
  pass
btnB.wasPressed(buttonB_wasPressed)

def buttonA_wasDoublePress():
  global distance, calibrate, batt, i2c0
  hat_vibrator_0.turn_off()
  label1.setColor(0xcc33cc)
  calibrate = None
  label1.setText('clear')
  axp.setLcdBrightness(100)
  speaker.tone(1200, 200)
  speaker.tone(800, 200)
  axp.setLcdBrightness(0)
  pass
btnA.wasDoublePress(buttonA_wasDoublePress)


speaker.setVolume(50)
hat_vibrator_0.set_duty(0)
axp.setLcdBrightness(0)
i2c0 = i2c_bus.easyI2C(i2c_bus.PORTA, 0x00, freq=400000)
label1.setColor(0x000000)
hat_vibrator_0.set_duty(100)
wait_ms(100)
hat_vibrator_0.set_duty(0)
wait_ms(50)
hat_vibrator_0.set_duty(100)
wait_ms(100)
hat_vibrator_0.set_duty(0)
while True:
  batt = map_value((axp.getBatVoltage()), 3.7, 4.1, 0, 100)
  hip_distance()
  label1.setText(str(calibrate))
  wait_ms(2)

Face/Head Module (micropython version)

MicroPython
Triggers vibrational alarm when an object is within 3-4 feet of the wearer's face. Flashed to M5StickCplus module
from m5stack import *
from m5ui import *
from uiflow import *
import i2c_bus
import time
from easyIO import *
import unit
import hat


setScreenColor(0x111111)
tof_0 = unit.get(unit.TOF, unit.PORTA)

hat_vibrator_0 = hat.get(hat.VIBRATOR)

distance = None
batt = None



label1 = M5TextBox(29, 42, "Haptic", lcd.FONT_DejaVu24, 0xe600ff, rotate=0)
label2 = M5TextBox(29, 134, "Assist", lcd.FONT_DejaVu24, 0x9900ff, rotate=0)
label3 = M5TextBox(46, 186, "1.0", lcd.FONT_DejaVu24, 0x0041ff, rotate=0)
label0 = M5TextBox(29, 86, "Vision", lcd.FONT_DejaVu24, 0x4d00ff, rotate=0)


# Describe this function...
def head_distance():
  global distance, batt, i2c0
  distance = tof_0.distance
  if distance==distance < 1000:
    hat_vibrator_0.set_duty(100)
  else:
    hat_vibrator_0.turn_off()

# Describe this function...
def one_pulse():
  global distance, batt, i2c0
  hat_vibrator_0.set_duty(50)
  wait_ms(100)
  hat_vibrator_0.turn_off()
  wait_ms(50)

# Describe this function...
def two_pulse():
  global distance, batt, i2c0
  hat_vibrator_0.set_duty(50)
  wait_ms(100)
  hat_vibrator_0.turn_off()
  wait_ms(50)
  hat_vibrator_0.set_duty(50)
  wait_ms(100)
  hat_vibrator_0.turn_off()
  wait_ms(50)


def buttonA_wasPressed():
  global distance, batt, i2c0
  hat_vibrator_0.turn_off()
  if batt==batt < 10:
    hat_vibrator_0.turn_off()
    speaker.setVolume(25)
    speaker.tone(900, 200)
  elif batt==batt < 20:
    one_pulse()
  elif batt==batt < 30:
    two_pulse()
  elif batt==batt < 40:
    one_pulse()
    two_pulse()
  elif batt==batt < 50:
    two_pulse()
    two_pulse()
  elif batt==batt < 60:
    two_pulse()
    two_pulse()
    one_pulse()
  elif batt==batt < 70:
    two_pulse()
    two_pulse()
    two_pulse()
  elif batt==batt < 80:
    two_pulse()
    two_pulse()
    two_pulse()
    one_pulse()
  elif batt==batt < 90:
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
  elif batt==batt < 95:
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
    one_pulse()
  elif batt==batt <= 100:
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
    two_pulse()
  else:
    hat_vibrator_0.turn_off()
  pass
btnA.wasPressed(buttonA_wasPressed)


axp.setLcdBrightness(0)
i2c0 = i2c_bus.easyI2C(i2c_bus.PORTA, 0x00, freq=400000)
hat_vibrator_0.turn_off()
axp.setLcdBrightness(50)
wait(3)
axp.setLcdBrightness(0)
hat_vibrator_0.set_duty(100)
wait_ms(100)
hat_vibrator_0.set_duty(0)
wait_ms(50)
hat_vibrator_0.set_duty(100)
wait_ms(100)
hat_vibrator_0.set_duty(0)
while True:
  batt = map_value((axp.getBatVoltage()), 3.7, 4.1, 0, 100)
  head_distance()
  wait_ms(2)

Credits

Colonel Panic
3 projects • 7 followers
Heckr
Contact

Comments

Please log in or sign up to comment.

1
2
3
Hey stranger! Sign up to access unlimited projects featuring LEGO and more – it's free.
Not now