This library uses the power enable pin on the lidar lite unit to enable multi-unit sampling. Attempted to add an additional change address function but didn't quite complete it. Thus, functionality of multiple units at the same time is achieved by the power enable pin and not by addressing the units separately.

Dependencies:   mbed

Fork of LidarLite by Akash Vibhute

LidarLite.cpp

Committer:
jakelarsen17
Date:
2016-01-26
Revision:
1:a01dc8b52be4
Parent:
0:8e6304ab38d2
Child:
2:917b2a1835b0

File content as of revision 1:a01dc8b52be4:

//Never code working properly for changing addresses of Lidar units 
//Refresh range and velocity functions work well

#include "LidarLite.h"
#include "mbed.h"
#include "PeripheralPins.h"
#include "PeripheralNames.h"

LidarLite::LidarLite(PinName sda, PinName scl):
    i2c_(sda, scl),debug(USBTX,USBRX)
    {
    i2c_.frequency(100000); //I2C @ 100kHz
    wait(0.5);
    //configure(int = 0, char = 0x62);
}

/* =============================================================================
  Configure
  Sets the configuration for the sensor, typically this is done in the begin()
  command, but sometimes (especially for multi-sensor applications) you will
  need to do this separately.
  Parameters
  ------------------------------------------------------------------------------
  - configuration: set the configuration for the sensor
    - default or 0 = equivelent to writing 0x00 to 0x00, i.e. full reset of
      sensor, if you write nothing for configuration or 0, the sensor will init-
      iate normally
    - 1 = high speed setting, set the aquisition count to 1/3 the default (works
      great for stronger singles) can be a little noisier
============================================================================= */
void LidarLite::configure(int configuration, char LidarLiteI2cAddress){
  uint8_t nackack = 1;
  switch (configuration){
    case 0: //  Default configuration
        nackack=i2c_.write(LidarLiteI2cAddress);        //device address with write condition
        if(nackack != 1)break;                       //No Ack, return False
        nackack=i2c_.write(0x00);                       //device ram address where obj value is present
        if(nackack != 1)break;                       //No Ack, return False
        //ack=i2c_.write(LidarLiteI2cAddress|0x00);   //device address with write condition (read is 0x01)
        //if(!ack)return false;                       //No Ack, return False
        i2c_.write(0x00);                              
    break;
    /*
    case 1: //  Set aquisition count to 1/3 default value, faster reads, slightly
            //  noisier values
      write(0x04,0x00,LidarLiteI2cAddress);
    break;
    case 2: //  Low noise, low sensitivity: Pulls decision criteria higher
            //  above the noise, allows fewer false detections, reduces
            //  sensitivity
      write(0x1c,0x20,LidarLiteI2cAddress);
    break;
    case 3: //  High noise, high sensitivity: Pulls decision criteria into the
            //  noise, allows more false detections, increses sensitivity
      write(0x1c,0x60,LidarLiteI2cAddress);
    break;
    */
  }
}



/* =============================================================================
  Change I2C Address for Single Sensor
  LIDAR-Lite now has the ability to change the I2C address of the sensor and
  continue to use the default address or disable it. This function only works
  for single sensors. When the sensor powers off and restarts this value will
  be lost and will need to be configured again.
  There are only certain address that will work with LIDAR-Lite so be sure to
  review the "Notes" section below
  Process
  ------------------------------------------------------------------------------
  1.  Read the two byte serial number from register 0x96
  2.  Write the low byte of the serial number to 0x18
  3.  Write the high byte of the serial number to 0x19
  4.  Write the new address you want to use to 0x1a
  5.  Choose whether to use the default address or not (you must do one of the
      following to commit the new address):
      1.  If you want to keep the default address, write 0x00 to register 0x1e
      2.  If you do not want to keep the default address write 0x08 to 0x1e
  Parameters
  ------------------------------------------------------------------------------
  - newI2cAddress: the hex value of the I2C address you want the sensor to have
  - disablePrimaryAddress (optional): true/false value to disable the primary
    address, default is false (i.e. leave primary active)
  - currentLidarLiteAddress (optional): the default is 0x62, but can also be any
    value you have previously set (ex. if you set the address to 0x66 and dis-
    abled the default address then needed to change it, you would use 0x66 here)
  Example Usage
  ------------------------------------------------------------------------------
  1.  //  Set the value to 0x66 with primary address active and starting with
      //  0x62 as the current address
      myLidarLiteInstance.changeAddress(0x66);
  Notes
  ------------------------------------------------------------------------------
    Possible Address for LIDAR-Lite
    7-bit address in binary form need to end in "0". Example: 0x62 = 01100010 so
    that works well for us. Essentially any even numbered hex value will work
    for 7-bit address.
    8-bit read address in binary form need to end in "00". Example: the default
    8-bit read address for LIDAR-Lite is 0xc4 = 011000100. Essentially any hex
    value evenly divisable by "4" will work.
  =========================================================================== */
void LidarLite::changeAddress(char newI2cAddress,  bool disablePrimaryAddress, char currentLidarLiteAddress){
  //  Array to save the serial number
  char serialNumber[2];
  char serialAdr[1] = {0x96};
  //char newI2cAddressArray[1];
  uint8_t nackack = 1;

  //  Read two bytes from 0x96 to get the serial number
  //read(0x96,2,serialNumber,false,currentLidarLiteAddress);
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write((currentLidarLiteAddress<<1), serialAdr, 1);
    }
    nackack = 1; 
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.read((currentLidarLiteAddress<<1)|0x01, serialNumber, 2);
    }
    /*               
    nackack=i2c_.write(currentLidarLiteAddress);            //device address with write condition
    if(!ack)return;                               //No Ack, return False
    ack=i2c_.write(0x96);                               //device ram address where Tobj value is present
    if(!ack)return;                               //No Ack, return False
    //ack=i2c_.write(currentLidarLiteAddress|0x01);       //device address with write condition (write is 0x00) 
    //if(!ack)return false;                               //No Ack, return False
    serialNumber[0]=i2c_.read(1);     //Tobj low byte
    serialNumber[1]=i2c_.read(1);     //Tobj high byte
    */
  
  //  Write the low byte of the serial number to 0x18
  //write(0x18,serialNumber[0],currentLidarLiteAddress);
    char lowbyte[2] = {0x18, serialNumber[0]};
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write((currentLidarLiteAddress<<1), lowbyte, 2);
    } 
    /*
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write(currentLidarLiteAddress, write, 2);
    }                    
    ack=i2c_.write(currentLidarLiteAddress);            //device address with write condition
    if(!ack)return;                               //No Ack, return False
    ack=i2c_.write(0x18);                               //device ram address where Tobj value is present
    if(!ack)return;                               //No Ack, return False
    //ack=i2c_.write(currentLidarLiteAddress|0x00);       //device address with write condition (read is 0x01) 
    //if(!ack)return false;                               //No Ack, return False
    i2c_.write(serialNumber[0]);     //Tobj low byte
    */
    
  //  Write the high byte of the serial number of 0x19
  //write(0x19,serialNumber[1],currentLidarLiteAddress); 
    char highbyte[2] = {0x19, serialNumber[1]};
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write((currentLidarLiteAddress<<1), highbyte, 2);
    }
    /*             
    ack=i2c_.write(currentLidarLiteAddress);            //device address with write condition
    if(!ack)return;                               //No Ack, return False
    ack=i2c_.write(0x19);                               //device ram address where Tobj value is present
    if(!ack)return;                               //No Ack, return False
    //ack=i2c_.write(currentLidarLiteAddress|0x00);       //device address with write condition (read is 0x01) 
    //if(!ack)return false;                               //No Ack, return False
    i2c_.write(serialNumber[1]);     //Tobj high byte
    */
  
  //  Write the new address to 0x1a
  //write(0x1a,newI2cAddress,currentLidarLiteAddress); 
    char newaddress[2] = {0x1a, newI2cAddress};
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write((currentLidarLiteAddress<<1), newaddress, 2);
    }
    /*              
    ack=i2c_.write(currentLidarLiteAddress);            //device address with write condition
    if(!ack)return;                               //No Ack, return False
    ack=i2c_.write(0x1a);                               //device ram address where Tobj value is present
    if(!ack)return;                               //No Ack, return False
    //ack=i2c_.write(currentLidarLiteAddress|0x00);       //device address with write condition (read is 0x01) 
    //if(!ack)return false;                               //No Ack, return False
    i2c_.write(newI2cAddress);       //Tobj high byte
    */

  //while(newI2cAddress != newI2cAddressArray[0]){
  //  read(0x1a,1,newI2cAddressArray,false,currentLidarLiteAddress);
  //}
  
  printf("WIN!");
  //  Choose whether or not to use the default address of 0x62
  if(disablePrimaryAddress){
    //write(0x1e,0x08,currentLidarLiteAddress); 
    char disable[2] = {0x1e, 0x08};
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write((currentLidarLiteAddress<<1), disable, 2);
    }
    /*                
    ack=i2c_.write(currentLidarLiteAddress);            //device address with write condition
    if(!ack)return;                               //No Ack, return False
    ack=i2c_.write(0x1e);                               //device ram address where Tobj value is present
    if(!ack)return;                               //No Ack, return False
    //ack=i2c_.write(currentLidarLiteAddress|0x00);       //device address with write condition (read is 0x01) 
    //if(!ack)return false;                               //No Ack, return False
    i2c_.write(0x08);       //Tobj high byte
    */
  }else{
    //write(0x1e,0x00,currentLidarLiteAddress);
    char enable[2] = {0x1e, 0x00};
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write((currentLidarLiteAddress<<1), enable, 2);
    } 
    /*                  
    ack=i2c_.write(currentLidarLiteAddress);            //device address with write condition
    if(!ack)return;                               //No Ack, return False
    ack=i2c_.write(0x1e);                               //device ram address where Tobj value is present
    if(!ack)return;                               //No Ack, return False
    //ack=i2c_.write(currentLidarLiteAddress|0x00);       //device address with write condition (read is 0x01) 
    //if(!ack)return false;                               //No Ack, return False
    i2c_.write(0x00);       //Tobj high byte
    */
  }
  return;
}


   
/* =============================================================================
  Change I2C Address for Multiple Sensors
  Using the new I2C address change feature, you can also change the address for
  multiple sensors using the PWR_EN line connected to Arduino's digital pins.
  Address changes will be lost on power off.
  Process
  ------------------------------------------------------------------------------
  1.
  Parameters
  ------------------------------------------------------------------------------
  - numberOfSensors: int representing the number of sensors you have connected
  - pinArray: array of the digital pins your sensors' PWR_EN line is connected
    to
  - i2cAddressArray: array of the I2C address you want to assign to your sen-
    sors, the order should reflect the order of the pinArray (see not for poss-
    ible addresses below)
  - usePartyLine(optional): true/false value of weather or not to leave 0x62
    available to all sensors for write (default is false)
  Example Usage
  ------------------------------------------------------------------------------
  1.  //  Assign new address to the sensors connected to sensorsPins and disable
      //  0x62 as a partyline to talk to all of the sensors
      int sensorPins[] = {2,3,4};
      unsigned char addresses[] = {0x66,0x68,0x64};
      myLidarLiteInstance.changeAddressMultisensor(3,sensorPins,addresses);
  Notes
  ------------------------------------------------------------------------------
    Possible Address for LIDAR-Lite
    7-bit address in binary form need to end in "0". Example: 0x62 = 01100010 so
    that works well for us. Essentially any even numbered hex value will work
    for 7-bit address.
    8-bit read address in binary form need to end in "00". Example: the default
    8-bit read address for LIDAR-Lite is 0xc4 = 011000100. Essentially any hex
    value evenly divisable by "4" will work.
  =========================================================================== */
void LidarLite::changeAddressMultiPwrEn(int numOfSensors, DigitalOut *pinArray, char *i2cAddressArray, char currentAddress){
    for (int i = 0; i < numOfSensors; i++){
      //pinMode(pinArray[i], OUTPUT); // Pin to first LIDAR-Lite Power Enable line
      wait(3);
      //pinArray[i] = 0;
      //wait(5);
      pinArray[i] = 1; //digitalWrite(pinArray[i], HIGH);
      wait(3);
      //configure(int = 0, char = 0x62);
      changeAddress(i2cAddressArray[i],true,currentAddress); // We have to turn off the party line to actually get these to load
      pinArray[i] = 0;
      wait(3);
    }
    //return newI2cAddress;
}



//get functions can be used for returning values while refresh functions can be used for updating without return,
//this may come in handy for threading, just remove the return statements in the refresh functions and make them void
int16_t LidarLite::getRange_cm()
{
   return(distance_LL);
}

int16_t LidarLite::getVelocity_cms()
{
    if(velocity_LL < 127)
        return(velocity_LL*10);
    else
        return((velocity_LL-256)*10);
}



//Refresh Range for returning distance
int16_t LidarLite::refreshRange(char LIDARLite_WriteAdr, char LIDARLite_ReadAdr)
{
    uint8_t nackack;
    char write[2]={SET_CommandReg, AcqMode};
    char read_dist[1]={GET_Distance2BReg};
    char dist[2];
    
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write(LIDARLite_WriteAdr, write, 2);
    }
    
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write(LIDARLite_WriteAdr, read_dist, 1);
    }    
    
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.read(LIDARLite_ReadAdr, dist, 2);
    }
    distance_LL = ((uint16_t)dist[0] << 8) + (uint16_t)dist[1];
    
    return(distance_LL);
}



//Refreshes velocity for return velocity
int16_t LidarLite::refreshVelocity(char LIDARLite_WriteAdr, char LIDARLite_ReadAdr)
{
    uint8_t nackack;
    char write[2]={SET_CommandReg, AcqMode};
    char read_vel[1]={GET_VelocityReg};
    char vel[1];
    
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write(LIDARLite_WriteAdr, write, 2);
    }
    
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.write(LIDARLite_WriteAdr, read_vel, 1);
    }    
    
    nackack=1;
    while(nackack !=0)
    {
        wait_ms(1);
        nackack = i2c_.read(LIDARLite_ReadAdr, vel, 1);
    }
    velocity_LL = (uint16_t)vel[0];
    
    if(velocity_LL < 127)
        return(velocity_LL*10);
    else
        return((velocity_LL-256)*10);
}