Whenever I read from my VCNL4200 over I2C, the 16bit word I get back is always 0x0000. This is completely independent of the register I'm reading, and still happens when reading the device ID register which has a fixed non-zero value. This has happened on both sensor chips I've tried.

As best I can tell the device reads I2C commands correctly, as I've probed it and verified that the device is doing what my setup function tells it to do. It's also behaving correctly with ACK/NACK bits (pulling low for ACK during write, letting SDA float for the micro to ACK during read).

The scope traces for SDA and SCL when I try to read the device ID register are below.

Scope trace of SDA and SCL during the read operation

Code I use to read/setup the sensor:

//count is number of bits, stop is whether or not there is a stop condition at the end
int i2cWrite(int8 address, int8 *data, int8 count, int1 stop);
int i2cRead(int8 address, int8 *data, int8 count);

int16 VCNL4200_Read(void) {
    int8 data[2] = {0};
    int8 psDataRegister[1] = {0x0E}; //0x08 is the address of the data, 0x0E for device ID
    i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 1);
    i2cRead(VCNL4200_I2C_ADDRESS, data, 2);
    return make16(data[1], data[0]);

void VCNL4200_Setup(void) {
    int8 configWords[5][2]  = {
        {0xF0, 0x00},   //PS_CONF1 , PS_CONF2
        {0x00, 0x20},   //PS_CONF3 , PS_MS
        {0x00, 0x00},   //PS_CANC_L, PS_CANC_H
        {0x00, 0x00},   //PS_THDL_L, PS_THDL_H
        {0x01, 0x00}    //PS_THDH_L, PS_THDH_H
    int8 configWordCurrent[3];

    for(int8 i = 0; i < 5; i++){
        configWordCurrent[0] = i+3;                             //1st byte, register address. Sequential from 0x03 to 0x07
        configWordCurrent[1] = configWords[i][0];               //2nd byte, lower byte of config word
        configWordCurrent[2] = configWords[i][1];               //3rd byte, upper byte of config word
        i2cWrite(VCNL4200_I2C_ADDRESS, configWordCurrent, 3, 1);//Send over I2C

The i2cWrite and i2cRead functions have been verified as working on other devices. I'm using a PIC16F1776 with CCS C compiler.

  • \$\begingroup\$ Where do you do your I2C setup? As in the clock speed? Is it possible you are using a clock speed too fast for that chip? \$\endgroup\$ – Ron Beyer Jan 16 '18 at 22:48
  • \$\begingroup\$ My clock speed is 100kHz, its setup using #use i2c(master, sda=PIN_B5, scl=PIN_B4, force_hw, fast=100000) (see the CCS manual for details). The VCNL4200 can run at 100kHz \$\endgroup\$ – Escape Jan 16 '18 at 22:53

It looks like the VCNL4200 expects a repeat-start between the two I2C commands, and you've got two separate commands with a stop between.

It's not very obvious from the data sheet, but this arduino driver doesn't send the stop message on WireEndTransmisson.

I suspect is the equivalent of i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 1); becoming i2cWrite(VCNL4200_I2C_ADDRESS, psDataRegister, 1, 0); in your code.

|improve this answer|||||
  • \$\begingroup\$ Thanks you! This was the problem, I've hanged this and its now working perfectly \$\endgroup\$ – Escape Jan 17 '18 at 0:08


On the digital interface you can see, when you are Reading data, that u cant send a stop message between commands. I made the same mistake, just like you, because others i2c devices send the stop message

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.