/ Trinket_Ultrasonic_Rangefinder / Trinket_Ultrasonic_Rangefinder.ino
Trinket_Ultrasonic_Rangefinder.ino
1 // SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries 2 // SPDX-FileCopyrightText: 2018 Anne Barela for Adafruit Industries 3 // 4 // SPDX-License-Identifier: MIT 5 6 /* 7 Demonstration sketch for Adafruit LCD backpack 8 using MCP23008 I2C expander and Maxbotic LV-EZ1 Ultrasonic Sensor 9 (other pin compatible Maxbotix sensors should also work) 10 Tested with the 5 volt Trinket mini microcontroller at 8 MHz 11 The ultrasonic sensor and pin use should be Gemma and Trinket 3V compatible 12 13 This sketch reads the LV-EZ1 by pulse count and prints the distance to the LCD 14 15 The circuit: 16 * 5V to Arduino 5V pin, I2C Backpack 5V and EZ1 +5 17 * GND to Arduino GND pin, I2C Backpack GND and EZ1 GND 18 * Display I2C Backpack CLK to Trinket GPIO #2 19 * Display I2C backpack DAT to Trinket GPIO #0 20 * LV-EZ1 Ultrasonic Sensor PW pin to Trinket GPIO #1 21 22 Portions of code provided free use on http://playground.arduino.cc/Main/MaxSonar 23 by Bruce Allen and Bill Gentles 24 25 Version 2.0 Adds Arduino IDE 1.6.7 and greater Wire support 26 Anne Barela for Adafruit Industries 27 */ 28 29 // include the library code 30 #include <Adafruit_LiquidCrystal.h> // Tiny LiquidCrystal library using TinyWireM 31 32 #define EZ1pin 1 // Trinket GPIO #1 33 34 // Connect display via i2c, default address #0 (A0-A2 not jumpered) 35 Adafruit_LiquidCrystal lcd(0); 36 37 // These values are for calculating a mathematical median for a number of samples as 38 // suggested by Maxbotix instead of a mathematical average 39 int8_t arraysize = 9; // quantity of values to find the median (sample size). Needs to be an odd number 40 //declare an array to store the samples. not necessary to zero the array values here, it just makes the code clearer 41 uint16_t rangevalue[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0}; 42 uint16_t modE; // calculated median distance 43 44 void setup() { 45 pinMode(EZ1pin, INPUT); // Sey ultrasonic sensor pin as input 46 lcd.begin(16, 2); // set up the LCD number of rows and columns: 47 lcd.setBacklight(HIGH); // Set backlight on (HIGH on, LOW off) 48 } 49 50 void loop() { 51 int16_t pulse; // number of pulses from sensor 52 int i=0; 53 54 while( i < arraysize ) 55 { 56 pulse = pulseIn(EZ1pin, HIGH); // read in time for pin to transition 57 rangevalue[i]=pulse/58; // pulses to centimeters (use 147 for inches) 58 if( rangevalue[i] < 645 && rangevalue[i] >= 15 ) i++; // ensure no values out of range 59 delay(10); // wait between samples 60 } 61 isort(rangevalue,arraysize); // sort samples 62 modE = mode(rangevalue,arraysize); // get median 63 64 lcd.setCursor(0, 0); // write data to LCD display via I2C backpack 65 lcd.print("Range: "); // write to LCD 66 lcd.setCursor(7,0); 67 lcd.print(" "); 68 lcd.setCursor(7,0); 69 lcd.print(modE); 70 lcd.setCursor(11,0); 71 lcd.print("cm"); 72 73 delay(500); // Read every half second 74 } 75 76 // Sorting function (Author: Bill Gentles, Nov. 12, 2010) 77 void isort(uint16_t *a, int8_t n){ 78 for (int i = 1; i < n; ++i) { 79 uint16_t j = a[i]; 80 int k; 81 for (k = i - 1; (k >= 0) && (j < a[k]); k--) { 82 a[k + 1] = a[k]; 83 } 84 a[k + 1] = j; 85 } 86 } 87 88 // Mode function, returning the mode or median. 89 uint16_t mode(uint16_t *x,int n){ 90 int i = 0; 91 int count = 0; 92 int maxCount = 0; 93 uint16_t mode = 0; 94 int bimodal; 95 int prevCount = 0; 96 while(i<(n-1)){ 97 prevCount=count; 98 count=0; 99 while( x[i]==x[i+1] ) { 100 count++; 101 i++; 102 } 103 if( count > prevCount && count > maxCount) { 104 mode=x[i]; 105 maxCount=count; 106 bimodal=0; 107 } 108 if( count == 0 ) { 109 i++; 110 } 111 if( count == maxCount ) { //If the dataset has 2 or more modes. 112 bimodal=1; 113 } 114 if( mode==0 || bimodal==1 ) { // Return the median if there is no mode. 115 mode=x[(n/2)]; 116 } 117 return mode; 118 } 119 return 0; 120 }