#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 */
*
* @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.
* - -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.
*/
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
return ESP_OK;
}
-int adc1_get_voltage(adc1_channel_t channel)
+int adc1_get_raw(adc1_channel_t channel)
{
uint16_t adc_value;
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);
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
---------------------------------------------------------------*/
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);
--- /dev/null
+#
+# Component Makefile
+#
+
+COMPONENT_ADD_INCLUDEDIRS := include
\ No newline at end of file
--- /dev/null
+// 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);
+}
+
--- /dev/null
+// 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
+ }
+};
+
--- /dev/null
+// 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);
+
../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
##
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>
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::
.. 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 driver’s 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
\ No newline at end of file
--- /dev/null
+/* 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
+}
+++ /dev/null
-/* 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);
-}
-
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);
```
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;
}