I’ve just used the ADC with ESPHome for the first time with a LDR (light sensor).
I used the 11dB attenuation option on an ESP32. I powered the device with 5V over USB, and used the 3.3V generated on-board to connect the LDR with a 47k resistor to make a voltage divider. I measured the input voltage at the top of the divider and it’s at about 3.288V. I have it configured like this diagram, except replace 5V with 3.288V and R1 is 47kOhm.
The weird thing is ESPHome is reporting voltages above 3.3V when the LDR resistance is very high!!! I will investigate further.
I ended up going for 6dB attenuation, I can’t recall the outcome of the 11dB. From my code, it looks like I used a calibration function to straighten the ESP32’s non-linear ADC. I might look into the 11dB thing again over the weekend. Here’s the code I ended up with, it might give you some ideas to investigate:
#******************************************************************************
# LDR Light Sensor
#******************************************************************************
- platform: adc
pin: GPIO35
name: "LDR Voltage"
internal: true
# https://bit.ly/ESP32_ADC_Attenuation
# 6 dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2 V
# 11 dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9 V (see note below)
# Note: At 11 dB attenuation the maximum voltage is limited by VDD_A (3.30V), not the full scale voltage.
attenuation: '6db'
id: ldr_voltage
update_interval: 200ms
filters:
- sliding_window_moving_average:
window_size: 10
send_every: 5
# For maximum accuracy, use the ADC calibration APIs and measure voltages within these recommended ranges.
# 6 dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750 mV
# 11 dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450 mV
- calibrate_linear:
# Map from SENSOR -> TRUE value
- 0.135 -> 0.193
- 2.06 -> 1.776
- 2.185 -> 1.872
- lambda: |-
float raw_volts = id(ldr_voltage).raw_state;
int raw_adc_count = (raw_volts * 4095.0 / 3.90);
float current = (3.28 - x) / 47200.0;
//ESP_LOGW("adc", "3.28-x = %.3f, current = %.1fuA", 3.28 - x, current * 1E6);
id(ldr_resistance) = (x / current);
//ESP_LOGI("adc", "Raw ADC count [%u], Raw ADC Voltage [%.3fV], Filtered ADC Voltage [%.3fV], Resistance [%.0fkΩ]", raw_adc_count, raw_volts, x, id(ldr_resistance) / 1000.0);
return x;