This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Issues reading virtual registers via I2C

Hello,

I have an AMS AS7261 light sensor that I'm using with my NRF51422 DK to take a light reading, pull it using nrf_drv_twi_tx/rx, and send it over BLE. However, when I try to read from the virtual registers of interest, nearly each of the registers return 0. Below is my function:

void read_sensor(uint16_t values[], const uint8_t registers[]) {

  uint8_t reg_addr = registers[0]; //first virtual register to read
  uint8_t end_reg = registers[1];
  uint8_t buf;
  ret_code_t status;
  uint16_t value;
  int counter = 0;

  while (reg_addr < end_reg) {
    value = 0;

    //Read higher byte
    buf = 0;
    while(true){
      status = nrf_drv_twi_tx(&m_twi, AS72XX_ADDR, &reg_addr, sizeof(reg_addr), true);
      if (status == NRF_SUCCESS)
        break;
    }

    while(true) {
      status = nrf_drv_twi_rx(&m_twi, AS72XX_ADDR, &buf, sizeof(buf));
      if (status == NRF_SUCCESS)
        break;
    }
    printf("Value at register %#x: %#x\r\n", reg_addr, buf);
    value = (buf<<8); //record higher byte
    reg_addr++;

    //Read lower byte
    buf = 0;
    while(true){
      status = nrf_drv_twi_tx(&m_twi, AS72XX_ADDR, &reg_addr, sizeof(reg_addr), true);
      if (status == NRF_SUCCESS)
        break;
    }

    while(true) {
      status = nrf_drv_twi_rx(&m_twi, AS72XX_ADDR, &buf, sizeof(buf));
      if (status == NRF_SUCCESS)
        break;
    }
    printf("Value at register %#x: %#x\r\n", reg_addr, buf);
    value += buf; //record lower byte
    reg_addr++;

    values[counter] = value; //store raw value in array
    counter++;
  }
}

I want to read each of the raw data registers, which according to the datasheet are registers 0x08 to 0x13:

The only registers that return a value other than 0 are the last 4, but the values I get are also wrong (in that they do not match up with the values shown in the provided GUI to read these values).

At this point I suspect this may be more of an issue with the sensor or how I'm reading it, but if it is an issue with my code any help is appreciated!

Thank you.

Parents
  • Hi Bennett

    Could there be some init/configuration sequence that you have to run before accessing these registers?

    Are there any registers in the sensor that hold a fixed value, that you could use to debug the communication?
    Many sensors have some kind of device ID register that will never change. 

    Have you tried to scope the lines to see what happens on the bus?

    Assuming the nrf_drv_twi_tx/rx calls are blocking I can't see any issues with the code. Can you let me know which SDK version you are using?

    Best regards
    Torbjørn

Reply
  • Hi Bennett

    Could there be some init/configuration sequence that you have to run before accessing these registers?

    Are there any registers in the sensor that hold a fixed value, that you could use to debug the communication?
    Many sensors have some kind of device ID register that will never change. 

    Have you tried to scope the lines to see what happens on the bus?

    Assuming the nrf_drv_twi_tx/rx calls are blocking I can't see any issues with the code. Can you let me know which SDK version you are using?

    Best regards
    Torbjørn

Children
  • I'm using SDK 12.03.

    I'm now noticing a few oddities when I use the scope. After doing a write (with nrf_drv_twi_tx), it mostly looks fine but SCL does not return to high at the end of the call. When I call the subsequent read, it looks like there's a NACK, but nrf_drv_twi_rx returns NRF_SUCCESS. I'll attach the scope captures below:

    Write:

    Read:

    I'm kind of new to this stuff so I'm not sure where the issue may lie, I'm thinking it's in the sensor, I've tried contacting the manufacturer. I also noticed that on the read, there isn't the "break" in the clock line between the end of the address and the start of the data like there is in the write screenshot, not sure if that's an issue or not.

    Thank you for your help,

    Bennett

  • Hi Bennett

    Thanks for the traces. 

    To me they look pretty normal. I tried running some comparable code on a nRF52DK which reads an LM75BD temperature sensor and an MMA7660 accelerometer over I2C, and the results are comparable.

    Granted it's running on a nRF52 device and not a nRF51, but the driver is the same, and I also see the 'missing' gap in the RX calls which is not there when sending data.

     I also think it's normal for the sensor to send a NACK after the last byte of information has been sent, to signal that no more data is coming. I see similar behavior from the LM75BD and MMA7660 devices. 

    Do you have a data sheet for the sensor that I could have a look at?

    Best regards
    Torbjørn

  •  I also think it's normal for the sensor to send a NACK after the last byte of information has been sent

    Yes - it is.

  • Hi Torbjørn,

    Thank you for your detailed respone. The data sheet is available here.

    Thanks,

    Bennett

  • Hi Bennett

    Thanks for sharing the data sheet. 

    Reading through the sample code for reading and writing the virtual registers this seems considerably more complicated than similar sensors I have worked with, and I am not sure the code you sent me is equivalent to the code they provided. 

    For one thing their virtual register read example starts with a read loop, to wait for the read buffer to be ready, while your code starts with a write. 

    Secondly, it is important to note that the nrf_drv_twi_rx function returns any error code returned by the TWI driver, it doesn't return the data read. The data read is stored in the buffer that you pass into the function. 

    In other words you have to implement the while(1) loops in the virtual register write/read procedures a bit different from what they do in the data sheet in order to properly check the status data returned from the sensor. 

    Best regards
    Torbjørn 

Related