Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Saudin Dizdarevic
Published © CC BY-ND

VCNL4000 - Integrated Proximity and Ambient Light Sensor

The VCNL4000 is a proximity sensor with an integrated ambient light sensor.

BeginnerProtip4,578
VCNL4000 - Integrated Proximity and Ambient Light Sensor

Things used in this project

Story

Read more

Code

Simple sketch for Arduino

C/C++
#include <Wire.h>
//We need to initialise  the I2C Address of the board,
#define VCNL4000_ADDRESS 0x13 // I2C bus address is set to 0010 011 = //13h –see the datasheet page 9
//Now wee need setup function -> this function loads only once:
void setup(){
  Serial.begin(9600);  // Serial used to print data
  Wire.begin();  // initialize I2C – see arduino reference for wire lib
  initVCNL4000(); //initilize and setup the board -> function
}
//our loop function    
void loop(){    
  unsigned int ambientValue = readAmbient(); //reading ambient light //data -> it takes about 100ms to read this data
  unsigned int proximityValue = readProximity();

  Serial.print(ambientValue);
  Serial.print(" | ");
  Serial.println(proximityValue);

  delay(100);  //Slow down the printing
  //  the readings take about 100ms to execute
}

//Out initVCNL4000() function looks like this:
void initVCNL4000(){
  byte temp = readVCNLByte(0x81); // Register #1 Product ID Revision //Register - >Register address = 81h. This register contains //information about product ID and product revision.
//Register data value of current revision = 11h -> check datasheet.

  if (temp != 0x11){  // Product ID Should be 0x11
    Serial.print("initVCNL4000 failed to initialize");
    Serial.println(temp, HEX);
  }else{
    Serial.println("VNCL4000 Connected...");
  } 

  /*VNCL400 init params
   Feel free to play with any of these values, but check the datasheet first!*/
// Register #4 Ambient Light Parameter Register
//Register address = 84h.
  writeVCNLByte(0x84, 0x0F);  // Configures ambient light measures - //Single conversion mode, 128 averages (2^7=128, 0x0F=1111(binary))
//Bit 3= Auto offset compensation = Enabled 
/* Register #3 LED Current Setting for Proximity Mode
Register address = 83h. This register is to set the LED current value for proximity measurement.
The value is adjustable in steps of 10 mA from 0 mA to 200 mA.
This register also contains information about the used device fuse program ID. */

  writeVCNLByte(0x83, 15);  /*
R/W bits. IR LED current = Value (dec.) x 10 mA. 
Valid Range = 0 to 20d. 
sets IR current in steps of 10mA 0-200mA //--> 15 decimal= 1111(binary)so current is set to 10x150mA= 150mA
*/


/*
Register #9 Proximity Measurement Signal Frequency 
Register address = 89h */

  writeVCNLByte(0x89, 2);  // Proximity IR test signal freq, 0-3 - //781.25 kHz (DEFAULT)

// Register #10 Proximity Modulator Timing Adjustment // Register address = 8Ah.  
  writeVCNLByte(0x8A, 0x81);  // proximity modulator timing – 81 //hex=129, recommended by Vishay 
}

//Now we need to write readProximity() function which looks like:
unsigned int readProximity(){
  // readProximity() returns a 16-bit value from the VCNL4000's //proximity data registers

// Register #0 Command Register
//Register address = 80h
//The register #0 is for starting ambient light or proximity measurements. This register contains 2 flag bits for data ready indication.  
  byte temp = readVCNLByte(0x80);
  writeVCNLByte(0x80, temp | 0x08);  /* command the sensor to perform a proximity measure
The command temp | 0x08 is needed because bits 0-2 are N/A (we dont need them, they can be equal to 0, so we are setting third bit (bit 3) to 1, it is Prox. od bit -> R/W bit. Starts a single on-demand measurement for proximity.
Result is available at the end of conversion for reading in the registers #7 (HB) and #8 (LB).)*/

  while(!(readVCNLByte(0x80)&0x20));  // Wait for the proximity data ready bit to be set
//we are setting fifth bit (bit 5) (0x20 hex=100000 binary) in register 0x80 to 1, it is Proximity data ready bit, Read only bit. Value = 1 when proximity measurement data is available in the result registers. This bit will be reset when one of the corresponding result registers (reg #7, reg #8) is read. */
  unsigned int data = readVCNLByte(0x87) << 8; //Shift data from //register 7 (bits 0:7)
  data |= readVCNLByte(0x88); //read data from register 8

  return data;
}


unsigned int readAmbient(){
  // readAmbient() returns a 16-bit value from the VCNL4000's ambient light data registers
  byte temp = readVCNLByte(0x80);
  writeVCNLByte(0x80, temp | 0x10);  /* command the sensor to perform ambient measure 
-> 0x10 = 10000 binary, set bit 4 from register 0x80 to 1,
als od R/W bit. Starts a single on-demand measurement for ambient light. If averaging is enabled, starts a sequence of readings and stores the averaged result. Result is available at the end of conversion for reading in the registers #5 (HB) and #6 (LB).  */
  
  while(!(readVCNLByte(0x80)&0x40));  // wait for the als data ready bit to be set als data rdy -> bit 6
  unsigned int data = readVCNLByte(0x85) << 8; //The same as proximity measure
  data |= readVCNLByte(0x86);

  return data;
}


void writeVCNLByte(byte address, byte data){
  // writeVCNLByte(address, data) writes a single byte of data to address
  Wire.beginTransmission(VCNL4000_ADDRESS);
  Wire.write(address);
  Wire.write(data);
  Wire.endTransmission();
}

byte readVCNLByte(byte address){
  // readByte(address) reads a single byte of data from address
  Wire.beginTransmission(VCNL4000_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(VCNL4000_ADDRESS, 1);
  while(!Wire.available());
  byte data = Wire.read();

  return data;
}

Credits

Saudin Dizdarevic
8 projects • 24 followers
Contact

Comments

Please log in or sign up to comment.