Merge branch 'feature/adc_calibration' into 'master'

esp_adc_cal component

See merge request !1084
This commit is contained in:
Jeroen Domburg 2017-08-30 10:00:19 +08:00
commit a1b5813049
12 changed files with 542 additions and 47 deletions

View file

@ -21,6 +21,7 @@ extern "C" {
#include <stdint.h>
#include "esp_err.h"
#include "driver/gpio.h"
typedef enum {
ADC_ATTEN_0db = 0, /*!<The input voltage of ADC will be reduced to about 1/1 */
@ -66,7 +67,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
*
* @note This function also configures the input GPIO pin mux to
* connect it to the ADC1 channel. It must be called before calling
* adc1_get_voltage() for this channel.
* adc1_get_raw() for this channel.
*
* The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage,
* usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.
@ -107,13 +108,22 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten);
* - -1: Parameter error
* - Other: ADC1 channel reading.
*/
int adc1_get_voltage(adc1_channel_t channel);
int adc1_get_raw(adc1_channel_t channel);
/** @cond */ //Doxygen command to hide deprecated function from API Reference
/*
* @deprecated This function returns an ADC1 reading but is deprecated due to
* a misleading name and has been changed to directly call the new function.
* Use the new function adc1_get_raw() instead
*/
int adc1_get_voltage(adc1_channel_t channel) __attribute__((deprecated));
/** @endcond */
/**
* @brief Configure ADC1 to be usable by the ULP
*
* This function reconfigures ADC1 to be controlled by the ULP.
* Effect of this function can be reverted using adc1_get_voltage function.
* Effect of this function can be reverted using adc1_get_raw function.
*
* Note that adc1_config_channel_atten, adc1_config_width functions need
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
@ -136,6 +146,22 @@ void adc1_ulp_enable();
*/
int hall_sensor_read();
/**
* @brief Output ADC2 reference voltage to gpio 25 or 26 or 27
*
* This function utilizes the testing mux exclusive to ADC 2 to route the
* reference voltage one of ADC2's channels. Supported gpios are gpios
* 25, 26, and 27. This refernce voltage can be manually read from the pin
* and used in the esp_adc_cal component.
*
* @param[in] gpio GPIO number (gpios 25,26,27 supported)
*
* @return
* - ESP_OK: v_ref successfully routed to selected gpio
* - ESP_ERR_INVALID_ARG: Unsupported gpio
*/
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio);
#ifdef __cplusplus
}
#endif

View file

@ -945,7 +945,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
return ESP_OK;
}
int adc1_get_voltage(adc1_channel_t channel)
int adc1_get_raw(adc1_channel_t channel)
{
uint16_t adc_value;
@ -975,6 +975,11 @@ int adc1_get_voltage(adc1_channel_t channel)
return adc_value;
}
int adc1_get_voltage(adc1_channel_t channel) //Deprecated. Use adc1_get_raw() instead
{
return adc1_get_raw(channel);
}
void adc1_ulp_enable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
@ -989,6 +994,43 @@ void adc1_ulp_enable(void)
portEXIT_CRITICAL(&rtc_spinlock);
}
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
{
int channel;
if(gpio == GPIO_NUM_25){
channel = 8; //Channel 8 bit
}else if (gpio == GPIO_NUM_26){
channel = 9; //Channel 9 bit
}else if (gpio == GPIO_NUM_27){
channel = 7; //Channel 7 bit
}else{
return ESP_ERR_INVALID_ARG;
}
//Configure RTC gpio
rtc_gpio_init(gpio);
rtc_gpio_output_disable(gpio);
rtc_gpio_input_disable(gpio);
rtc_gpio_pullup_dis(gpio);
rtc_gpio_pulldown_dis(gpio);
SET_PERI_REG_BITS(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0, RTC_CNTL_DBG_ATTEN_S); //Check DBG effect outside sleep mode
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 1, RTC_CNTL_DTEST_RTC_S); //Config test mux to route v_ref to ADC2 Channels
//set ent
SET_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC_M);
//set sar2_en_test
SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST_M);
//force fsm
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); //Select power source of ADC
//set sar2 en force
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //Pad bitmap controlled by SW
//set en_pad for channels 7,8,9 (bits 0x380)
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, 1<<channel, SENS_SAR2_EN_PAD_S);
return ESP_OK;
}
/*---------------------------------------------------------------
DAC
---------------------------------------------------------------*/
@ -1141,11 +1183,11 @@ static int hall_sensor_get_value() //hall sensor without LNA
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_XPD_HALL); // xpd hall
SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE_M); // phase force
CLEAR_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE); // hall phase
Sens_Vp0 = adc1_get_voltage(ADC1_CHANNEL_0);
Sens_Vn0 = adc1_get_voltage(ADC1_CHANNEL_3);
Sens_Vp0 = adc1_get_raw(ADC1_CHANNEL_0);
Sens_Vn0 = adc1_get_raw(ADC1_CHANNEL_3);
SET_PERI_REG_MASK(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE);
Sens_Vp1 = adc1_get_voltage(ADC1_CHANNEL_0);
Sens_Vn1 = adc1_get_voltage(ADC1_CHANNEL_3);
Sens_Vp1 = adc1_get_raw(ADC1_CHANNEL_0);
Sens_Vn1 = adc1_get_raw(ADC1_CHANNEL_3);
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE);
CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE);

View file

@ -0,0 +1,5 @@
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := include

View file

@ -0,0 +1,111 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "driver/adc.h"
#include "esp_adc_cal.h"
static const esp_adc_cal_lookup_table_t *table_ptrs[4] = {&esp_adc_cal_table_atten_0,
&esp_adc_cal_table_atten_1,
&esp_adc_cal_table_atten_2,
&esp_adc_cal_table_atten_3};
uint32_t get_adc_vref_from_efuse()
{
//TODO: Replaced with read to eFuse once ATE confirms location of 5 bits
return 0;
}
void esp_adc_cal_get_characteristics(uint32_t v_ref,
adc_atten_t atten,
adc_bits_width_t bit_width,
esp_adc_cal_characteristics_t *chars)
{
chars->v_ref = v_ref;
chars->table = table_ptrs[atten];
chars->bit_width = bit_width;
if (v_ref >= ADC_CAL_LOW_V_REF) {
chars->gain = ((chars->v_ref - ADC_CAL_LOW_V_REF)
* chars->table->gain_m)
+ chars->table->gain_c;
chars->offset = (((chars->v_ref - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ chars->table->offset_c
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2))
>> ADC_CAL_OFFSET_SCALE; //Bit shift to cancel 2^10 multiplier
chars->ideal_offset = (((ADC_CAL_IDEAL_V_REF - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ chars->table->offset_c
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
>> ADC_CAL_OFFSET_SCALE;
} else { //For case where v_ref is smaller than low bound resulting in negative
chars->gain = chars->table->gain_c
- ((ADC_CAL_LOW_V_REF - chars->v_ref)
* chars->table->gain_m);
chars->offset = (chars->table->offset_c
- ((chars->v_ref - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
>> ADC_CAL_OFFSET_SCALE; //Bit shift to cancel 2^10 multiplier
chars->ideal_offset = (chars->table->offset_c
- ((ADC_CAL_IDEAL_V_REF - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
>> ADC_CAL_OFFSET_SCALE;
}
}
static uint32_t esp_adc_cal_interpolate_round(uint32_t lower, uint32_t upper,
uint32_t step, uint32_t point)
{
//Interpolate 'point' between 'lower' and 'upper' seperated by 'step'
return ((lower * step) - (lower * point) + (upper * point) + (step / 2)) / step;
}
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc,
const esp_adc_cal_characteristics_t *chars)
{
//Scale ADC to 12 bit width (0 to 4095)
adc <<= (ADC_WIDTH_12Bit - chars->bit_width);
uint32_t i = (adc >> chars->table->bit_shift); //find index for lut voltages
//Refernce LUT to obtain voltage using index
uint32_t voltage = esp_adc_cal_interpolate_round(chars->table->voltage[i],
chars->table->voltage[i + 1],
(1 << chars->table->bit_shift),
adc - (i << chars->table->bit_shift));
/*
* Apply Gain, scaling(bit shift) and offset to interpolated voltage
* v_true = (((v_id - off_id)*gain)*scaling) + off_true
*/
if (voltage > chars->ideal_offset) {
voltage = (voltage - chars->ideal_offset) * chars->gain;
voltage += (1 << ADC_CAL_GAIN_SCALE) / 2; //For rounding when scaled
voltage >>= ADC_CAL_GAIN_SCALE;
voltage += chars->offset;
} else { //For case where voltage is less than ideal offset leading to negative value
voltage = ((chars->ideal_offset - voltage) * chars->gain);
voltage += (1 << ADC_CAL_GAIN_SCALE) / 2; //For rounding when scaled
voltage >>= ADC_CAL_GAIN_SCALE;
voltage = chars->offset - voltage;
}
return voltage;
}
uint32_t adc1_to_voltage(adc1_channel_t channel, const esp_adc_cal_characteristics_t *chars)
{
return esp_adc_cal_raw_to_voltage((uint32_t)adc1_get_raw(channel), chars);
}

View file

@ -0,0 +1,96 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_adc_cal.h"
/**
* Mean error of 219 modules: 3.756418mV
* Max error of 219 modules: 26.314087mV
* Mean of max errors of 219 modules: 7.387282mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_0 = {
.gain_m = 56,
.gain_c = 59928,
.offset_m = 91,
.offset_c = 52798,
.bit_shift = 7,
.voltage = {
54, 90, 120, 150, 180, 209, 241, 271,
301, 330, 360, 391, 421, 450, 480, 511,
541, 571, 601, 630, 660, 690, 720, 750,
780, 809, 839, 870, 900, 929, 959, 988,
1018
}
};
/**
* Mean error of 219 modules: 4.952441mV
* Max error of 219 modules: 38.235321mV
* Mean of max errors of 219 modules: 9.718749mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_1 = {
.gain_m = 57,
.gain_c = 59834,
.offset_m = 108,
.offset_c = 54733,
.bit_shift = 7,
.voltage = {
60, 102, 143, 184, 223, 262, 303, 343,
383, 423, 463, 503, 543, 583, 623, 663,
703, 742, 782, 823, 862, 901, 942, 981,
1022, 1060, 1101, 1141, 1180, 1219, 1259, 1298,
1338
}
};
/**
* Mean error of 219 modules: 6.793558mV
* Max error of 219 modules: 51.435440mV
* Mean of max errors of 219 modules: 13.083121mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_2 = {
.gain_m = 56,
.gain_c = 59927,
.offset_m = 154,
.offset_c = 71995,
.bit_shift = 7,
.voltage = {
82, 138, 194, 250, 305, 360, 417, 473,
529, 584, 639, 696, 751, 806, 861, 917,
971, 1026, 1081, 1136, 1192, 1246, 1301, 1356,
1411, 1466, 1522, 1577, 1632, 1687, 1743, 1799,
1855
}
};
/**
* Mean error of 219 modules: 13.149460mV
* Max error of 219 modules: 97.102951mV
* Mean of max errors of 219 modules: 35.538924mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_3 = {
.gain_m = 33,
.gain_c = 62214,
.offset_m = 610,
.offset_c = 108422,
.bit_shift = 7,
.voltage = {
110, 221, 325, 430, 534, 637, 741, 845,
947, 1049, 1153, 1256, 1358, 1461, 1565, 1670,
1774, 1878, 1983, 2088, 2192, 2293, 2393, 2490,
2580, 2665, 2746, 2820, 2885, 2947, 3007, 3060,
3107
}
};

View file

@ -0,0 +1,141 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "driver/adc.h"
/** @cond */
#define ADC_CAL_GAIN_SCALE 16
#define ADC_CAL_OFFSET_SCALE 10
#define ADC_CAL_IDEAL_V_REF 1100 //In mV
#define ADC_CAL_LOW_V_REF 1000
#define ADC_CAL_HIGH_V_REF 1200
#define ADC_CAL_MIN 0
#define ADC_CAL_MAX 4095
/** @endcond */
/**
* @brief Structure storing Lookup Table
*
* The Lookup Tables (LUT) of a given attenuation contains 33 equally spaced
* points. The Gain and Offset curves are used to find the appopriate gain and
* offset factor given a reference voltage v_ref.
*
* @note A seperate LUT is provided for each attenuation and are defined in
* esp_adc_cal_lookup_tables.c
*/
typedef struct {
uint32_t gain_m; /**<Gradient of Gain Curve */
uint32_t gain_c; /**<Offset of Gain Curve */
uint32_t offset_m; /**<Gradient of Offset Curve */
uint32_t offset_c; /**<Offset of Offset Curve */
uint32_t bit_shift; /**<Bit shift used find corresponding LUT points
given an ADC reading*/
uint32_t voltage[]; /**<Array of voltages in mV representing the
ADC-Voltage curve */
} esp_adc_cal_lookup_table_t;
/**
* @brief Structure storing ADC characteristics of given v_ref
*
* The ADC Characteristics structure stores the gain and offset factors of an
* ESP32 module's ADC. These factors are calculated using the reference voltage,
* and the Gain and Offset curves provided in the lookup tables.
*
* @note Call esp_adc_cal_get_characteristics() to initialize the structure
*
*/
typedef struct {
uint32_t v_ref; /**<Reference Voltage of current ESP32 Module in mV*/
uint32_t gain; /**<Scaling factor used to correct LUT voltages to
current v_ref. Bit shifted by << ADC_CAL_GAIN_SCALE
for uint32 arithmetic */
uint32_t offset; /**<Offset in mV used to correct LUT Voltages to current v_ref */
uint32_t ideal_offset; /**<Offset in mV at the ideal reference voltage */
adc_bits_width_t bit_width; /**<Bit width of ADC e.g. ADC_WIDTH_12Bit */
const esp_adc_cal_lookup_table_t *table; /**<Pointer to LUT */
} esp_adc_cal_characteristics_t;
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_0; /**<LUT for atten0 */
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_1; /**<LUT for atten1 */
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_2; /**<LUT for atten2 */
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_3; /**<LUT for atten3 */
/**
* @brief Calculate characteristics of ADC
*
* This function will calculate the gain and offset factors based on the
* reference voltage parameter and the Gain and Offset curve provided in the LUT.
*
* @note reference voltage of the ADCs can be routed to GPIO using
* adc2_vref_to_gpio() from the ADC driver
*
* @note The LUT members have been bit shifted by ADC_CAL_GAIN_SCALE or
* ADC_CAL_OFFSET_SCALE to make them uint32_t compatible. This bit shifting will
* accounted for in this function
*
* @param[in] v_ref true reference voltage of the ADC in mV (1000 to 1200mV). Nominal
* value for reference voltage is 1100mV.
* @param[in] atten attenuation setting used to select the corresponding lookup table
* @param[in] bit_width bit width of ADC
* @param[out] chars pointer to structure used to store ADC characteristics of module
*/
void esp_adc_cal_get_characteristics(uint32_t v_ref,
adc_atten_t atten,
adc_bits_width_t bit_width,
esp_adc_cal_characteristics_t *chars);
/**
* @brief Convert raw ADC reading to voltage in mV
*
* This function converts a raw ADC reading to a voltage in mV. This conversion
* is based on the ADC's characteristics. The raw ADC reading is referenced
* against the LUT (pointed to inside characteristics struct) to obtain a voltage.
* Gain and offset factors are then applied to the voltage in order to obtain
* the final result.
*
* @param[in] adc ADC reading (different bit widths will be handled)
* @param[in] chars pointer to structure containing ADC characteristics of
* the module. Structure also contains pointer to the
* corresponding LUT
*
* @return Calculated voltage in mV
*
* @note characteristics structure must be initialized using
* esp_adc_cal_get_characteristics() before this function is used
*/
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc,
const esp_adc_cal_characteristics_t *chars);
/**
* @brief Reads ADC1 and returns voltage in mV
*
* This function reads the ADC1 using adc1_get_raw() to obtain a raw ADC
* reading. The reading is then converted into a voltage value using
* esp_adc_cal_raw_to_voltage().
*
* @param[in] channel Channel of ADC1 to measure
* @param[in] chars Pointer to ADC characteristics struct
*
* @return voltage Calculated voltage in mV
*
* @note ADC must be initialized using adc1_config_width() and
* adc1_config_channel_atten() before this function is used
*
* @note characteristics structure must be initialized using
* esp_adc_cal_get_characteristics() before this function is used
*/
uint32_t adc1_to_voltage(adc1_channel_t channel, const esp_adc_cal_characteristics_t *chars);

View file

@ -74,6 +74,7 @@ INPUT = \
../components/driver/include/driver/timer.h \
../components/driver/include/driver/touch_pad.h \
../components/driver/include/driver/uart.h \
../components/esp_adc_cal/include/esp_adc_cal.h \
##
## Protocols - API Reference
##

View file

@ -9,13 +9,15 @@ analog signals.
The ADC driver API currently only supports ADC1 (9 channels, attached to GPIOs 32-39).
Taking an ADC reading involves configuring the ADC with the desired precision and attentuation settings, and then calling adc1_get_voltage() to read the channel.
Taking an ADC reading involves configuring the ADC with the desired precision and attentuation settings, and then calling adc1_get_raw() to read the channel.
It is also possible to read the internal hall effect sensor via ADC1.
Application Example
-------------------
A full example using the ADC driver and the esp_adc_cal is available in esp-idf: :example:`peripherals/adc`
Reading voltage on ADC1 channel 0 (GPIO 36)::
#include <driver/adc.h>
@ -24,7 +26,7 @@ Reading voltage on ADC1 channel 0 (GPIO 36)::
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_0,ADC_ATTEN_0db);
int val = adc1_get_voltage(ADC1_CHANNEL_0);
int val = adc1_get_raw(ADC1_CHANNEL_0);
Reading the internal hall effect sensor::
@ -43,3 +45,58 @@ API Reference
.. include:: /_build/inc/adc.inc
ADC Calibration
===============
Overview
--------
The esp_adc_cal API provides functions to correct for differences in measured voltages caused by non-ideal ADC reference voltages in ESP32s. The ideal ADC reference voltage is 1100mV however the reference voltage of different ESP32s can range from 1000mV to 1200mV.
Correcting the measured voltage using the esp_adc_cal API involves referencing a lookup table of voltages. The voltage obtained from the lookup table is the scaled and shifted by a gain and offset factor that is based on the ADC's reference voltage.
The reference voltage of the ADCs can be routed to certain GPIOs and measured manually using the ADC drivers adc2_vref_to_gpio() function.
Application Example
-------------------
Reading the ADC and obtaining a result in mV::
#include <driver/adc.h>
#include <esp_adc_cal.h>
...
#define V_REF 1100 //ADC reference voltage
//Config ADC and characteristics
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_11db);
//Calculate ADC characteristics i.e. gain and offset factors
esp_adc_cal_characteristics_t characteristics;
esp_adc_cal_get_characteristics(V_REF, ADC_ATTEN_11db, ADC_WIDTH_12Bit, &characteristics);
//Read ADC and obtain result in mV
uint32_t voltage = adc1_to_voltage(ADC1_CHANNEL_6, &characteristics);
printf("%d mV\n",voltage);
Routing ADC reference voltage to GPIO::
#include <driver/adc.h>
#include <driver/gpio.h>
#include <esp_err.h>
...
esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25);
if (status == ESP_OK){
printf("v_ref routed to GPIO\n");
}else{
printf("failed to route v_ref\n");
}
API Reference
-------------
.. include:: /_build/inc/esp_adc_cal.inc

View file

@ -0,0 +1,51 @@
/* ADC1 Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_system.h"
#include "esp_adc_cal.h"
/*Note: Different ESP32 modules may have different reference voltages varying from
* 1000mV to 1200mV. Use #define GET_VREF to route v_ref to a GPIO
*/
#define V_REF 1100
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_6) //GPIO 34
//#define V_REF_TO_GPIO //Remove comment on define to route v_ref to GPIO
void app_main(void)
{
#ifndef V_REF_TO_GPIO
//Init ADC and Characteristics
esp_adc_cal_characteristics_t characteristics;
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_0db);
esp_adc_cal_get_characteristics(V_REF, ADC_ATTEN_0db, ADC_WIDTH_12Bit, &characteristics);
uint32_t voltage;
while(1){
voltage = adc1_to_voltage(ADC1_TEST_CHANNEL, &characteristics);
printf("%d mV\n",voltage);
vTaskDelay(pdMS_TO_TICKS(1000));
}
#else
//Get v_ref
esp_err_t status;
status = adc2_vref_to_gpio(GPIO_NUM_25);
if (status == ESP_OK){
printf("v_ref routed to GPIO\n");
}else{
printf("failed to route v_ref\n");
}
fflush(stdout);
#endif
}

View file

@ -1,35 +0,0 @@
/* ADC1 Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_6)
void adc1task(void* arg)
{
// initialize ADC
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db);
while(1){
printf("The adc1 value:%d\n",adc1_get_voltage(ADC1_TEST_CHANNEL));
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
void app_main()
{
xTaskCreate(adc1task, "adc1task", 1024*3, NULL, 10, NULL);
}

View file

@ -18,7 +18,7 @@ int sampling_period = 20;
int i = 0;
uint32_t sampling_start = esp_log_timestamp(); //this clock counts miliseconds
do {
ESP_LOGI(TAG, "Sample:%d, Value:%d", ++i, adc1_get_voltage(ADC1_TEST_CHANNEL));
ESP_LOGI(TAG, "Sample:%d, Value:%d", ++i, adc1_get_raw(ADC1_TEST_CHANNEL));
} while (esp_log_timestamp() - sampling_start < sampling_period);
```

View file

@ -87,7 +87,7 @@ int adc1_sample_and_show(int sampling_period)
int i = 0;
uint32_t sampling_start = esp_log_timestamp();
do {
ESP_LOGI(TAG, "Sample:%d, Value:%d", ++i, adc1_get_voltage(ADC1_TEST_CHANNEL));
ESP_LOGI(TAG, "Sample:%d, Value:%d", ++i, adc1_get_raw(ADC1_TEST_CHANNEL));
} while (esp_log_timestamp() - sampling_start < sampling_period);
return i;
}