FDC1004: MEAS*_MSB register output fixed value:0X7FFF

Part Number: FDC1004

HI all,

I am new to FDC1004, i am using FDC1004 with ESP-32 with I2C in single measurement mode. But MEAS*_MSB registers always returns fixed value0X7FFF. My code is same as the related question:

FDC1004 returns fixed value - Sensors forum - Sensors - TI E2E support forums

  • 您好,

    已经收到了您的案例,调查需要些时间,感谢您的耐心等待。

  • add other info :

    (1)pcb picture as follows:

    (2)source code:

    A. fdc1004_dreiver.c:

    #define FDC1004_SAMPLE_RATE_100HZ (0x01)
    #define FDC1004_SAMPLE_RATE_200HZ (0x02)
    #define FDC1004_SAMPLE_RATE_400HZ (0x03)


    #define FDC1004_CONF_MEAS_CHA_SHIFT (13)
    #define FDC1004_CONF_MEAS_CHB_SHIFT (10)
    #define FDC1004_CONF_MEAS_CAPDAC_SHIFT (5)
    #define FDC1004_CONF_MEAS_CHB_DISABLED (0x7)
    #define FDC1004_CONF_MEAS_CHB_DISABLED_CAPDAC_ENABLE (0x4)

    #define FDC1004_FDC_CONF_RATE_SHIFT (10)
    #define FDC1004_FDC_CONF_REPEAT_SHIFT (8)

    #define FDC1004_REG_MEAS1_MSB (0x00)
    #define FDC1004_REG_MEAS1_LSB (0x01)
    #define FDC1004_REG_MEAS2_MSB (0x02)
    #define FDC1004_REG_MEAS2_LSB (0x03)
    #define FDC1004_REG_MEAS3_MSB (0x04)
    #define FDC1004_REG_MEAS3_LSB (0x05)
    #define FDC1004_REG_MEAS4_MSB (0x06)
    #define FDC1004_REG_MEAS4_LSB (0x07)
    #define FDC1004_REG_CONF_MEAS1 (0x08)
    #define FDC1004_REG_CONF_MEAS2 (0x09)
    #define FDC1004_REG_CONF_MEAS3 (0x0A)
    #define FDC1004_REG_CONF_MEAS4 (0x0B)
    #define FDC1004_REG_FDC_CONF (0x0C)
    #define FDC1004_REG_DEVICE_ID (0xFF)

    // Measurement bounds for CAPDAC adjustment
    #define FDC1004_UPPER_BOUND (0x4000)
    #define FDC1004_LOWER_BOUND (-0x4000)

    // Conversion constants
    #define FDC1004_ATTOFARADS_UPPER_WORD (457)
    #define FDC1004_FEMTOFARADS_CAPDAC (3028)

    #define FDC1004_CAPDAC_MAX (0x1F)
    #define FDC1004_CHANNEL_MAX (0x03)
    #define FDC1004_MEASUREMENT_MAX (0x03)
    #define FDC1004_IS_CHANNEL(x) (x >= 0 && x <= FDC1004_CHANNEL_MAX)

    #define FDC1004_MEAS_MAX (0x03)
    #define FDC1004_IS_MEAS(x) (x >= 0 && x <= FDC1004_MEAS_MAX)

    static const uint8_t SAMPLE_DELAYS_MS[] = {11, 11, 6}; // Delays for 100Hz, 200Hz, 400Hz
    static const uint8_t MEASUREMENT_CONFIG_REGISTERS[] = {
        FDC1004_REG_CONF_MEAS1, FDC1004_REG_CONF_MEAS2,
        FDC1004_REG_CONF_MEAS3, FDC1004_REG_CONF_MEAS4};

    static const uint8_t MEASUREMENT_MSB_REGISTERS[] = {
        FDC1004_REG_MEAS1_MSB, FDC1004_REG_MEAS2_MSB,
        FDC1004_REG_MEAS3_MSB, FDC1004_REG_MEAS4_MSB};

    static const uint8_t MEASUREMENT_LSB_REGISTERS[] = {
        FDC1004_REG_MEAS1_LSB, FDC1004_REG_MEAS2_LSB,
        FDC1004_REG_MEAS3_LSB, FDC1004_REG_MEAS4_LSB};

    // Configuration bits
    constexpr uint16_t FDC_CONF_RST = (1 << 15);
    constexpr uint16_t FDC_CONF_REPEAT = (1 << 8);

    namespace LiquidLevelSensor
    {

    bool FDC1004::init()
    {
        // Verify communication by reading manufacturer ID and device ID
        uint16_t device_id = read_device_id();
        ESP_LOGI(TAG, "Device ID: 0x%04X", device_id);


        // 重置设备
        if (!writeRegister16(FDC1004_REG_FDC_CONF, 0x8000))
        { // 设置复位位
            ESP_LOGE(TAG, "Failed to reset device");
            return false;
        }

        // 等待复位完成
        vTaskDelay(pdMS_TO_TICKS(10)); // 10ms延迟

        // test code
        uint16_t value_of_fdc_conf = readRegister16(FDC1004_REG_FDC_CONF);
        ESP_LOGI(TAG, "FDC_CONF: 0x%04X", value_of_fdc_conf);
        ESP_LOGI(TAG, "FDC1004 initialized successfully");
        return true;
    }

    uint8_t FDC1004::get_rate()
    {
        return rate_;
    }

    uint8_t FDC1004::get_capdac(uint8_t channel)
    {
        if (channel > 3 || channel < 0)
        {
            ESP_LOGE(TAG, "Invalid channel: %d", channel);
            return -1; // Invalid channel
        }
        return capdac_[channel];
    }

    void FDC1004::set_capdac(uint8_t channel, uint8_t capdac_val)
    {
        if (channel > 3 || channel < 0)
        {
            ESP_LOGE(TAG, "Invalid channel: %d", channel);
            return; // Invalid channel
        }

        ESP_LOGI(TAG, "Setting CAPDAC for channel %d : %d--->%d", channel, capdac_[channel], capdac_val);

        capdac_[channel] = capdac_val;
    }


    bool FDC1004::configure_measurement(uint8_t channel)
    {
        if (channel > 3 || channel < 0)
        {
            ESP_LOGE(TAG, "Invalid channel: %d", channel);
            return false;
        }

    #if 1
        uint8_t capdac_value = get_capdac(channel);

        // Configure measurement register
        uint16_t conf_value = (((uint16_t)channel) << FDC1004_CONF_MEAS_CHA_SHIFT) | // CHA
                              (FDC1004_CONF_MEAS_CHB_DISABLED_CAPDAC_ENABLE << FDC1004_CONF_MEAS_CHB_SHIFT) |         // CHB = CAPDAC
                              (((uint16_t)capdac_value) << FDC1004_CONF_MEAS_CAPDAC_SHIFT);    // CAPDAC value

        writeRegister16(MEASUREMENT_CONFIG_REGISTERS[channel], conf_value);

        uint16_t fdc_register = readRegister16(MEASUREMENT_CONFIG_REGISTERS[channel]);
        ESP_LOGI(TAG, "Measurement %d configured with value: 0x%04X, set value 0x%04X", channel, fdc_register, conf_value);
    #else
        uint8_t capdac_value = 0;
        int16_t conf_value = 0;

        for (int i = 0; i < 4; i++)
        {

            capdac_value = get_capdac(i);
            conf_value = (((int16_t)i) << FDC1004_CONF_MEAS_CHA_SHIFT) | // CHA
                         (FDC1004_CONF_MEAS_CHB_DISABLED << FDC1004_CONF_MEAS_CHB_SHIFT) |         // CHB = CAPDAC
                         (((int16_t)capdac_value) << FDC1004_CONF_MEAS_CAPDAC_SHIFT);    // CAPDAC value


            writeRegister16(MEASUREMENT_CONFIG_REGISTERS[i], conf_value);
        }
    #endif
        return true;
    }

    bool FDC1004::trigger_measurement(uint8_t channel)
    {
        if (channel > 3)
        {
            ESP_LOGE(TAG, "Invalid measurement number: %d", channel);
            return false;
        }

        uint8_t rate_val = get_rate();

        ESP_LOGI(TAG, "Triggering measurement on  rate 0X%x",  rate_val);

    #if 1
        uint16_t fdc_conf = 0;
        fdc_conf = ((uint16_t)rate_val) << FDC1004_FDC_CONF_RATE_SHIFT; // sample rate
        fdc_conf |= 1 << FDC1004_FDC_CONF_REPEAT_SHIFT; //repeat disabled
        fdc_conf |= (1 << (7-channel)); // Enable measurement
       
        writeRegister16(FDC1004_REG_FDC_CONF, fdc_conf);

        uint16_t fdc_register = readRegister16(FDC1004_REG_FDC_CONF);
        ESP_LOGI(TAG, "FDC_CONF: 0x%04X, set value 0x%04X", fdc_register, fdc_conf);

        if (rate_val == FDC1004_SAMPLE_RATE_100HZ)
            vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[0])); // delay for conf work
        else if (rate_val == FDC1004_SAMPLE_RATE_200HZ)
            vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[1])); // delay for conf work
        else if (rate_val == FDC1004_SAMPLE_RATE_400HZ)
            vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[2])); // delay for conf work
        else
            vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[0])); // delay for conf work
    #else
        uint16_t fdc_conf = 0;
        for (int i = 0; i < 4; i++)
        {
            fdc_conf = ((uint16_t)rate_val) << FDC1004_FDC_CONF_RATE_SHIFT; // sample rate
            fdc_conf |= 0 << FDC1004_FDC_CONF_REPEAT_SHIFT; //repeat disabled
            fdc_conf |= (1 << (7 - i)); // Enable measurement

            writeRegister16(FDC1004_REG_FDC_CONF, fdc_conf);

            if (rate_val == FDC1004_SAMPLE_RATE_100HZ) {
                ESP_LOGI(TAG, "Triggering measurement on channel delay %d for 100HZ", SAMPLE_DELAYS_MS[0]);
                vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[0])); // delay for conf work
            }
            else if (rate_val == FDC1004_SAMPLE_RATE_200HZ) {
                ESP_LOGI(TAG, "Triggering measurement on channel delay %d for 200HZ", SAMPLE_DELAYS_MS[0]);
                vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[1])); // delay for conf work
            }
            else if (rate_val == FDC1004_SAMPLE_RATE_400HZ) {
                ESP_LOGI(TAG, "Triggering measurement on channel delay %d for 400HZ", SAMPLE_DELAYS_MS[0]);
                vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[2])); // delay for conf work
            }
            else {
                ESP_LOGI(TAG, "Triggering measurement on channel default delay %d for 100HZ", SAMPLE_DELAYS_MS[0]);
                vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[0])); // delay for conf work
            }
        }
    #endif
        return true;
    }


    float FDC1004::read_capacitance(uint8_t channel)
    {
        if (channel > 3)
        {
            ESP_LOGE(TAG, "Invalid measurement number: %d", channel);
            return false;
        }

        uint16_t fdc_register = readRegister16(FDC1004_REG_FDC_CONF);
        if (!(fdc_register & ( 1 << (3-channel)))) {
            //ESP_LOGI(TAG, "measurement not completed");
            //vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[0]))
            //return -1;

            int count = 0;
            do {
                vTaskDelay(pdMS_TO_TICKS(SAMPLE_DELAYS_MS[0])); // wait for measurement to complete
                fdc_register = readRegister16(FDC1004_REG_FDC_CONF);
                count++;          
            } while((!(fdc_register & ( 1 << (3-channel)))) && count < 5);

            if (count >= 5) {
                ESP_LOGE(TAG, "channel %d Measurement not completed after retries", channel);
                return -1; // Measurement not completed
            }
        }

       

        uint16_t msb = readRegister16(MEASUREMENT_MSB_REGISTERS[channel]);
        uint16_t lsb = readRegister16(MEASUREMENT_LSB_REGISTERS[channel]);

        ESP_LOGI(TAG, "Measurement %d MSB: 0x%04X, LSB: 0x%04X", channel, msb, lsb);

        // convertToPicofarads
        uint8_t cur_capdac = get_capdac(channel);

        float capacitance_af = (float)FDC1004_ATTOFARADS_UPPER_WORD * (float)msb;  // attofarads
        float capacitance_pf = capacitance_af / 1000000.0f;                        // Convert to picofarads
        capacitance_pf += ((float)FDC1004_FEMTOFARADS_CAPDAC * (float)cur_capdac) / 1000.0f; // Add CAPDAC offset

        // if (msb == 0x7fff) {
        //     uint16_t conf = 0;
        //     conf = ((uint16_t)rate_val) << FDC1004_FDC_CONF_RATE_SHIFT; // sample rate
        //     conf |= 0 << FDC1004_FDC_CONF_REPEAT_SHIFT; //repeat disabled
        //     conf |= (1 << (7-channel)); // Enable measurement

        //     writeRegister16(FDC1004_REG_FDC_CONF, fdc_conf);
        // }

        // auto adjust capdac
        #if 0
        if (msb > FDC1004_UPPER_BOUND && cur_capdac < FDC1004_CAPDAC_MAX) {
            set_capdac(channel, cur_capdac + 1);
        }
        else if (msb < FDC1004_LOWER_BOUND && cur_capdac > 0) {
            set_capdac(channel, cur_capdac - 1);
        }
    #endif
        return capacitance_pf;
    }

    uint16_t FDC1004::read_device_id()
    {
        uint16_t device_id = readRegister16(FDC1004_REG_DEVICE_ID);
        return device_id;
    }

    uint16_t FDC1004::readRegister16(uint8_t reg)
    {
        uint8_t buffer[2];
        ReadRegMultiBytes(static_cast<uint8_t>(reg), buffer, 2);
        return (buffer[0] << 8) | buffer[1];
    }

    bool FDC1004::writeRegister16(uint8_t reg, uint16_t value)
    {
        uint8_t buffer[3] = {static_cast<uint8_t>(reg), static_cast<uint8_t>(value >> 8), static_cast<uint8_t>(value & 0xFF)};
        WriteRegMultiBytes(buffer, 3);
        return true;
    }

    } // namespace LiquidLevelSensor
    B. source code calling function of fdc_dreiver in application.c :
    #if 1
        fdc1004_->configure_measurement(0); // Single-ended measurement on channel 1
        // Trigger single measurement
        if(false == fdc1004_->trigger_measurement(0))
        {
            ESP_LOGE(TAG, "Failed to trigger measurement: ");
            vTaskDelay(pdMS_TO_TICKS(1000));
            // continue;
        }

        // Read capacitance
        //float capacitance;
        //float capacitance;
        //capacitance = fdc1004_->read_capacitance(0);

        ESP_LOGE(TAG, "--------------------- 0 Capacitance: %f",  fdc1004_->read_capacitance(0));

        fdc1004_->configure_measurement(1); // Single-ended measurement on channel 1
        // Trigger single measurement
        if(false == fdc1004_->trigger_measurement(1))
        {
            ESP_LOGE(TAG, "Failed to trigger measurement: ");
            vTaskDelay(pdMS_TO_TICKS(1000));
            // continue;
        }

        ESP_LOGE(TAG, "--------------------- 1 Capacitance: %f",  fdc1004_->read_capacitance(1));
    #endif
        fdc1004_->configure_measurement(2); // Single-ended measurement on channel 1
        // Trigger single measurement
        if(false == fdc1004_->trigger_measurement(2))
        {
            ESP_LOGE(TAG, "Failed to trigger measurement: ");
            vTaskDelay(pdMS_TO_TICKS(1000));
            // continue;
        }

        ESP_LOGE(TAG, "--------------------- 2 Capacitance: %f",  fdc1004_->read_capacitance(2));

        fdc1004_->configure_measurement(3); // Single-ended measurement on channel 1
        // Trigger single measurement
        if(false == fdc1004_->trigger_measurement(3))
        {
            ESP_LOGE(TAG, "Failed to trigger measurement: ");
            vTaskDelay(pdMS_TO_TICKS(1000));
            // continue;
        }

        ESP_LOGE(TAG, "--------------------- 3 Capacitance: %f",  fdc1004_->read_capacitance(3));
    }
    *********NOTES: The print info in the above code correspons to the following picture:
     
  • 您好,

          请通过读取芯片的Device ID(0x1004)来判断芯片是否工作以及验证I2C时序。

  • 1,读取MEAS*_MSB寄存器之前,已经通过读取Device ID为0x1004,判断i2c时序了

    2,循环读取了MEAS1_MSB,MEAS2_MSB,MEAS3_MSB和MEAS4_MSB四个通道的寄存器的值了,

    其中通道MEAS1和MEAS3,在电路中都是作为reference sensor,通道MEAS2和MEAS4,在电路中都是作为liquid sensor,

    通道MEAS1和MEAS2读取到的值时动态变化的,但是MEAS3和MEAS4从设备上电后读取的值就是固定的0X7FFF.

    如果i2c时序不正常,我的软件程序会reset的,实际没有reset同时能够读取4个通道MEAS*的值,说明i2c时序时正常的。

  • 您好,

         对于单端4通道采样,各通道寄存器配置是类似的。

         您是否在硬件连接上交换通道测试过?通道1<->通道3    通道2<->通道4