This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] OPT4048:OPT4048DTSR

Guru**** 2555380 points
Other Parts Discussed in Thread: OPT4048

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/sensors-group/sensors/f/sensors-forum/1541874/opt4048-opt4048dtsr

器件型号:OPT4048


工具/软件:

我正在使用 OPT4048 光传感器来测量光亮度和 CCT 值。 我正在读取 0x0、0x2、0x04、0x06 寄存器、我要执行的转换步骤如下所示  

I2C_Transfer_Deft Return_Type = I2C_TRANSACTION (I2C_FLAG_WRITE_READ、OPT4048_I2C_BUS_ADDRESSRegistered、1、数据、 3);

if (ret != i2cTransferDone){

*通道[i]= 0;

返回 false

}

uint8_t EXPONENT =(DATA[0]>>4)& 0x0F;

uint32_t MANTISSA =(((DATA[0]和 0x0F)<< 16)|(DATA[1]<< 8)| DATA[2];

*通道[i]= MANTISSA * 0.00215f * POW(2,指数);

我正在接收来自通道 0 的光数据、并使用通道 1、2、3 数据进行 CCT 计算。

但我面临的问题是、即使光强度发生变化、每次读数都是恒定的。

重新启动器件后、会更新正确的读数。 在配置寄存器中、我正在使用连续模式、通过{0x0A、0x0C、0x9F}写入 config reg

我是否需要添加更多延迟、或者应该使用中断引脚来获得更新的读数?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Gayathri:

    我有几个问题:

    1.您能否发送配置的其余部分? 似乎您列出的部分配置在文本中被切断。 您能否向我发送寄存器 0x0A 和 0x0B 的值?

    2.您提到读数是恒定的,即使光强度发生变化。 这是否仅适用于前几个样本? 它最终是否会发送更新的读数?

    可能是您在传感器有足够时间更新之前读取传感器输出、从而导致多个重复的读数。 在这种情况下、添加更多延迟或使用中断引脚可能起作用。  

    我认为最好的选择是使中断能够在每次转换结束时触发。 这样、MCU 会在转换完成时收到通知、并启动 I2C 读取。

    谢谢、
    Daniel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Daniel:  

    我正在共享代码片段。 我在代码中未使用 0x0B 寄存器。 整个时间内的值保持不变、而不仅仅是对几个样本而言。 此外、每 10s 后调用一次 READ 函数。  

    谢谢、

    Gayathri

     /*
     * ALS_OPT4048.cpp
     *
     */
    
    #include <math.h>
    #include "AppEvent.h"
    #include "TextOnlyLogging.h"
    
    
    // Add this to the top of your ALS_OPT4048.cpp file:
    #include <stdio.h>
    #include "ALS_OPT4048.h"
    #include "I2C_sensors.h"
    #include "sl_sleeptimer.h"
    #include "sl_i2cspm.h"
     #define OPT4048_I2C_BUS_ADDRESS OPT4048_ADDR_GND
    
    
    // Improved initialization with better error checking
    bool OPT4048::init()
    {
        ChipLogDetail(AppServer, "Starting OPT4048 initialization...");
    
        if (!checkDeviceID()) {
            ChipLogError(AppServer, "OPT4048 Device ID check failed!");
            return false;
        }
    
        ChipLogDetail(AppServer, "OPT4048 Device ID verified successfully");
    
        uint8_t reset[3] = { OPT4048_REG_CONFIG, 0x00, 0x01 };
        if (I2C_transaction(I2C_FLAG_WRITE, OPT4048_I2C_BUS_ADDRESS, reset, 3, nullptr, 0) != i2cTransferDone) {
            ChipLogError(AppServer, "OPT4048 soft reset failed");
            return false;
        }
    
        sl_sleeptimer_delay_millisecond(100);
    
        uint8_t config[3] = { OPT4048_REG_CONFIG, 0x0C, 0x9F };
        if (I2C_transaction(I2C_FLAG_WRITE, OPT4048_I2C_BUS_ADDRESS, config, 3, nullptr, 0) != i2cTransferDone) {
            ChipLogError(AppServer, "OPT4048 configuration failed");
            return false;
        }
    
        ChipLogDetail(AppServer, "OPT4048 configured, waiting for data...");
        sl_sleeptimer_delay_millisecond(100);  // Increased for stabilization
    
        debugReadAllRegisters();
        return true;
    }
    
    bool OPT4048::checkDeviceID()
    {
        uint8_t reg = OPT4048_REG_DEVICE_ID;
        uint8_t data[2];
    
        if (I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, data, 2) != i2cTransferDone)
            return false;
    
        bool idValid = ((data[0] == OPT4048_DEVICE_ID_L) && (data[1] == OPT4048_DEVICE_ID_H));
        if (!idValid)
            ChipLogError(AppServer, "Device ID mismatch: 0x%02X 0x%02X", data[0], data[1]);
    
        return idValid;
    }
    
    // Debug function to read and display all important registers
    bool OPT4048::debugReadAllRegisters()
    {
        uint8_t reg;
        uint8_t data[3];
        I2C_TransferReturn_TypeDef ret;
    
        // Read Device ID
        reg = OPT4048_REG_DEVICE_ID;
        ret = I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, data, 2);
        if (ret == i2cTransferDone) {
            uint16_t deviceID = (data[0] << 8) | data[1];
            ChipLogDetail(AppServer, "Device ID: 0x%04X (expected: 0x8021)", deviceID);
        } else {
            ChipLogError(AppServer, "Failed to read Device ID, I2C error: %d", ret);
            return false;
        }
    
        // Read Configuration Register
        reg = OPT4048_REG_CONFIG;
        ret = I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, data, 2);
        if (ret == i2cTransferDone) {
            uint16_t config = (data[0] << 8) | data[1];
            ChipLogDetail(AppServer, "Config Register: 0x%04X", config);
            ChipLogDetail(AppServer, "  - Mode: %d (0=powerdown, 1=forced, 2=oneshot, 3=continuous)",
                         (config >> 2) & 0x03);
            ChipLogDetail(AppServer, "  - Conversion Time: %d", (config >> 4) & 0x0F);
            ChipLogDetail(AppServer, "  - Range: %d", config & 0x0F);
        } else {
            ChipLogError(AppServer, "Failed to read Config Register");
        }
    
        // Read all channel registers
        // Use correct MSB+LSB pair per channel
        const uint8_t channelRegs[4][2] = {
            { 0x00, 0x01 },  // CH0
            { 0x02, 0x03 },  // CH1
            { 0x04, 0x05 },  // CH2
            { 0x06, 0x07 }   // CH3
        };
    
    
    
        for (int i = 0; i < 4; i++) {
    
            uint8_t upper = 10, lower = 20;
    
            // Read MSB + exponent
            reg = channelRegs[i][0];
            ret = I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, &upper, 1);
            if (ret != i2cTransferDone) continue;
    
            // Optional short delay (some chips need > tBUF between register reads)
            sl_sleeptimer_delay_millisecond(1);
    
            // Read LSB + CRC
            reg = channelRegs[i][1];
            ret = I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, &lower, 1);
            if (ret != i2cTransferDone) continue;
    
            uint8_t exponent = (upper >> 4) & 0x0F;
            uint16_t mantissa = ((upper & 0x0F) << 8) | (lower >> 4);
            float lux = mantissa * 0.00215f * pow(2, exponent);
    
            ChipLogDetail(AppServer, "CH%d Lux: %.2f (Exp=%u, Mant=%u)", i, lux, exponent, mantissa);
        }
    
    
        return true;
    }
    
    
    
    /*float OPT4048::readChannels(float &ch0, float &ch1, float &ch2, float &ch3)
    {// Optional: Wait for conversion to complete
      sl_sleeptimer_delay_millisecond(120);  // Match your conversion time
    
      // Read 3 bytes from CH3 MSB register (0x06)
      uint8_t reg = 0x06;
      uint8_t data[3];
      sl_sleeptimer_delay_millisecond(500);  // Between reads
      I2C_TransferReturn_TypeDef ret = I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, data, 3);
      if (ret != i2cTransferDone)
          return false;
    
      uint8_t msb = data[0];
      uint8_t mid = data[1];
      uint8_t lsb = data[2];
    
      //uint8_t exponent = (msb >> 4) & 0x0F;
      uint32_t mantissa = ((msb & 0x0F) << 16) | (mid << 8) | lsb;
    
      // Recommended lux calculation (datasheet Equation 9)
      float lux = mantissa * 0.00215f;
    
      // Store or scale as needed
      Luminance_Val = lux;
    
      return Luminance_Val;
    }*/
    
    bool OPT4048::readAllChannels(float & ch0, float & ch1, float & ch2, float & ch3)
    {
        const uint8_t channelRegs[4] = { 0x00, 0x02, 0x04, 0x06 };
        float * channels[4] = { &ch0, &ch1, &ch2, &ch3 };
    
        for (int i = 0; i < 4; i++)
        {
            uint8_t reg = channelRegs[i];
            uint8_t data[3] = {0};
    
            I2C_TransferReturn_TypeDef ret = I2C_transaction(I2C_FLAG_WRITE_READ, OPT4048_I2C_BUS_ADDRESS, &reg, 1, data, 3);
            if (ret != i2cTransferDone) {
                *channels[i] = 0;
                return false;
            }
    
            uint8_t exponent = (data[0] >> 4) & 0x0F;
            uint32_t mantissa = ((data[0] & 0x0F) << 16) | (data[1] << 8) | data[2];
            *channels[i] = mantissa * 0.00215f * pow(2, exponent);
        }
        sl_sleeptimer_delay_millisecond(500);  // Increased for stabilization
    
        return true;
    }
    
    bool OPT4048::calculateCCT(float ch1, float ch2, float ch3, float & cie_x, float & cie_y, float & cct)
    {
        float X = 0.4124f * ch1 + 0.3576f * ch2 + 0.1805f * ch3;
        float Y = 0.2126f * ch1 + 0.7152f * ch2 + 0.0722f * ch3;
        float Z = 0.0193f * ch1 + 0.1192f * ch2 + 0.9505f * ch3;
    
        float sum = X + Y + Z;
        if (sum == 0.0f) {
            cie_x = cie_y = cct = 0.0f;
            return false;
        }
    
        cie_x = X / sum;
        cie_y = Y / sum;
    
        float n = (cie_x - 0.3320f) / (0.1858f - cie_y);
        cct = 449.0f * powf(n, 3) + 3525.0f * powf(n, 2) + 6823.3f * n + 5520.33f;
        return true;
    }
    
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Gayathri:

    您能指出在代码中设置器件配置的部分吗? 我没有看到对配置寄存器 0x0A 进行 I2C 写入。 您能否介绍一下 0x0A 寄存器的内容?  

    谢谢、

    Daniel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Uint8_t CONFIG[3]={0x0A、0x0C、0x9F};

    I2C_TRANSACTION (I2C_FLAG_WRITE、OPT4048_I2C_BUS_ADDRESS、CONFIG、3、Nullptr、 0)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Gayathri:

    看起来您正在将 0x0C9F 写入配置寄存器、对吗? 在这种情况下、工作模式位 (5-4) 实际上为 01、这意味着您处于单触发模式而不是连续模式。 这也解释了为什么您只在复位器件后才看到寄存器更新为正确的值。 重新发送器件配置时、将触发单触发测量、以更新这些寄存器以反映新的光强度。

    谢谢、

    Daniel

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢您的问题一直出现在 0x0A 寄存器中。 重新检查数据表后、我将其更改为 0x3230。 我的值更新正常。

    谢谢、

    Gayathri