/ Trinket_Ultrasonic_Rangefinder / code.py
code.py
1 # SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 """ 6 This Code uses the: 7 * Adafruit LCD backpack using MCP23008 I2C expander 8 * Maxbotic LV-EZ1 Ultrasonic Sensor 9 10 Tested with the Trinket M0 11 The ultrasonic sensor and pin use should be Gemma M0 compatible 12 This sketch reads the LV-EZ1 by pulse count 13 Then prints the distance to the LCD and python console 14 15 The circuit: 16 * 5V to Trinket M0 USB or BAT pin, I2C Backpack 5V and EZ1 +5 17 * GND to Trinket M0 GND pin, I2C Backpack GND and EZ1 GND 18 * Display I2C Backpack SLK to Trinket GPIO #2 19 * Display I2C backpack SDA to Trinket GPIO #0 20 * LV-EZ1 Ultrasonic Sensor PW pin to Trinket GPIO #1 21 * Backlight can be hard wired by connecting LCD pin 16, 17 or 18 to GND 22 """ 23 24 import time 25 26 import adafruit_character_lcd 27 import board 28 import busio 29 import pulseio 30 31 ez1pin = board.D1 # Trinket GPIO #1 32 33 # i2c LCD initialize bus and class 34 i2c = busio.I2C(board.SCL, board.SDA) 35 cols = 16 36 rows = 2 37 lcd = adafruit_character_lcd.Character_LCD_I2C(i2c, cols, rows) 38 39 # calculated mode or median distance 40 mode_result = 0 41 42 # pulseio can store multiple pulses 43 # read in time for pin to transition 44 samples = 18 45 pulses = pulseio.PulseIn(board.D1, maxlen=samples) 46 47 # sensor reads which are in range will be stored here 48 rangevalue = [0, 0, 0, 0, 0, 0, 0, 0, 0] 49 50 # 25ms sensor power up pause 51 time.sleep(.25) 52 53 54 def tof_cm(time_of_flight): 55 """ 56 EZ1 ultrasonic sensor is measuring "time of flight" 57 Converts time of flight into distance in centimeters 58 """ 59 convert_to_cm = 58 60 cm = time_of_flight / convert_to_cm 61 62 return cm 63 64 65 def tof_inches(time_of_flight): 66 """ 67 EZ1 ultrasonic sensor is measuring "time of flight" 68 Converts time of flight into distance in inches 69 """ 70 convert_to_inches = 147 71 inches = time_of_flight / convert_to_inches 72 73 return inches 74 75 76 def find_mode(x): 77 """ 78 find the mode (most common value reported) 79 will return median (center of sorted list) 80 should mode not be found 81 """ 82 n = len(x) 83 84 if n == 0: # If somehow there is a null array 85 return 0 86 87 if n == 1: # In trivial case of a one element array 88 return x[0] # just return the element as the mode. 89 90 max_count = 0 91 mode = 0 92 bimodal = 0 93 counter = 0 94 index = 0 95 96 while index < (n - 1): 97 prev_count = counter 98 counter = 0 99 100 while (x[index]) == (x[index + 1]): 101 counter += 1 102 index += 1 103 104 if (counter > prev_count) and (counter > max_count): 105 mode = x[index] 106 max_count = counter 107 bimodal = 0 108 109 if counter == 0: 110 index += 1 111 112 # If the dataset has 2 or more modes. 113 if counter == max_count: 114 bimodal = 1 115 116 # Return the median if there is no mode. 117 if (mode == 0) or (bimodal == 1): 118 mode = x[int(n / 2)] 119 120 return mode 121 122 123 while True: 124 125 # wait between samples 126 time.sleep(.5) 127 128 if len(pulses) == samples: 129 j = 0 # rangevalue array counter 130 131 # only save the values within range 132 # range readings take 49mS 133 # pulse width is .88mS to 37.5mS 134 for i in range(0, samples): 135 tof = pulses[i] # time of flight - PWM HIGH 136 137 if 880 < tof < 37500: 138 if j < len(rangevalue): 139 rangevalue[j] = tof_cm(tof) 140 j += 1 141 142 # clear pulse samples 143 pulses.clear() # clear all values in pulses[] 144 145 # sort samples 146 rangevalue = sorted(rangevalue) 147 148 # returns mode or median 149 mode_result = int(find_mode(rangevalue)) 150 151 # python console prints both centimeter and inches distance 152 cm2in = .393701 153 mode_result_in = mode_result * cm2in 154 print(mode_result, "cm", "\t\t", int(mode_result_in), "in") 155 156 # result must be in char/string format for LCD printing 157 digit_string = str(mode_result) 158 159 lcd.clear() 160 lcd.message("Range: ") # write to LCD 161 lcd.message(" ") 162 lcd.message(digit_string) 163 lcd.message("cm") 164 165 time.sleep(2)