Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32 ADC Raw to Voltage Conversion problem #72983

Open
c3pStefano opened this issue May 18, 2024 · 1 comment
Open

ESP32 ADC Raw to Voltage Conversion problem #72983

c3pStefano opened this issue May 18, 2024 · 1 comment
Assignees
Labels
area: ADC Analog-to-Digital Converter (ADC) bug The issue is a bug, or the PR is fixing a bug platform: ESP32 Espressif ESP32 priority: low Low impact/importance bug

Comments

@c3pStefano
Copy link

Hello everyone,

I recently encountered a problem while working on a Zephyr project with an ESP32. Specifically, the issue arose when trying to convert raw ADC readings to voltage values. The problem occurs due to an unexpected jump in the scaled ADC values. Here’s the context and details:

Problem Description

In my code, I use the following function to convert raw ADC readings to voltage:
From here zephyr\drivers\adc\adc_esp32.c will be called
modules\hal\espressif\zephyr\esp32\src\esp_adc_cal\esp_adc_cal.c

uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) {
    assert(chars != NULL);
    printk("ADC before= %d\n", adc_reading);

    // Scale adc_reading if not 12 bits wide
    adc_reading = (adc_reading << (ADC_WIDTH_BIT_12 - chars->bit_width));
    if (adc_reading > ADC_12_BIT_RES - 1) {
        adc_reading = ADC_12_BIT_RES - 1;    // Set to 12bit res max
    }
    printk("ADC nachher = %d\n", adc_reading);

    if (LUT_ENABLED && (chars->atten == ADC_ATTEN_DB_11) && (adc_reading >= LUT_LOW_THRESH)) {
        uint32_t lut_voltage = calculate_voltage_lut(adc_reading, chars->vref, chars->low_curve, chars->high_curve);
        printk("ADC Reading: %d, Voltage: %d\n", adc_reading, lut_voltage);

        if (adc_reading <= LUT_HIGH_THRESH) {
            uint32_t linear_voltage = calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
            return interpolate_two_points(linear_voltage, lut_voltage, LUT_ADC_STEP_SIZE, (adc_reading - LUT_LOW_THRESH));
        } else {
            return lut_voltage;
        }
    } else {
        return calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
    }
}

The problem appears when chars->bit_width is set to 3, causing large jumps in the scaled values due to significant bit shifts.

Analysis

When chars->bit_width is 3, the scaling factor becomes (12 - 3) = 9 bits, leading to significant jumps. For example:

  • If adc_reading is 7 (max for 3 bits), the calculation is 7 << 9 = 3584.

Such a large jump can cause instability and unexpected behavior in the voltage readings.

My Code

\src\main.c

#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(aqua, 1);

#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
#error "No suitable devicetree overlay specified"
#endif

static const struct adc_dt_spec adc_channel = ADC_DT_SPEC_GET(DT_PATH(zephyr_user));

int main(void)
{
    printk("Starte Programm\n");
    int32_t val_mv;
    int err;

    if (!adc_is_ready_dt(&adc_channel)) {
        LOG_ERR("ADC controller device %s not ready", adc_channel.dev->name);
        return 0;
    } else {
        printk("ADC ready\n");
    }

    err = adc_channel_setup_dt(&adc_channel);
    if (err < 0) {
        LOG_ERR("Could not setup channel #%d (%d)", 0, err);
        return 0;
    } else {
        printk("Channel setup erfolgreich\n");
    }

    int16_t buf;
    struct adc_sequence sequence = {
        .buffer = &buf,
        /* buffer size in bytes, not number of samples */
        .buffer_size = sizeof(buf),
        // Optional
        //.calibrate = true,
    };

    err = adc_sequence_init_dt(&adc_channel, &sequence);
    if (err < 0) {
        LOG_ERR("Could not initialize sequence");
        return 0;
    } else {
        printk("Sequence setup erfolgreich\n");
    }

    while (1) {
        err = adc_read(adc_channel.dev, &sequence);
        if (err < 0) {
            LOG_ERR("Could not read (%d)", err);
            continue;
        }
        printk("Unit1 = %d\n", buf);

        // Unkalibrierter Wert direkt ausgeben
        int32_t cal = buf;
        printk("Cal = %d\n", cal);

        // Optional: Zusätzliche Verarbeitung für Kalibrierung hinzufügen
        // val_mv = adc_raw_to_millivolts(adc_channel, cal); // Falls verfügbar

        printk(" = %d\n", cal);

        k_sleep(K_MSEC(1000));
    }
    return 0;
}

\boards\esp32_devkitc_wroom_procpu.overlay


/ {
	zephyr,user {
		/* adjust channel number according to pinmux in board.dts */
		io-channels = <&adc0 6>;
	};
};

&adc0 {
	status = "okay";
	#address-cells = <1>;
	#size-cells = <0>;
    compatible = "espressif,esp32-adc";
	channel@6 {
		reg = <6>;
		zephyr,gain = "ADC_GAIN_1";
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,resolution = <12>;
	};
};
CONFIG_I2C=y
CONFIG_DISPLAY=y
CONFIG_SSD1306=y
CONFIG_SSD1306_DEFAULT_CONTRAST=128
CONFIG_LOG=y
CONFIG_CFB_LOG_LEVEL_DBG=y
CONFIG_CHARACTER_FRAMEBUFFER=y
CONFIG_SENSOR=y
CONFIG_ADC=y
CONFIG_LOG_OVERRIDE_LEVEL=1

Environment Setup

  • Operating System: Windows 11
  • Zephyr Version: 3.6.99
  • CMake Version: 3.29.2
  • Python Version: 3.10.11 (virtual environment)
  • West Tool Version: 1.2.0
  • Zephyr SDK: 0.16.6 installed at C:/Users/name/zephyr-sdk-0.16.6
  • Compiler: GCC 12.2.0
  • Esptool: esptool.py v4.7.0
  • Board Configuration: esp32_devkitc_wroom/esp32/procpu

Best regards,
Stefan

@c3pStefano c3pStefano added the bug The issue is a bug, or the PR is fixing a bug label May 18, 2024
Copy link

Hi @c3pStefano! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

@henrikbrixandersen henrikbrixandersen added the platform: ESP32 Espressif ESP32 label May 18, 2024
@henrikbrixandersen henrikbrixandersen added the area: ADC Analog-to-Digital Converter (ADC) label May 18, 2024
@nashif nashif added the priority: low Low impact/importance bug label May 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ADC Analog-to-Digital Converter (ADC) bug The issue is a bug, or the PR is fixing a bug platform: ESP32 Espressif ESP32 priority: low Low impact/importance bug
Projects
None yet
Development

No branches or pull requests

4 participants