Silica Sensor Node board sends custom ble advertising for the Gateway board

Dependencies:   X_NUCLEO_IKS01A2_SPI3W

Fork of sensor-node-ble by Roberto Spelta

Getting started with mbed SensorNode BLE

Information

History project:

  • 26/01/2017 - First Release

This project uses the Bluetooth Low Energy in order to send advertaisments every second. These payloads are read by the Visible Things Gateway board, more about it here . Every advertaisments contains sensors data read form the SensorTile and the Silica Sensor Board. For details please read the document in the MAN folder,

The application:

  • reads sensors data (accelerometer, gyroscope, lux, pressure, temperature, proximity, magnetometer)
  • send these data by BLE

You can compile this project in three ways:

1. Using the Online compiler.

Information

Learn how to use the Online compiler reading https://docs.mbed.com/docs/mbed-os-handbook/en/latest/dev_tools/online_comp/ page.

2. Using the compiler on your PC

Information

Learn how to use the mbed-cli reading https://docs.mbed.com/docs/mbed-os-handbook/en/latest/dev_tools/cli/ page.
The name of the machine is SILICA_SENSOR_NODE.

3. Exporting to 3rd party tools (IDE)

Information

Learn how to use the mbed-cli reading https://docs.mbed.com/docs/mbed-os-handbook/en/latest/dev_tools/third_party/ page. We have exported the project for you, please read here

Warning

This example requires a Visible Things Gateway board. If you don't have this board you can use RF Connect app from an Android phone just to see the raw data sent from the SensorNode.

VL6180x/VL6180x.cpp

Committer:
rspelta
Date:
2018-01-26
Revision:
5:26b07c500aa2
Parent:
3:94aee6f716b7

File content as of revision 5:26b07c500aa2:

/******************************************************************************
 * SFE_VL6180x.cpp
 * Library for VL6180x time of flight range finder.
 * Casey Kuhns @ SparkFun Electronics
 * 10/29/2014
 * https://github.com/sparkfun/
 * 
 * The VL6180x by ST micro is a time of flight range finder that
 * uses pulsed IR light to determine distances from object at close
 * range.  The average range of a sensor is between 0-200mm
 * 
 * In this file are the functions in the VL6180x class
 * 
 * Resources:
 * This library uses the Arduino Wire.h to complete I2C transactions.
 * 
 * Development environment specifics:
 *  IDE: Arduino 1.0.5
 *  Hardware Platform: Arduino Pro 3.3V/8MHz
 *  VL6180x Breakout Version: 1.0
 * 
 * 
 * This code is beerware. If you see me (or any other SparkFun employee) at the
 * local pub, and you've found our code helpful, please buy us a round!
 * 
 * Distributed as-is; no warranty is given.
 ******************************************************************************/


#include "VL6180x.h"

//VL6180x::VL6180x(PinName sda, PinName scl, uint8_t addr) : m_i2c(sda, scl), m_addr(addr) {}

VL6180x::VL6180x(I2C *i2c, uint8_t addr) : m_i2c(i2c), m_addr(addr)
{
  m_i2c->frequency(400000);
  PE1801_setRegister( GPIO_SET_DIR_LOW, 0x40 ); // only IO6 setted as output
  PE1801_setRegister( GPIO_SET_DIR_MID, 0 );  
  PE1801_setRegister( GPIO_SET_DIR_HIGH, 0 );
  PE1801_setRegister( GPIO_SET_LOW, 0x40 ); // set 1 DEV_RESN
}

int VL6180x::VL6180xInit(void){
  uint8_t data; //for temp data storage
  
  data = VL6180x_getRegister(VL6180X_SYSTEM_FRESH_OUT_OF_RESET);
  wait_ms(50);
  if(data != 1) {
	  printf("error\n\r");
	  return VL6180x_FAILURE_RESET;
  }

  //Required by datasheet
  //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
  VL6180x_setRegister(0x0207, 0x01);
  VL6180x_setRegister(0x0208, 0x01);
  VL6180x_setRegister(0x0096, 0x00);
  VL6180x_setRegister(0x0097, 0xfd);
  VL6180x_setRegister(0x00e3, 0x00);
  VL6180x_setRegister(0x00e4, 0x04);
  VL6180x_setRegister(0x00e5, 0x02);
  VL6180x_setRegister(0x00e6, 0x01);
  VL6180x_setRegister(0x00e7, 0x03);
  VL6180x_setRegister(0x00f5, 0x02);
  VL6180x_setRegister(0x00d9, 0x05);
  VL6180x_setRegister(0x00db, 0xce);
  VL6180x_setRegister(0x00dc, 0x03);
  VL6180x_setRegister(0x00dd, 0xf8);
  VL6180x_setRegister(0x009f, 0x00);
  VL6180x_setRegister(0x00a3, 0x3c);
  VL6180x_setRegister(0x00b7, 0x00);
  VL6180x_setRegister(0x00bb, 0x3c);
  VL6180x_setRegister(0x00b2, 0x09);
  VL6180x_setRegister(0x00ca, 0x09);  
  VL6180x_setRegister(0x0198, 0x01);
  VL6180x_setRegister(0x01b0, 0x17);
  VL6180x_setRegister(0x01ad, 0x00);
  VL6180x_setRegister(0x00ff, 0x05);
  VL6180x_setRegister(0x0100, 0x05);
  VL6180x_setRegister(0x0199, 0x05);
  VL6180x_setRegister(0x01a6, 0x1b);
  VL6180x_setRegister(0x01ac, 0x3e);
  VL6180x_setRegister(0x01a7, 0x1f);
  VL6180x_setRegister(0x0030, 0x00);

  return 0;
}
VL6180x::~VL6180x(void) {
};

void VL6180x::VL6180xDefautSettings(void){
  //Recommended settings from datasheet
  //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf

  //Enable Interrupts on Conversion Complete (any source)
  VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CONFIG_GPIO, (4 << 3)|(4) ); // Set GPIO1 high when sample complete


  VL6180x_setRegister(VL6180X_SYSTEM_MODE_GPIO1, 0x10); // Set GPIO1 high when sample complete
  VL6180x_setRegister(VL6180X_READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); //Set Avg sample period
  VL6180x_setRegister(VL6180X_SYSALS_ANALOGUE_GAIN, 0x46); // Set the ALS gain
  VL6180x_setRegister(VL6180X_SYSRANGE_VHV_REPEAT_RATE, 0xFF); // Set auto calibration period (Max = 255)/(OFF = 0)
  VL6180x_setRegister(VL6180X_SYSALS_INTEGRATION_PERIOD, 0x63); // Set ALS integration time to 100ms
  VL6180x_setRegister(VL6180X_SYSRANGE_VHV_RECALIBRATE, 0x01); // perform a single temperature calibration
  //Optional settings from datasheet
  //http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00122600.pdf
  VL6180x_setRegister(VL6180X_SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); // Set default ranging inter-measurement period to 100ms
  VL6180x_setRegister(VL6180X_SYSALS_INTERMEASUREMENT_PERIOD, 0x0A); // Set default ALS inter-measurement period to 100ms
  VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); // Configures interrupt on ‘New Sample Ready threshold event’ 
  //Additional settings defaults from community
  VL6180x_setRegister(VL6180X_SYSRANGE_MAX_CONVERGENCE_TIME, 0x32);
  VL6180x_setRegister(VL6180X_SYSRANGE_RANGE_CHECK_ENABLES, 0x10 | 0x01);
  VL6180x_setRegister16bit(VL6180X_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, 0x7B );
  VL6180x_setRegister16bit(VL6180X_SYSALS_INTEGRATION_PERIOD, 0x64);

  VL6180x_setRegister(VL6180X_READOUT_AVERAGING_SAMPLE_PERIOD,0x30);
  VL6180x_setRegister(VL6180X_SYSALS_ANALOGUE_GAIN,0x40);
  VL6180x_setRegister(VL6180X_FIRMWARE_RESULT_SCALER,0x01);
}
void VL6180x::getIdentification(struct VL6180xIdentification *temp){
	  
  temp->idModel =  VL6180x_getRegister(VL6180X_IDENTIFICATION_MODEL_ID);
  temp->idModelRevMajor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODEL_REV_MAJOR);
  temp->idModelRevMinor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODEL_REV_MINOR);
  temp->idModuleRevMajor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODULE_REV_MAJOR);
  temp->idModuleRevMinor = VL6180x_getRegister(VL6180X_IDENTIFICATION_MODULE_REV_MINOR);

  temp->idDate = VL6180x_getRegister16bit(VL6180X_IDENTIFICATION_DATE);
  temp->idTime = VL6180x_getRegister16bit(VL6180X_IDENTIFICATION_TIME);
}


uint8_t VL6180x::changeAddress(uint8_t old_address, uint8_t new_address){
  
  //NOTICE:  IT APPEARS THAT CHANGING THE ADDRESS IS NOT STORED IN NON-VOLATILE MEMORY
  // POWER CYCLING THE DEVICE REVERTS ADDRESS BACK TO 0X29
 
  if( old_address == new_address) return old_address;
  if( new_address > 127) return old_address;
   
   VL6180x_setRegister(VL6180X_I2C_SLAVE_DEVICE_ADDRESS, new_address);
   
   return VL6180x_getRegister(VL6180X_I2C_SLAVE_DEVICE_ADDRESS); 
}
  


uint8_t VL6180x::getDistance() {
  uint8_t distance;
  VL6180x_setRegister(VL6180X_SYSRANGE_START, 0x01); //Start Single shot mode
  wait_ms(10);
  distance = VL6180x_getRegister(VL6180X_RESULT_RANGE_VAL);
  VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CLEAR, 0x07);
  return distance;
}

float VL6180x::getAmbientLight(vl6180x_als_gain VL6180X_ALS_GAIN)
{
  //First load in Gain we are using, do it everytime incase someone changes it on us.
  //Note: Upper nibble shoudl be set to 0x4 i.e. for ALS gain of 1.0 write 0x46
  VL6180x_setRegister(VL6180X_SYSALS_ANALOGUE_GAIN, (0x40 | VL6180X_ALS_GAIN)); // Set the ALS gain

  //Start ALS Measurement 
  VL6180x_setRegister(VL6180X_SYSALS_START, 0x01);

    wait_ms(100); //give it time... 

  VL6180x_setRegister(VL6180X_SYSTEM_INTERRUPT_CLEAR, 0x07);

  //Retrieve the Raw ALS value from the sensoe
  unsigned int alsRaw = VL6180x_getRegister16bit(VL6180X_RESULT_ALS_VAL);
  
  //Get Integration Period for calculation, we do this everytime incase someone changes it on us.
  unsigned int alsIntegrationPeriodRaw = VL6180x_getRegister16bit(VL6180X_SYSALS_INTEGRATION_PERIOD);
  
  float alsIntegrationPeriod = 100.0 / alsIntegrationPeriodRaw ;

  //Calculate actual LUX from Appnotes

  float alsGain = 0.0;
  
  switch (VL6180X_ALS_GAIN){
    case GAIN_20: alsGain = 20.0; break;
    case GAIN_10: alsGain = 10.32; break;
    case GAIN_5: alsGain = 5.21; break;
    case GAIN_2_5: alsGain = 2.60; break;
    case GAIN_1_67: alsGain = 1.72; break;
    case GAIN_1_25: alsGain = 1.28; break;
    case GAIN_1: alsGain = 1.01; break;
    case GAIN_40: alsGain = 40.0; break;
  }

//Calculate LUX from formula in AppNotes
  
  float alsCalculated = (float)0.32 * ((float)alsRaw / alsGain) * alsIntegrationPeriod;

  return alsCalculated;
}

// --- Private Functions --- //

uint8_t VL6180x::VL6180x_getRegister(uint16_t registerAddr)
{

  uint8_t data;
  char data_write[2];
  char data_read[1];
  data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
  data_write[1] = registerAddr & 0xFF; //LSB of register address 
  m_i2c->write(m_addr, data_write, 2,0); 
  m_i2c->read(m_addr,data_read,1,1);
  //Read Data from selected register
  data=data_read[0];
  return data;
  
  /*
  #if 1
  char reg[] = { 0, 0 };
  char ret[] = { 0, 0 };
  m_i2c->write(m_addr, &reg[0], 2);
  m_i2c->read(m_addr, ret, 1 );
  printf("%02x, %02x, %02x\n\r", ret[0], ret[1], m_addr );
  #else
  char reg[] = { 0x0FU, 0 };
  char ret[] = { 0, 0 };
  m_i2c->frequency(400000);
  m_i2c->write(0xBE, &reg[0], 1, 1);
  m_i2c->read(0xBE, ret, 1 );
  printf("%02x, %02x, %02x\n\r", ret[0], ret[1], m_addr );
  #endif
  return ret[0];*/
}

uint16_t VL6180x::VL6180x_getRegister16bit(uint16_t registerAddr)
{
  uint8_t data_low;
  uint8_t data_high;
  uint16_t data;

  char data_write[2];
  char data_read[2];
  data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
  data_write[1] = registerAddr & 0xFF; //LSB of register address 
  m_i2c->write(m_addr, data_write, 2,0); 
  m_i2c->read(m_addr,data_read,2,1);
  data_high = data_read[0]; //Read Data from selected register
  data_low = data_read[1]; //Read Data from selected register
  data = (data_high << 8)|data_low;

  return data;
}

void VL6180x::PE1801_setRegister(uint8_t registerAddr, uint8_t data)
{
    char w2_data[2];
    
    w2_data[0] = registerAddr;
    w2_data[1] = data;
    m_i2c->write( PE180_ADDRESS, w2_data, 2 );  
}

void VL6180x::VL6180x_setRegister(uint16_t registerAddr, uint8_t data)
{
    char data_write[3];
    data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
    data_write[1] = registerAddr & 0xFF; //LSB of register address 
    data_write[2] = data & 0xFF; 
    m_i2c->write(m_addr, data_write, 3); 
}

void VL6180x::VL6180x_setRegister16bit(uint16_t registerAddr, uint16_t data)
{
    char data_write[4];
    data_write[0] = (registerAddr >> 8) & 0xFF; //MSB of register address 
    data_write[1] = registerAddr & 0xFF; //LSB of register address 
    data_write[2] = (data >> 8) & 0xFF;
    data_write[3] = data & 0xFF; 
    m_i2c->write(m_addr, data_write, 4); 
}