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.

[参考译文] OPT3004:能够&'t 更改传感器配置

Guru**** 2455360 points
Other Parts Discussed in Thread: OPT3004

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

https://e2e.ti.com/support/sensors-group/sensors/f/sensors-forum/1510066/opt3004-can-t-change-the-sensor-configuration

器件型号:OPT3004

工具/软件:

大家好、我正在将 OPT3004环境光传感器实施到 ESP32-S3固件中。

我能够建立 I2C 连接、读取所有寄存器的值都没有问题。 但是、在尝试更改配置寄存器时、该命令不会生效。

以下是写入、然后读取配置寄存器时的逻辑分析仪图片:

由于某种原因、图像没有最佳分辨率、以下是图像的数据:

写入0x44 0x01 0xD0 0x7C

然后、读取过程为:写入0x44 0x01读取0x44 0xD0 0x1C、

以下是配置时我的实现代码:

static const uint8_t OPT3004_I2C_ADDR = 0x44; // I2C Address OPT3004
i2c_master_dev_handle_t opt3004_i2c_dev_handle;

typedef enum
{
  OPT3004_REG_RESULT = 0x00,
  OPT3004_REG_CONFIG = 0x01,
  OPT3004_REG_LO_THRESH = 0x02,
  OPT3004_REG_HI_THRESH = 0x03,
  OPT3004_REG_MANUFACTURER_ID = 0x7E,
  OPT3004_REG_DEVICE_ID = 0x7F
} opt3004_reg_addr_t;

typedef union{
  uint16_t reg;
  struct{
    uint16_t exponent:4;
    uint16_t fraction:12;
  } bytes;
} opt3004_reg_t;

typedef union{
  uint16_t conf;
  struct{
    uint16_t range_num_field:4; // R/W full scale range selection
    uint16_t conversion_time:1; // R/W time for conversion 0:100ms 1:800ms
    uint16_t conversion_mode:2; // R/W mode of conversion 00:shutdown 01:singleshot 10-11:continuous
    uint16_t overflow:1; // R 0:light between selected scale 1:light exceeds selected scale
    uint16_t conversion_ready:1; // R 0:conversion not ready 1:conversion ready
    uint16_t flag_high:1; // R 0:light below high threshold 1:light above high threshold
    uint16_t flag_low:1; // R 0:light above low threshold 1:light below low threshold
    uint16_t latch_field:1; // R/W 0:interrupt with no user-controlled clear 1:interrupt with user-controlled clear
    uint16_t polarity:1; // R/W 0:active low 1:active high
    uint16_t mask_exponent:1; // R/W 0:no change to exponent value of register 1:changes the value of exponent to 0000b when range is manually selected
    uint16_t fault_count:2; // R/W number of faults to trigger interrupt 00:1 fault 01:2 faults 10:4 faults 11:8 faults
  } bits;
} opt3004_conf_t;

opt3004_status_t opt3004_init(opt3004_t *opt3004_params)
{
  ESP_LOGI(TAG, "%s - Initializing OPT3004", __func__);
  if (opt3004_params == NULL)
  {
    ESP_LOGE(TAG, "%s - NULL Params", __func__);
    return OPT3004_ERR;
  }
  OPT3004_PARAMS = opt3004_params;
  //Init I2C
  if (opt3004_i2c_init_device() != OPT3004_OK)
  {
    ESP_LOGE(TAG, "%s - Error init I2C", __func__);
    return OPT3004_ERR;
  }
  //Read Manufacturer ID
  uint16_t manufacturerID = 0;
  if (opt3004_read_reg_i2c(OPT3004_REG_MANUFACTURER_ID, &manufacturerID, 0) != OPT3004_OK)
  {
    ESP_LOGE(TAG, "%s - Error reading Manufacturer ID", __func__);
    return OPT3004_ERR;
  }
  ESP_LOGI(TAG, "%s - Manufacturer ID: %04X", __func__, manufacturerID);
  //Read Device ID
  uint16_t deviceID = 0;
  if (opt3004_read_reg_i2c(OPT3004_REG_DEVICE_ID, &deviceID, 0) != OPT3004_OK)
  {
    ESP_LOGE(TAG, "%s - Error reading Device ID", __func__);
    return OPT3004_ERR;
  }
  ESP_LOGI(TAG, "%s - Device ID: %04X", __func__, deviceID);
  //Read Config
  uint16_t conf_reg = 0;
  if (opt3004_read_reg_i2c(OPT3004_REG_CONFIG, &conf_reg, 0) != OPT3004_OK)
  {
    ESP_LOGE(TAG, "%s - Error reading Config", __func__);
    return OPT3004_ERR;
  }
  ESP_LOGI(TAG, "%s - Config register %04X", __func__, conf_reg);
  opt3004_conf_t conf;
  conf.conf = conf_reg;
  ESP_LOGI(TAG, "%s - Configuration", __func__);
  ESP_LOGI(TAG, "%s - Range: %s", __func__, conf.bits.range_num_field == 0b1100 ? "Automatic" : "Manual");
  ESP_LOGI(TAG, "%s - Convertion time: %s", __func__, conf.bits.conversion_time == 0b1 ? "800ms" : "100ms");
  ESP_LOGI(TAG, "%s - Conversion mode: %s", __func__, conf.bits.conversion_mode == 0b00 ? "Shutdown" : conf.bits.conversion_mode == 0b01 ? "One shot" : "Continuos conversion");
  ESP_LOGI(TAG, "%s - Latch: %s", __func__, conf.bits.latch_field == 0b0 ? "Transparent Hysteresis" : "Window Hysteresis");
  ESP_LOGI(TAG, "%s - Polarity: %s", __func__, conf.bits.polarity == 0b0 ? "Active Low Interrupt" : "Active High Interrupt");
  ESP_LOGI(TAG, "%s - Exponent: %s", __func__, conf.bits.mask_exponent == 0b0 ? "No change to exponent value of register" : "Change to exponent value of register");
  ESP_LOGI(TAG, "%s - Fault count: %s", __func__, conf.bits.fault_count == 0b00 ? "1 fault" : conf.bits.fault_count == 0b01 ? "2 faults" : conf.bits.fault_count == 0b10 ? "4 faults" : "8 faults");
  ESP_LOGI(TAG, "%s - Flag high: %d", __func__, conf.bits.flag_high);
  ESP_LOGI(TAG, "%s - Flag low: %d", __func__, conf.bits.flag_low);
  ESP_LOGI(TAG, "%s - Convertion overflow: %d", __func__, conf.bits.overflow);
  ESP_LOGI(TAG, "%s - Convertion ready: %d", __func__, conf.bits.conversion_ready);
  //New configuration
  conf.bits.range_num_field = 0b1100; // Automatic full-scale setting
  conf.bits.conversion_time = 0b1; // 800ms conversion time
  conf.bits.conversion_mode = 0b11; // Continuous conversion mode
  ESP_LOGI(TAG, "New Config %04X", conf.conf);
  //Write new configuration
  if (opt3004_escribir_reg_i2c(OPT3004_REG_CONFIG, conf.conf) != OPT3004_OK)
  {
    ESP_LOGE(TAG, "%s - Error writing new configuration", __func__);
    return OPT3004_ERR;
  }
  //Read new configuration
  if (opt3004_read_reg_i2c(OPT3004_REG_CONFIG, &conf_reg, 0) != OPT3004_OK)
  {
    ESP_LOGE(TAG, "%s - Error al leer registro de configuración", __func__);
    return OPT3004_ERR;
  }
  ESP_LOGI(TAG, "%s - New config Read %04X", __func__, conf_reg);
  ESP_LOGI(TAG, "%s - Sensor OPT3004 initialized", __func__);
  return OPT3004_OK;
}

以下是与 OPT3004交互时 ESP32-S3固件的记录数据:

I (8505) OPT3004: opt3004_init - Initializing OPT3004
I (8575) OPT3004: opt3004_init - Manufacturer ID: 5449
I (8615) OPT3004: opt3004_init - Device ID: 3001
I (8625) OPT3004: opt3004_init - Config register D01C
I (8635) OPT3004: opt3004_init - Configuration
I (8635) OPT3004: opt3004_init - Range: Automatic
I (8645) OPT3004: opt3004_init - Convertion time: 800ms
I (8645) OPT3004: opt3004_init - Convertion mode: Shutdown
I (8655) OPT3004: opt3004_init - Latch: Transparent Hysteresis
I (8655) OPT3004: opt3004_init - Polarity: Active High Interrupt
I (8665) OPT3004: opt3004_init - Exponent: No change to exponent value of register
I (8675) OPT3004: opt3004_init - Fault count: 8 faults
I (8675) OPT3004: opt3004_init - Flag high: 0
I (8685) OPT3004: opt3004_init - Flag low: 0
I (8685) OPT3004: opt3004_init - Convertion overflow: 0
I (8685) OPT3004: opt3004_init - Convertion ready: 0
I (8695) OPT3004: New Config D07C
I (8705) OPT3004: opt3004_init - New config Read D01C
I (8705) OPT3004: opt3004_init - Sensor OPT3004 initialized


我不知道如何才能将转换模式从"关断"更改为"连续"。

希望您可以帮助我找出导致此问题的原因。

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

    您好、Ivan、  

    我想您可能无法正确寻址写入命令。  

    在写入时尝试0x45  

    谢谢、  

    Joseph Scherphorn

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

    嗯、问题是我用来解析配置数据的联合体、我在解析结果数据时遇到了相同的问题。 以下是两个联合体都已校正的代码片段:

    typedef union{
      uint16_t reg;
      struct{
        uint16_t fraction:12;
        uint16_t exponent:4;
      } bytes;
    } opt3004_reg_t;
    
    typedef union{
      uint16_t conf;
      struct{
        uint16_t fault_count:2; // R/W number of faults to trigger interrupt 00:1 fault 01:2 faults 10:4 faults 11:8 faults
        uint16_t mask_exponent:1; // R/W 0:no change to exponent value of register 1:changes the value of exponent to 0000b when range is manually selected
        uint16_t polarity:1; // R/W 0:active low 1:active high
        uint16_t latch_field:1; // R/W 0:interrupt with no user-controlled clear 1:interrupt with user-controlled clear
        uint16_t flag_low:1; // R 0:light above low threshold 1:light below low threshold
        uint16_t flag_high:1; // R 0:light below high threshold 1:light above high threshold
        uint16_t conversion_ready:1; // R 0:conversion not ready 1:conversion ready
        uint16_t overflow:1; // R 0:light between selected scale 1:light exceeds selected scale
        uint16_t conversion_mode:2; // R/W mode of conversion 00:shutdown 01:singleshot 10-11:continuous
        uint16_t conversion_time:1; // R/W time for conversion 0:100ms 1:800ms
        uint16_t range_num_field:4; // R/W full scale range selection
      } bits;
    } opt3004_conf_t;

    这一切都是关于字节的字节序、传感器首先发送 MSB、ESP32-S3固件以 LSB 优先的方式工作...

    另外、在读取操作中、我有一个溢出会破坏数据缓冲区:

    *res = ((uint16_t)result[0] << 8) | result[1];

    我没有将"Result[0]"转换为 uint16_t、这出于某种明显的原因会破坏整个缓冲区。

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

    感谢您跟进并分享您的调查结果。