Robojax

Lesson 76: Using VL6180 62cm Laser Distance sensors with Arduino

Lesson 76: Using VL6180 62cm Laser Distance sensors with Arduino

Please select other codes for this lecture from the links below.

  • VL6180 Datasheet (pdf)
  • Part 8: Obstacle Avoidance with Arduino

    In this lesson we learn how to use one, two or more VL6180 62cm laser ToF (Time of Flight) distance sensor using Arduino. the module is explained, wiring diagram shown and wiring is explained. Code is fully explained and demonstrated. This code is for two sensor.

    wiring diagram for VL6180
    
      /*
     *  Arduino code 
    * Lesson 76-2: Using two or more VL6180 Laser  Distance Sensor with Arduino 
     * Adafruit code modified for this tutorial 
    Using two or more VL6180X 20cm Time-of-Flight proximity sensor with Arduino
    
    View code for using single VL6180X sensors: https://robojax.com/course1/lecture76
    
     * Original code and library by https://github.com/adafruit/Adafruit_VL6180X
     * 
     * Written/updated by Ahmad Shamshiri for Robojax Robojax.com
     * on Mar 12, 2021  in Ajax, Ontario, Canada
     Watch the video instruction for this sketch: https://youtu.be/_H9D0czQpSI
     
    
    
    Please watch video instruciton of this code : https://youtu.be/_H9D0czQpSI
     
    
      This video is part of Arduino Step by Step Course which starts here: https://youtu.be/-6qSrDUA5a8
    
     
    
    If you found this tutorial helpful, please support me so I can continue creating 
    content like this. You can support me on Patreon http://robojax.com/L/?id=63
    
    or make donation using PayPal http://robojax.com/L/?id=64
      
     * This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact.* 
     * This code has been download from Robojax.com
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
    
        You should have received a copy of the GNU General Public License
        along with this program.  If not, see <https://www.gnu.org/licenses/>. 
    
    */
    
    #include <Adafruit_VL6180X.h>
    
    // address we will assign if dual sensor is present
    #define LOX1_ADDRESS 0x30
    #define LOX2_ADDRESS 0x31
    
    
    
    // set the pins to shutdown
    #define SHT_LOX1 7
    #define SHT_LOX2 6
    
    
    // Optional define GPIO pins to check to see if complete
    #define GPIO_LOX1 4
    #define GPIO_LOX2 3
    
    
    #define TIMING_PIN 13
    
    // objects for the VL6180X
    Adafruit_VL6180X lox1 = Adafruit_VL6180X();
    Adafruit_VL6180X lox2 = Adafruit_VL6180X();
    
    
    // Setup mode for doing reads
    typedef enum {RUN_MODE_DEFAULT, RUN_MODE_TIMED, RUN_MODE_ASYNC, RUN_MODE_GPIO, RUN_MODE_CONT} runmode_t;
    
    runmode_t run_mode = RUN_MODE_DEFAULT;
    uint8_t show_command_list = 1;
    
    //==========================================================================
    // Define some globals used in the continuous range mode
    // Note: going to start table drive this part, may back up and do the rest later
    Adafruit_VL6180X *sensors[] = {&lox1, &lox2};
    const uint8_t COUNT_SENSORS = sizeof(sensors) / sizeof(sensors[0]);
    const int sensor_gpios[COUNT_SENSORS] = {GPIO_LOX1, GPIO_LOX2}; // if any are < 0 will poll instead
    uint8_t  tempRange;
    uint8_t         sensor_ranges[COUNT_SENSORS];
    uint8_t         sensor_status[COUNT_SENSORS];
    // Could do with uint8_t for 8 sensors, but just in case...
    const uint16_t  ALL_SENSORS_PENDING = ((1 << COUNT_SENSORS) - 1);
    uint16_t        sensors_pending = ALL_SENSORS_PENDING;
    uint32_t        sensor_last_cycle_time;
    
    
    /*
        Reset all sensors by setting all of their XSHUT pins low for delay(10), then set all XSHUT high to bring out of reset
        Keep sensor #1 awake by keeping XSHUT pin high
        Put all other sensors into shutdown by pulling XSHUT pins low
        Initialize sensor #1 with lox.begin(new_i2c_address) Pick any number but 0x29 and it must be under 0x7F. Going with 0x30 to 0x3F is probably OK.
        Keep sensor #1 awake, and now bring sensor #2 out of reset by setting its XSHUT pin high.
        Initialize sensor #2 with lox.begin(new_i2c_address) Pick any number but 0x29 and whatever you set the first sensor to
    */
    void setID() {
      // all reset
      digitalWrite(SHT_LOX1, LOW);
      digitalWrite(SHT_LOX2, LOW);
    
      delay(10);
    
      // all unreset
      digitalWrite(SHT_LOX1, HIGH);
      digitalWrite(SHT_LOX2, HIGH);
    
      delay(10);
    
      // activating LOX1 and reseting LOX2
      digitalWrite(SHT_LOX1, HIGH);
      digitalWrite(SHT_LOX2, LOW);
    
    
      // initing LOX1
      if (!lox1.begin()) {
        Serial.println(F("Failed to boot first VL6180X"));
        while (1);
      }
      lox1.setAddress(LOX1_ADDRESS);
      delay(10);
    
      // activating LOX2
      digitalWrite(SHT_LOX2, HIGH);
      delay(10);
    
      //initing LOX2
      if (!lox2.begin()) {
        Serial.println(F("Failed to boot second VL6180X"));
        while (1);
      }
      lox2.setAddress(LOX2_ADDRESS);
      delay(10);
    
     
    }
    
    void readSensor(Adafruit_VL6180X &vl) {
    
      float lux = vl.readLux(VL6180X_ALS_GAIN_5);
    
      uint8_t range = vl.readRange();
    
      uint8_t status = vl.readRangeStatus();
    
      if (status == VL6180X_ERROR_NONE) {
          tempRange = range;//save it for the moment
      }
    
      // Some error occurred, print it out!
    
      if  ((status >= VL6180X_ERROR_SYSERR_1) && (status <= VL6180X_ERROR_SYSERR_5)) {
        Serial.print("(System error)");
      }
      else if (status == VL6180X_ERROR_ECEFAIL) {
        Serial.print("(ECE failure)");
      }
      else if (status == VL6180X_ERROR_NOCONVERGE) {
        Serial.print("(No convergence)");
      }
      else if (status == VL6180X_ERROR_RANGEIGNORE) {
        Serial.print("(Ignoring range)");
      }
      else if (status == VL6180X_ERROR_SNR) {
        Serial.print("Signal/Noise error");
      }
      else if (status == VL6180X_ERROR_RAWUFLOW) {
        Serial.print("Raw reading underflow");
      }
      else if (status == VL6180X_ERROR_RAWOFLOW) {
        Serial.print("Raw reading overflow");
      }
      else if (status == VL6180X_ERROR_RANGEUFLOW) {
        Serial.print("Range reading underflow");
      }
      else if (status == VL6180X_ERROR_RANGEOFLOW) {
        Serial.print("Range reading overflow");
      }
    }
    
    void read_sensors() {
      readSensor(lox1);
      sensor_ranges[0]=tempRange;//save it now
    
      readSensor(lox2);
      sensor_ranges[1]=tempRange; //save it now 
    
      Serial.println();
    }
    
    
    
    
    
    //===============================================================
    // Setup
    //===============================================================
    void setup() {
      Serial.begin(115200);
    
      // wait until serial port opens for native USB devices
      while (! Serial) {
        delay(1);
      }
    
      pinMode(SHT_LOX1, OUTPUT);
      pinMode(SHT_LOX2, OUTPUT);
    
    
      // Enable timing pin so easy to see when pass starts and ends
      pinMode(TIMING_PIN, OUTPUT);
    
    #ifdef GPIO_LOX1
      // If we defined GPIO pins, enable them as PULL UP
      pinMode(GPIO_LOX1, INPUT_PULLUP);
      pinMode(GPIO_LOX2, INPUT_PULLUP);
    
    #endif
    
      Serial.println("Shutdown pins inited...");
    
      digitalWrite(SHT_LOX1, LOW);
      digitalWrite(SHT_LOX2, LOW);
    
      digitalWrite(TIMING_PIN, LOW);
      Serial.println("All in reset mode...(pins are low)");
    
    
      Serial.println("Starting...");
      setID();
    
    }
    
    //===============================================================
    // Loop
    //===============================================================
    void loop() {
     read_sensors();
          for(int i=0; i<COUNT_SENSORS; i++)
          {
            Serial.print("Sensor ");
            Serial.print(i);
            Serial.print(" :");        
            Serial.print(sensor_ranges[i]);
            Serial.print("mm");
            Serial.println();
          } 
    //      if(sensor_ranges[1] >=76)
    //      {
    //        //do something here
    //      }
      delay(100);
    }