Skip to content

Commit cd1fbe8

Browse files
pkendall64CapnBry
andauthored
ADC attenuation for ESP32 targets (ExpressLRS#2252)
* Hardware configurable ADC attenuation * Add -1 option to be able to unset the attenuation value * Only set ADC attenuation if set * Add ADC cal characterization option * Hardware configurable ADC attenuation * Add -1 option to be able to unset the attenuation value * Only set ADC attenuation if set * Add ADC cal characterization option * Adjustments to VBAT using eFuse calibration * Final scale/offset for production ERx-xx RXes --------- Co-authored-by: Bryan Mayland <[email protected]>
1 parent 59febd0 commit cd1fbe8

12 files changed

Lines changed: 194 additions & 27 deletions

src/hardware/RX/Frank 2400.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@
3232
"vbat": 34,
3333
"vbat_offset": 12,
3434
"vbat_scale": 410,
35+
"vbat_atten": 0,
3536
"button": 0
3637
}

src/hardware/RX/Generic 2400 True Diversity PA PWM 14.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@
3232

3333
"vbat": 36,
3434
"vbat_offset": -197,
35-
"vbat_scale": 1200
35+
"vbat_scale": 1200,
36+
"vbat_atten": 0
3637
}

src/hardware/RX/Generic 2400 True Diversity PWM 16.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
"radio_mosi":32,
44
"radio_rst":25,
55
"radio_sck":33,
6-
6+
77
"radio_busy":37,
88
"radio_dio1":38,
99
"radio_nss":26,
10-
10+
1111
"radio_busy_2":39,
1212
"radio_dio1_2":34,
1313
"radio_nss_2":27,
14-
14+
1515
"power_min":0,
1616
"power_high":0,
1717
"power_max":0,
@@ -23,10 +23,11 @@
2323
"led_rgb_isgrb":true,
2424
"ledidx_rgb_status":[0],
2525
"ledidx_rgb_boot":[0],
26-
26+
2727
"pwm_outputs":[14,12,13,15,2,0,4,9,10,5,18,23,19,22,3,1],
2828

2929
"vbat": 36,
3030
"vbat_offset": -197,
31-
"vbat_scale": 1200
31+
"vbat_scale": 1200,
32+
"vbat_atten": 0
3233
}

src/hardware/RX/Generic 900 True Diversity PWM 16.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
"radio_mosi":32,
44
"radio_rst":25,
55
"radio_sck":33,
6-
6+
77
"radio_dio0":37,
88
"radio_dio1":38,
99
"radio_nss":26,
10-
10+
1111
"radio_dio0_2":39,
1212
"radio_dio1_2":34,
1313
"radio_nss_2":27,
@@ -23,10 +23,11 @@
2323
"led_rgb_isgrb":true,
2424
"ledidx_rgb_status":[0],
2525
"ledidx_rgb_boot":[0],
26-
26+
2727
"pwm_outputs":[14,12,13,15,2,0,4,9,10,5,18,23,19,22,3,1],
2828

2929
"vbat": 36,
3030
"vbat_offset": -197,
31-
"vbat_scale": 1200
31+
"vbat_scale": 1200,
32+
"vbat_atten": 0
3233
}

src/hardware/RX/Radiomaster 2400 ER8G.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"i2c_scl": 18,
3030
"vbat": 39,
3131
"button": 0,
32-
"vbat_scale": 1280,
33-
"vbat_offset": -250
32+
"vbat_scale": 700,
33+
"vbat_offset": -30,
34+
"vbat_atten": 7
3435
}

src/hardware/RX/Vario 2400.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"pwm_outputs": [14,1,3,15,2,4],
2222
"vbat": 39,
2323
"button": 0,
24-
"vbat_scale": 1038,
25-
"vbat_offset": -153
24+
"vbat_scale": 1024,
25+
"vbat_offset": -62,
26+
"vbat_atten": 7
2627
}

src/hardware/targets.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@
106106
"layout_file": "Generic 900 True Diversity PWM 16.json",
107107
"overlay": {
108108
"pwm_outputs":[13,15,2,0,4,9,10,5,18,23,19,22,3,1],
109-
"vbat_offset": -300,
110-
"vbat_scale": 1227
109+
"vbat_offset": 4,
110+
"vbat_scale": 285,
111+
"vbat_atten": 4
111112
},
112113
"upload_methods": ["uart", "wifi", "betaflight"],
113114
"platform": "esp32",
@@ -211,8 +212,9 @@
211212
"layout_file": "Generic 2400 True Diversity PA PWM 14.json",
212213
"overlay": {
213214
"radio_dcdc": true,
214-
"vbat_offset": -300,
215-
"vbat_scale": 1227
215+
"vbat_offset": 4,
216+
"vbat_scale": 285,
217+
"vbat_atten": 4
216218
},
217219
"upload_methods": ["uart", "wifi", "betaflight"],
218220
"platform": "esp32",

src/html/hardware.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,19 @@ <h1><b>ExpressLRS</b></h1>
262262
<tr><td></td><td>VBat pin<img class="icon-analog"/></td><td><input size='3' id='vbat' name='vbat' type='text'/></td><td>Analog input pin for reading VBAT voltage (1V max on 8285, 3.3V max on ESP32)</td></tr>
263263
<tr><td></td><td>VBat offset</td><td><input size='7' id='vbat_offset' name='vbat_offset' type='text'/></td><td>Offset and scale are used together with the analog pin to calculate the voltage</td></tr>
264264
<tr><td></td><td>VBat scale</td><td><input size='7' id='vbat_scale' name='vbat_scale' type='text'/></td><td>voltage = (analog - offset) / scale</td></tr>
265+
<tr><td></td><td>VBat attenuation</td><td>
266+
<select id='vbat_atten' name='vbat_atten'>
267+
<option value='-1'>Default</option>
268+
<option value='0'>0 dB</option>
269+
<option value='1'>2.5 dB</option>
270+
<option value='2'>6 dB</option>
271+
<option value='3'>11 dB</option>
272+
<option value='4'>0 dB + calibration</option>
273+
<option value='5'>2.5 dB + calibration</option>
274+
<option value='6'>6 dB + calibration</option>
275+
<option value='7'>11 dB + calibration</option>
276+
</select>
277+
</td><td>ADC pin attenuation (ESP32) and optional efuse-based calibration adjustment</td></tr>
265278

266279
<tr><td colspan='2'><b>SPI VTX</td></tr>
267280
<tr><td></td><td>RF amp PWM pin<img class="icon-pwm"/></td><td><input size='3' id='vtx_amp_pwm' name='vtx_amp_pwm' type='text'/></td><td>Set the power output level of the VTX PA (value is calculated based on power and frequency using VPD interpolation values)</td></tr>

src/include/hardware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ typedef enum {
123123
HARDWARE_vbat,
124124
HARDWARE_vbat_offset,
125125
HARDWARE_vbat_scale,
126+
HARDWARE_vbat_atten,
126127

127128
// VTX
128129
HARDWARE_vtx_amp_pwm,

src/lib/AnalogVbat/devAnalogVbat.cpp

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,25 @@
55
#include "CRSF.h"
66
#include "telemetry.h"
77
#include "median.h"
8+
#include "logging.h"
89

910
// Sample 5x samples over 500ms (unless SlowUpdate)
1011
#define VBAT_SMOOTH_CNT 5
12+
#if defined(DEBUG_VBAT_ADC)
13+
#define VBAT_SAMPLE_INTERVAL 20U // faster updates in debug mode
14+
#else
1115
#define VBAT_SAMPLE_INTERVAL 100U
16+
#endif
1217

1318
typedef uint16_t vbatAnalogStorage_t;
1419
static MedianAvgFilter<vbatAnalogStorage_t, VBAT_SMOOTH_CNT>vbatSmooth;
1520
static uint8_t vbatUpdateScale;
1621

22+
#if defined(PLATFORM_ESP32)
23+
#include "esp_adc_cal.h"
24+
static esp_adc_cal_characteristics_t *vbatAdcUnitCharacterics;
25+
#endif
26+
1727
/* Shameful externs */
1828
extern Telemetry telemetry;
1929

@@ -33,25 +43,47 @@ static int start()
3343
}
3444
vbatUpdateScale = 1;
3545
#if defined(PLATFORM_ESP32)
36-
analogSetPinAttenuation(GPIO_ANALOG_VBAT, ADC_0db);
3746
analogSetWidth(12);
47+
48+
int atten = hardware_int(HARDWARE_vbat_atten);
49+
if (atten != -1)
50+
{
51+
// if the configured value is higher than the max item (11dB, it indicates to use cal_characterize)
52+
bool useCal = atten > ADC_11db;
53+
if (useCal)
54+
{
55+
atten -= (ADC_11db + 1);
56+
57+
vbatAdcUnitCharacterics = new esp_adc_cal_characteristics_t();
58+
int8_t channel = digitalPinToAnalogChannel(GPIO_ANALOG_VBAT);
59+
adc_unit_t unit = (channel > (SOC_ADC_MAX_CHANNEL_NUM - 1)) ? ADC_UNIT_2 : ADC_UNIT_1;
60+
esp_adc_cal_characterize(unit, (adc_atten_t)atten, ADC_WIDTH_BIT_12, 3300, vbatAdcUnitCharacterics);
61+
}
62+
analogSetPinAttenuation(GPIO_ANALOG_VBAT, (adc_attenuation_t)atten);
63+
}
3864
#endif
65+
3966
return VBAT_SAMPLE_INTERVAL;
4067
}
4168

4269
static void reportVbat()
4370
{
44-
uint32_t adc = vbatSmooth.calc_scaled();
45-
uint16_t vbat;
46-
// For negative offsets, anything between abs(OFFSET)*CNT and 0 is considered 0
47-
if (ANALOG_VBAT_OFFSET < 0 && adc <= (ANALOG_VBAT_OFFSET * -vbatSmooth.scale()))
71+
uint32_t adc = vbatSmooth.calc();
72+
#if defined(PLATFORM_ESP32) && !defined(DEBUG_VBAT_ADC)
73+
if (vbatAdcUnitCharacterics)
74+
adc = esp_adc_cal_raw_to_voltage(adc, vbatAdcUnitCharacterics);
75+
#endif
76+
77+
int32_t vbat;
78+
// For negative offsets, anything between abs(OFFSET) and 0 is considered 0
79+
if (ANALOG_VBAT_OFFSET < 0 && adc <= -ANALOG_VBAT_OFFSET)
4880
vbat = 0;
4981
else
50-
vbat = adc * 100U / (ANALOG_VBAT_SCALE * vbatSmooth.scale());
82+
vbat = ((int32_t)adc - ANALOG_VBAT_OFFSET) * 100 / ANALOG_VBAT_SCALE;
5183

5284
CRSF_MK_FRAME_T(crsf_sensor_battery_t) crsfbatt = { 0 };
5385
// Values are MSB first (BigEndian)
54-
crsfbatt.p.voltage = htobe16(vbat);
86+
crsfbatt.p.voltage = htobe16((uint16_t)vbat);
5587
// No sensors for current, capacity, or remaining available
5688

5789
CRSF::SetHeaderAndCrc((uint8_t *)&crsfbatt, CRSF_FRAMETYPE_BATTERY_SENSOR, CRSF_FRAME_SIZE(sizeof(crsf_sensor_battery_t)), CRSF_ADDRESS_CRSF_TRANSMITTER);
@@ -64,8 +96,15 @@ static int timeout()
6496
{
6597
return DURATION_NEVER;
6698
}
67-
int adc = analogRead(GPIO_ANALOG_VBAT);
68-
adc = (adc > ANALOG_VBAT_OFFSET) ? adc - ANALOG_VBAT_OFFSET : 0;
99+
100+
uint32_t adc = analogRead(GPIO_ANALOG_VBAT);
101+
#if defined(PLATFORM_ESP32) && defined(DEBUG_VBAT_ADC)
102+
// When doing DEBUG_VBAT_ADC, every value is adjusted (for logging)
103+
// in normal mode only the final value is adjusted to save CPU cycles
104+
if (vbatAdcUnitCharacterics)
105+
adc = esp_adc_cal_raw_to_voltage(adc, vbatAdcUnitCharacterics);
106+
DBGLN("$ADC,%u", adc);
107+
#endif
69108

70109
unsigned int idx = vbatSmooth.add(adc);
71110
if (idx == 0 && connectionState == connected)

0 commit comments

Comments
 (0)