Xinyuan-LilyGO / T-Display-S3

MIT License
731 stars 173 forks source link

Measure BAT_ADC incorrect voltage #190

Closed krupis closed 2 months ago

krupis commented 9 months ago

I use the following code to measure the voltage on GPIO4


static int adc_raw[2][10];
static int voltage[2][10];
adc_oneshot_unit_handle_t adc1_handle;

#define EXAMPLE_ADC1_CHAN3          ADC_CHANNEL_3
#define EXAMPLE_ADC_ATTEN           ADC_ATTEN_DB_11

void ADC_Setup(){

    adc_oneshot_unit_init_cfg_t init_config1 = {
        .unit_id = ADC_UNIT_1,
    };

    ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));

        adc_oneshot_chan_cfg_t config = {
        .bitwidth = ADC_BITWIDTH_DEFAULT,
        .atten = EXAMPLE_ADC_ATTEN,
    };

    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN3, &config));

}

float Get_ADC_Voltage(uint16_t channel){
    ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, channel, &adc_raw[0][0]));
    ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, channel, adc_raw[0][0]);
    float voltage = adc_raw[0][0] * 3.3 / 4096;
    ESP_LOGI(TAG, "ADC%d Channel[%d] Voltage: %.2f", ADC_UNIT_1 + 1, channel, voltage);
    return voltage;
}

And then in my main.c I call:

Get_ADC_Voltage(EXAMPLE_ADC1_CHAN3);

I have connected the battery and measuring ADC

[1B][0;32mI (382492) ADC: ADC1 Channel[3] Raw Data: 2661[1B][0m
[1B][0;32mI (382492) ADC: ADC1 Channel[3] Voltage: 2.14[1B][0m
[1B][0;32mI (383492) ADC: ADC1 Channel[3] Raw Data: 2669[1B][0m
[1B][0;32mI (383492) ADC: ADC1 Channel[3] Voltage: 2.15[1B][0m
[1B][0;32mI (384492) ADC: ADC1 Channel[3] Raw Data: 2670[1B][0m
[1B][0;32mI (384492) ADC: ADC1 Channel[3] Voltage: 2.15[1B][0m
[1B][0;32mI (385492) ADC: ADC1 Channel[3] Raw Data: 2663[1B][0m
[1B][0;32mI (385492) ADC: ADC1 Channel[3] Voltage: 2.15[1B][0m
[1B][0;32mI (386492) ADC: ADC1 Channel[3] Raw Data: 2659[1B][0m
[1B][0;32mI (386492) ADC: ADC1 Channel[3] Voltage: 2.14[1B][0m

When measured with Multimeter, the voltage across battery terminals is 3.9V (while the battery is connected to the board)

When I disconnect the battery, the results are:

[1B][0;32mI (427542) ADC: ADC1 Channel[3] Raw Data: 2823[1B][0m
[1B][0;32mI (427542) ADC: ADC1 Channel[3] Voltage: 2.27[1B][0m
[1B][0;32mI (428542) ADC: ADC1 Channel[3] Raw Data: 2836[1B][0m
[1B][0;32mI (428542) ADC: ADC1 Channel[3] Voltage: 2.28[1B][0m
[1B][0;32mI (429542) ADC: ADC1 Channel[3] Raw Data: 2829[1B][0m
[1B][0;32mI (429542) ADC: ADC1 Channel[3] Voltage: 2.28[1B][0m

My questions:

  1. When battery is plugged in, the ADC voltage is 2.14V (considering that there is a voltage divider 100kOhm and 100kOhm), the battery voltage according to the ADC is 4.3V which is too high. The actual battery voltage is 3.9V

  2. When the battery is not connected, the ADC measures 2.28V and I cannot wrap my head around how is that possible.

nvx commented 9 months ago

I'm getting similar weirdness, showing 4095 raw value. Is there a different hw revision of the board that's wired differently or something perhaps?

krupis commented 8 months ago

@nvx The fact that you are seeing 4095 raw value is very strange indeed. Can you measure the voltage using multimeter? Since your ADC tells that there is 4095, that means the maximum value is measured on the ADC pin.

Anyways, I am still waiting for LilyGo to comment regarding this.

nvx commented 8 months ago

@nvx The fact that you are seeing 4095 raw value is very strange indeed. Can you measure the voltage using multimeter? Since your ADC tells that there is 4095, that means the maximum value is measured on the ADC pin.

Anyways, I am still waiting for LilyGo to comment regarding this.

Yeah DMM reads sane values. I got the version in a case, ended up taking it out of the case to see if I could see anything obviously wrong, after giving up I put it back in the case and now it reads a slightly saner voltage, but still much lower than it should be when running from battery, and when running from USB (with or without the battery attached) it seems to go up to 4.6V which is much higher than the DMM reads. I'm not sure if maybe there was a small solder ball or something I dislodged while bucking with it. I'm guessing there's a problem with the voltage reference.

lewisxhe commented 8 months ago

I have uploaded a short example for you to try. Since the code you provided is not included in Arduino, I only used Arduino for testing.

https://github.com/Xinyuan-LilyGO/T-Display-S3/blob/main/example/GetBatteryVoltage/GetBatteryVoltage.ino

krupis commented 8 months ago

@lewisxhe Hello. Thanks for you reply. I still have a couple of issues regarding measuring battery voltage.

  1. I have run your example code and found out that the example is not able to measure the battery voltage while the USB is plugged in. Why is that the case? Does the BAT_ADC suppose to measure Voltage across the battery terminals? If that is the case, it should be able to measure the voltage even when the USB is connected. When I connect the USB, the voltage accross the battery terminals goes up by about 100mV indicating charging progress.

  2. When the USB is disconnected, the measured Battery voltage displayed on the display is 3400mV. The actual Voltage measured using digital multimeter is 3600mV. 200mV is quite a large error.

lewisxhe commented 8 months ago

@krupis

  1. When USB is plugged in, the BAT voltage is taken over by the TP4065 charging IC, so the voltage tested at this time is meaningless.
  2. The ADC of ESP32 is not very accurate, and in the example, I only read the data once and did not do any data processing. In actual circumstances, the internal voltage reference of ESP32 is affected by the external power supply, so it cannot be accurately obtained. Voltage data can only be used as a reference.
krupis commented 8 months ago

@lewisxhe Wouldn't it be better and more informative to measure the battery directly across its terminals? This would allow us to measure its voltage even when the USB is plugged in, right?

I dont really understand why would it be done any other way.

nvx commented 8 months ago
  1. When USB is plugged in, the BAT voltage is taken over by the TP4065 charging IC, so the voltage tested at this time is meaningless.

According to the schematic the ADC is measuring the voltage directly (via a voltage divider), so I'm a little confused why this isn't showing the battery terminal voltage still - even if the TP4065 chip is charging the battery, it should still display the charging voltage (which may be higher than the battery voltage once the charger is disconnected, but still match what a DMM shows when measured across the terminals)

  1. The ADC of ESP32 is not very accurate, and in the example, I only read the data once and did not do any data processing. In actual circumstances, the internal voltage reference of ESP32 is affected by the external power supply, so it cannot be accurately obtained. Voltage data can only be used as a reference.

Even reading it continuously results in similar errors though. Looking at the schematic the ESP32 voltage reference should be regulated though. Is the schematic accurate? Are the board designs available so we can cross reference it against the schematic to confirm if there's any discrepancies between the two which would allow for compensating in software if discovered.

lewisxhe commented 8 months ago

@lewisxhe Wouldn't it be better and more informative to measure the battery directly across its terminals? This would allow us to measure its voltage even when the USB is plugged in, right?

I dont really understand why would it be done any other way.

There's nothing I can do about it, I'm not the one who designed this circuit.

lewisxhe commented 8 months ago

image

@nvx This is the current path as I understand it.

nvx commented 8 months ago

image

@nvx This is the current path as I understand it.

Good catch, but wouldn't that completely bypass the charging circuitry and overcharge the battery which would be quite dangerous if we're not missing something here?

lewisxhe commented 8 months ago

image Oh! I overlooked something.

krupis commented 8 months ago

I still cannot wrap my head around why we would not be able to measure the battery voltage when the USB is plugged in. It should measure identically to what the DMM measures across the battery terminals.

krupis commented 8 months ago

I have now started to understand what is the problem. The name of the ADC pin BAT_ADC is very misleading because its not actually measuring the voltage across battery terminals but instead it is just measuring the supply voltage (measuring Battery if USB is not plugged in and when the USB is plugged in it measured 5V).

This in my opinion is not correct for Battery powered application and VUSB_ADC and BAT_ADC should be seperated. Currently, there is no way to know if the battery is charging or not as there is no possible way to measure the battery voltage using ADC when it is being charged.

nvx commented 8 months ago

image Oh! I overlooked something.

Except from what I can see that MOSFET would be turned on, and when turned on it will happily conduct in both directions unless I'm missing something

github-actions[bot] commented 3 months ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 2 months ago

This issue was closed because it has been inactive for 14 days since being marked as stale.