sparkfun / SparkFun_Qwiic_TMF882X_Arduino_Library

Arduino Library for SparkFun's Qwiic TMF882X breakout boards
https://docs.sparkfun.com/SparkFun_Qwiic_TMF882X_Arduino_Library/
Other
9 stars 3 forks source link

Unable to Set Custom I2C ID #1

Open shivakumar-tekumatla opened 2 years ago

shivakumar-tekumatla commented 2 years ago

I tried setting a new I2C ID using setI2CAddress function. The function returns True , but the communication fails. I tried the following program . I also attached the I2C communication data capturing using Saleae logic analyzer.

/*

  Example-01_Basic.ino

  This demo shows a basic use of a TMF882X device. The device is connected to, 
  and a single reading is taken for each loop iteration. 

  Supported Boards:

   SparkFun Qwiic dToF Imager - TMF8820        https://www.sparkfun.com/products/19036
   SparkFun Qwiic Mini dToF Imager - TMF8820   https://www.sparkfun.com/products/19218
   SparkFun Qwiic Mini dToF Imager - TMF8821   https://www.sparkfun.com/products/19451
   SparkFun Qwiic dToF Imager - TMF8821        https://www.sparkfun.com/products/19037

  Written by Kirk Benell @ SparkFun Electronics, April 2022

  Repository:
     https://github.com/sparkfun/SparkFun_Qwiic_TMF882X_Arduino_Library

  Documentation:
     https://sparkfun.github.io/SparkFun_Qwiic_TMF882X_Arduino_Library/

  SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).
*/

#include "SparkFun_TMF882X_Library.h" //http://librarymanager/All#SparkFun_Qwiic_TMPF882X

SparkFun_TMF882X  myTMF882X;
uint8_t new_address = 0x50;

// Structure to hold the measurement results - this is defined by the TMF882X SDK.

static struct tmf882x_msg_meas_results myResults;

void setup()
{

    delay(1000);
    Serial.begin(115200);
    Serial.println("");

    Serial.println("In setup");
    Serial.println("==============================");

    // Initialize the TMF882X device
    if(!myTMF882X.begin())
    {
        Serial.println("Error - The TMF882X failed to initialize - is the board connected?");
        while(1);
    }else
        Serial.println("TMF882X started.");

    Serial.println("Change the device address");
    delay(2000);
    Serial.println(myTMF882X.setI2CAddress(new_address));
    delay(2000);

    // The device is now ready for operations
}

void loop()
{
    delay(2000);

    // get a Measurement
    if(myTMF882X.startMeasuring(myResults))
    {
        // print out results
        Serial.println("Measurement:");
        Serial.print("     Result Number: "); Serial.print(myResults.result_num);
        Serial.print("  Number of Results: "); Serial.println(myResults.num_results);       

        for (int i = 0; i < myResults.num_results; ++i) 
        {
            Serial.print("       conf: "); Serial.print(myResults.results[i].confidence);
            Serial.print(" distance mm: "); Serial.print(myResults.results[i].distance_mm);
            Serial.print(" channel: "); Serial.print(myResults.results[i].channel);
            Serial.print(" sub_capture: "); Serial.println(myResults.results[i].sub_capture);   

        }
        Serial.print("     photon: "); Serial.print(myResults.photon_count);    
        Serial.print(" ref photon: "); Serial.print(myResults.ref_photon_count);
        Serial.print(" ALS: "); Serial.println(myResults.ambient_light); Serial.println();
    }
}
[Session 0.zip](https://github.com/sparkfun/SparkFun_Qwiic_TMF882X_Arduino_Library/files/9263378/Session.0.zip)
shivakumar-tekumatla commented 2 years ago

I have contacted AMS about this , and it seems to be procedure to change the device ID is different from what is given in the documentation. Update procedure looks like below. This is taken from their email to me, and also tested.

  1. EN = 1, download FW, confirm appid = 0x03
  2. Change 0x31 GPIO_0 & 0x32 GPIO_1 registers to 0x5 (Output high)
  3. Enter config page & change 0x3B I2C_SLAVE_ADDRESS to a value other than the default address 0x41 (I used 0x22)
  4. Write to 0x3E I2C_ADDR_CHANGE with value 0xF
  5. Write config page WRITE_CONFIG_PAGE into CMD_STAT register
  6. After confirming appid = 0x03, execute CMD_STAT 0x21 to change I2C address If someone planning to update this driver, you can follow these steps.
ghost commented 2 years ago

Thanks for the detailed information. I'll take a look at this and get it fixed/tested - probably in the next couple weeks. -Kirk

hartmms commented 2 years ago

@shivakumar-tekumatla, I took a crack at fixing the address change using your suggested code. I'm not able to get it to work. Perhaps you can post the actual code you used? Thanks.

shivakumar-tekumatla commented 2 years ago

@hartmms , I was able to change using below program. I wrote the program in python .

def I2C_Chg_Fun(self,new_addr):
        new_addr = (((new_addr&0x7F) <<1) & 0xFE) # Shifting by one bit 
        self.bus.write_byte_data(self.I2C_ADDR,self.GPIO_0_REG,0x5)
        self.bus.write_byte_data(self.I2C_ADDR,self.GPIO_1_REG,0x5)
        self.bus.write_byte_data(self.I2C_ADDR, self.CMD_STAT_REG, self.LOAD_CONFIG_CMN )  #Step-1 
        self.STAT_OK = 0x20  #assigning a random value first 
        while self.STAT_OK>=0x10:  # Step-2 : Read until a value less than 0x10 is transmitted 
            self.STAT_OK = self.bus.read_byte_data(self.I2C_ADDR, self.CMD_STAT_REG)
            time.sleep(0.1)
        self.bus.write_byte_data(self.I2C_ADDR,self.I2C_SLAVE_ADDR_REG,new_addr)
        time.sleep(0.5)
        self.bus.write_byte_data(self.I2C_ADDR,self.I2C_ADDR_CHG_REG,0xF)
        time.sleep(0.5)
        self.bus.write_byte_data(self.I2C_ADDR,self.CMD_STAT_REG,0x15) 
        time.sleep(0.5)
        self.bus.write_byte_data(self.I2C_ADDR,self.CMD_STAT_REG,0x21)
        time.sleep(0.5)

Please note that I wrote this program after writing image to the sensor and confirming the application code to be 0x03.

berickson commented 11 months ago

I know it's been a while, but I tried getting a .cpp version of above working, and it isn't working for me. The code below seems to have no effect. Has anyone got this working from within the library?

   Serial.printf("setting I2C address to 0x%02x\n", address);

    // shift address by one bit 
    address = ((address&0x75)<<1)&0xfe;

    // Change 0x31 GPIO_0 & 0x32 GPIO_1 registers to 0x5 (Output high)
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_GPIO_0, 0x5);
    delay(500);
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_GPIO_1, 0x5);
    delay(500);
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_CMD_STAT, TMF8X2X_COM_CMD_STAT__cmd_stat__CMD_LOAD_CONFIG_PAGE_COMMON);
    delay(500);

    // wait for status to be less than 0x10
    uint8_t status = 0x20;
    while (status >= 0x10) // read until a value less than 0x10 is transmitted
    {
        _i2cBus->readRegisterRegion(_i2cAddress, TMF8X2X_COM_CMD_STAT, &status, 1);
        delay(100);
    }
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_I2C_SLAVE_ADDRESS, address);
    delay(500);
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_I2C_ADDR_CHANGE, 0xf);
    delay(500);
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_CMD_STAT, TMF8X2X_COM_CMD_STAT__cmd_stat__CMD_WRITE_CONFIG_PAGE);
    delay(500);
    _i2cBus->writeRegisterByte(_i2cAddress, TMF8X2X_COM_CMD_STAT, TMF8X2X_COM_CMD_STAT__cmd_stat__CMD_I2C_SLAVE_ADDRESS);

    Serial.printf("I2C address now reads as 0x%02x\n", getI2CAddress());
shivakumar-tekumatla commented 11 months ago

@berickson , can you try with a different delay between the commands? Maybe 1 second ? I do not know if this is the case , but I remember changing the delays when switching from python to cpp.

berickson commented 11 months ago

@shivakumar-tekumatla Thanks for the reply. I tried changing all delays to 1 second and didn't get any change in behavior.

shivakumar-tekumatla commented 11 months ago

@berickson , another reason could be the factory firmware might have changed since then. Are you using the latest one ? if that is the case can you try following the actual method from the documentation. I remember talking to them to change the process and the documentation. They might have done that

b1uep0nd commented 11 months ago

I encountered the same issue as described in this GitHub issue while working with C code. However, I was able to resolve it and would like to share my solution. It seems that the firmware defined in tof_bin_image.c is outdated and likely contains bugs related to TMF882X. I downloaded the latest hex file from the TMF882X website and resolved the issue by specifying hex mode when calling fwdl. I hope this information is helpful.

shivakumar-tekumatla commented 11 months ago

@b1uep0nd thanks for your comment. Please post your solution.

berickson commented 11 months ago

@b1uep0nd I'll try with the udpated hex. Before I start, I'm curious. After you set the I2C address, does it survive reboots and firmware uploads or does the address need to be set every time the devices start up?

b1uep0nd commented 11 months ago

I modified the loadFirmware function like this. The firmwareBinImage is the latest HEX data downloaded.

    // Load the fireware.
    if (tmf882x_fwdl(&_TOF, FWDL_TYPE_HEX, firmwareBinImage, length))

@berickson You will need to set the address every time the device starts up.