/ 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  }