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

Updated ADC Implementation to support ESP-IDF 5.0 #89

Merged
merged 7 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
### C ###
# SDK Config files
sdkconfig

# Build folder
build/

Expand Down
13 changes: 5 additions & 8 deletions examples/lsa/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@ static const char* TAG = "LSA_READINGS";
void app_main(void)
{
// enable line sensor
ESP_ERROR_CHECK(enable_line_sensor());

//Union containing line sensor readings
adc_handle_t adc_handle;
ESP_ERROR_CHECK(enable_line_sensor(&adc_handle));
line_sensor_array line_sensor_readings;

while(1)
while (1)
{
// get line sensor readings
line_sensor_readings = read_line_sensor();
line_sensor_readings = read_line_sensor(adc_handle);
for(int i = 0; i < 5; i++)
{
// constrain lsa readings between BLACK_MARGIN and WHITE_MARGIN
Expand All @@ -58,6 +56,5 @@ void app_main(void)

// log final lsa readings
ESP_LOGI(TAG, "LSA_0: %d \t LSA_1: %d \t LSA_2: %d \t LSA_3: %d \t LSA_4: %d",line_sensor_readings.adc_reading[0], line_sensor_readings.adc_reading[1], line_sensor_readings.adc_reading[2], line_sensor_readings.adc_reading[3], line_sensor_readings.adc_reading[4]);

}
}
}
40 changes: 21 additions & 19 deletions include/adc.h
RISHI27-dot marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
#include <stdio.h>
#include <stdlib.h>

#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
Expand All @@ -39,36 +40,37 @@
#include "esp_err.h"
#include "pin_defs.h"

#define DEFAULT_VREF 1100
#define ADC_ATTEN ADC_ATTEN_DB_11
#define ADC_BITWIDTH_LEN ADC_BITWIDTH_12

/**
* @brief Configure width and attenuation of ADC 1
* @brief Structure representing an ADC object.
*
* @return esp_err_t - returns ESP_OK if 11dB attenuation and 12 bit width configured to ADC 1, else it returns ESP_ERR_INVALID_ARG.
**/
esp_err_t config_adc1();
* This structure holds the handles and calibration data for an ADC.
*/
typedef struct
{
adc_oneshot_unit_handle_t adc1_handle; /**< Handle for ADC1 oneshot unit. */
adc_cali_handle_t adc1_cali_handle[5]; /**< Array of calibration handles for ADC1. */
bool do_calib[5]; /**< Array indicating whether calibration should be performed for each channel. */
} adc_obj_t;

/**
* @brief Characterize ADC 1 using either Vref or Two Point
*
* @return esp_err_t
**/
esp_err_t characterize_adc1();
typedef adc_obj_t *adc_handle_t;

/**
* @brief call function config_adc1() and characterize_adc1().
*
* @return esp_err_t - returns ESP_OK if Configuration and Characterization of adc1 is successful, else it returns ESP_ERR_INVALID_ARG.
**/
esp_err_t enable_adc1();
esp_err_t enable_adc1(adc_obj_t** adc_obj);

/**
* @brief Read raw adc value of given adc pin.
*
* @param adc_pin One of the GPIO pin to which LSA is connected (36/39/35/34)
* @brief Reads the adc value from the GPIO(channel) specified.
*
* @return esp_err_t -returns raw reading of adc pin if lsa pin is passed to function, else it returns ESP_ERR_INVALID_ARG.
* @param adc_handle_t adc_handle - pointer to adc object.
* @param int gpio - gpio pin number of the channel to be read.
* @return int - returns the adc value read from the channel.
**/
int read_adc(int adc_pin);
int read_adc(adc_handle_t adc_handle, int gpio);
RISHI27-dot marked this conversation as resolved.
Show resolved Hide resolved

#endif
4 changes: 2 additions & 2 deletions include/lsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ typedef union line_sensor_array

* @return esp_err_t i.e it shows if adc is initialised successfully or not
**/
esp_err_t enable_line_sensor();
esp_err_t enable_line_sensor(adc_handle_t *adc_handle);

/**
* @brief Get multisampled line sensor array readings
Expand All @@ -62,6 +62,6 @@ esp_err_t enable_line_sensor();
* @return Returns a pointer to a struct that contains multisampled adc readings
for all the pins specified in lsa_pins array
**/
line_sensor_array read_line_sensor();
line_sensor_array read_line_sensor(adc_handle_t adc_handle);

#endif
158 changes: 108 additions & 50 deletions src/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,82 +24,140 @@

#include "adc.h"

static const char *TAG_ADC = "adc";
static const char *TAG = "adc";
static const int adc_io[5] = {LSA_A0, LSA_A1, LSA_A2, LSA_A3, LSA_A4};

esp_err_t config_adc1()
esp_err_t config_adc1(adc_obj_t *adc_obj)
{
// Configure ADC to 12 bit width
CHECK(adc1_config_width(ADC_WIDTH_BIT_12));

// Configure ADC to 11dB attenuation
CHECK(adc1_config_channel_atten(ADC_CHANNEL_4, ADC_ATTEN_DB_11));
CHECK(adc1_config_channel_atten(ADC_CHANNEL_7, ADC_ATTEN_DB_11));
CHECK(adc1_config_channel_atten(ADC_CHANNEL_6, ADC_ATTEN_DB_11));
CHECK(adc1_config_channel_atten(ADC_CHANNEL_3, ADC_ATTEN_DB_11));
CHECK(adc1_config_channel_atten(ADC_CHANNEL_0, ADC_ATTEN_DB_11));

ESP_LOGI(TAG_ADC, "Configured ADC_1 to 12 Bit and 11dB attenuation");
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_LEN,
.atten = ADC_ATTEN,
RISHI27-dot marked this conversation as resolved.
Show resolved Hide resolved
};
// Assign channels to each io in adc_io
for (int i = 0; i < sizeof(adc_io) / sizeof(adc_io[0]); i++)
{
adc_channel_t channel;
adc_unit_t unit;
ESP_ERROR_CHECK(adc_oneshot_io_to_channel(adc_io[i], &unit, &channel));
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_obj->adc1_handle, channel, &config));
}

return ESP_OK;
}

esp_err_t characterize_adc1()
static bool adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle)
{
esp_adc_cal_characteristics_t adc_chars;
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, DEFAULT_VREF, &adc_chars);
adc_cali_handle_t handle = NULL;
esp_err_t ret = ESP_FAIL;
bool calibrated = false;

if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP)
{
ESP_LOGI(TAG_ADC, "eFuse Two Point: Supported");
ESP_LOGI(TAG_ADC, "Characterized using Two Point Value");
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
if (!calibrated) {
ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
adc_cali_curve_fitting_config_t cali_config = {
.unit_id = unit,
.chan = channel,
.atten = atten,
.bitwidth = ADC_BITWIDTH_LEN,
};
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
if (ret == ESP_OK) {
calibrated = true;
}
}
else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF)
{
ESP_LOGI(TAG_ADC, "eFuse Vref: Supported");
ESP_LOGI(TAG_ADC, "Characterized using eFuse Vref");
#endif

#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
if (!calibrated) {
ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
adc_cali_line_fitting_config_t cali_config = {
.unit_id = unit,
.atten = atten,
.bitwidth = ADC_BITWIDTH_LEN,
};
ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
if (ret == ESP_OK) {
calibrated = true;
}
}
else
#endif

*out_handle = handle;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Calibration Success");
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
} else {
ESP_LOGE(TAG, "Invalid arg or no memory");
}

return calibrated;
}

esp_err_t calib_init(adc_obj_t *adc_obj)
{
for (int i = 0; i < sizeof(adc_io) / sizeof(adc_io[0]); i++)
{
ESP_LOGI(TAG_ADC, "Characterized using Default Vref");
adc_channel_t channel;
adc_unit_t unit;
ESP_ERROR_CHECK(adc_oneshot_io_to_channel(adc_io[i], &unit, &channel));
adc_obj->do_calib[i] = adc_calibration_init(ADC_UNIT_1, channel, ADC_ATTEN, &adc_obj->adc1_cali_handle[i]);
RISHI27-dot marked this conversation as resolved.
Show resolved Hide resolved
}
return ESP_OK;
}

esp_err_t enable_adc1()
esp_err_t enable_adc1(adc_obj_t** adc_obj)
{
CHECK(config_adc1());
CHECK(characterize_adc1());

ESP_LOGI(TAG_ADC, "Configured and Characterized adc 1");
adc_obj_t *ret = NULL;
ret = calloc(1, sizeof(adc_obj_t));
ESP_ERROR_CHECK(ret == NULL ? ESP_ERR_NO_MEM : ESP_OK);
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &ret->adc1_handle));
config_adc1(ret);
calib_init(ret);
*adc_obj = ret;

return ESP_OK;
}

int read_adc(int adc_pin)
int read_adc(adc_handle_t adc_handle, int gpio)
{
if (adc_pin == LSA_A0)
{
return adc1_get_raw(ADC_CHANNEL_4);
}
else if (adc_pin == LSA_A1)
{
return adc1_get_raw(ADC_CHANNEL_7);
}
else if (adc_pin == LSA_A2)
{
return adc1_get_raw(ADC_CHANNEL_6);
}
else if (adc_pin == LSA_A3)
int adc_reading = 0;
int voltage = 0;
adc_channel_t channel;
adc_unit_t unit;
ESP_ERROR_CHECK(adc_oneshot_io_to_channel(gpio, &unit, &channel));
ESP_ERROR_CHECK(adc_oneshot_read(adc_handle->adc1_handle, channel, &adc_reading));
int arr_loc = 0;
switch (gpio)
{
return adc1_get_raw(ADC_CHANNEL_3);
case LSA_A0:
arr_loc = 0;
break;
case LSA_A1:
arr_loc = 1;
break;
case LSA_A2:
arr_loc = 2;
break;
case LSA_A3:
arr_loc = 3;
break;
case LSA_A4:
arr_loc = 4;
break;
default:
break;
}
else if (adc_pin == LSA_A4)
if (adc_handle->do_calib[arr_loc])
{
return adc1_get_raw(ADC_CHANNEL_0);
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc_handle->adc1_cali_handle[arr_loc], adc_reading, &voltage));
return voltage;
}
else
{
ESP_LOGE(TAG_ADC, "Invalid adc pin");
return ESP_FAIL;
return adc_reading;
}
}
10 changes: 5 additions & 5 deletions src/lsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@

static const int line_sensor_pins[5] = {LSA_A0, LSA_A1, LSA_A2, LSA_A3, LSA_A4};

esp_err_t enable_line_sensor()
esp_err_t enable_line_sensor(adc_handle_t *adc_handle)
{
esp_err_t err = enable_adc1(line_sensor_pins);
return err;
ESP_ERROR_CHECK(enable_adc1(adc_handle));
return ESP_OK;
}

line_sensor_array read_line_sensor()
line_sensor_array read_line_sensor(adc_handle_t adc_handle)
{
line_sensor_array line_sensor_readings;

Expand All @@ -45,7 +45,7 @@ line_sensor_array read_line_sensor()
{
for (int j = 0; j < 5; j++)
{
line_sensor_readings.adc_reading[j] = line_sensor_readings.adc_reading[j] + read_adc(line_sensor_pins[j]);
line_sensor_readings.adc_reading[j] = line_sensor_readings.adc_reading[j] + read_adc(adc_handle, line_sensor_pins[j]);
}
}

Expand Down