Tech Note 151 - ESP32 ADC Accuracy Improvement using the ADC reference voltage to correct readings.

Поділитися
Вставка

КОМЕНТАРІ • 72

  • @bgable7707
    @bgable7707 2 роки тому +1

    OMG, "preferred Value", first time I've heard this reference used. Your excellent explanation makes sense. I also just watched your new video related to Improving ADC accuracy, “Tech Note 151 - ESP32 ADC Accuracy Improvement using the ADC reference voltage”
    FYI: I’m working on ESP-01 battery-powered sensors and want to be notified when the batteries drop below ~ < 3.0. This helps!

    • @G6EJD
      @G6EJD  2 роки тому +2

      Preferred values are used for all resistor value ranges, in fact resisters can only be purchased by preferred values unless you want a specialised value.

    • @bgable7707
      @bgable7707 2 роки тому

      @@G6EJD Look like I added my comment for video 115 to this one 151, oh well. reviewing 115 now

  • @MPElectronique
    @MPElectronique 3 роки тому +1

    Thank you Dave.
    Nice to have great news from you always.
    Marc.

  • @omniyambot9876
    @omniyambot9876 2 роки тому +1

    Omg I was pissed because the esp32 don't read milivolts accurately. Thanks man!!

  • @roycejp
    @roycejp 3 роки тому +5

    Thank you for your great tutorials on ESP32!
    Please make a tutorial on flash encryption and secure boot.
    There is no tutorial available on this that explains this in a simple manner.
    How do we protect our code from being unauthorised reads.
    This is the only reason keeping me from using ESP32 for more serious applications.
    Thank you!

  • @alainclarke3566
    @alainclarke3566 3 роки тому +1

    Thank you David just what i needed right now

  • @s.husain6125
    @s.husain6125 3 роки тому +2

    Thank you david sir ....

  • @stevel7957
    @stevel7957 Рік тому

    David, thanks for your many contributions to the ESP32 community. I've learned much from your tech notes on UA-cam! Thank you. I implemented this setup to calibrate the ADC and I have observed on both of my ESP32 Dev Modules (both are ESP32-WROOM-S2) very poor ADC repeatability - with some measurements spot on but many ranging out as far as +/- 0.15 volts in error. My DC source is a rock solid HP benchtop unit that my HP benchtop multimeter shows outputting a steady +3.0063 VDC. I downloaded your sketch so there is nothing else running on the processor. However, I have noticed the same phenomena using other code (I wrote) so there is something The variance is unacceptably high and I'm trying to chase down the source if it. I even modified your code to include a for loop and average multiple results to try to reduce the noise but this had no effect. So maybe something within the ESP32 board is impacting results...
    Is it a common trait of the ESP32 ADC's to have "marginal" repeatability? Or is this what I should expect? I would expect this not to be the case since trying to improve measurement accuracy to < 1% would be moot if the system is not repeatable in the first place... Any ideas?

    • @G6EJD
      @G6EJD  Рік тому

      Hi Steve, well I agree with your findings, reading the Espressif data sheets they make reference to each ESP32 has its ADC reference voltage laser trimmed during production and that each device will be different, but then they allow access to the reference voltage so that accuracy can be improved at implementation. So each ESP32 has to be individually calibrated to take into account external component tolerances, where resistors will add say +/- 1-2% to uncalibrated accuracy spread, then ADC conversion will add +/- 1-bit of accuracy spread, leading to a result that should be (once calibrated) quite repeatable within a given ADC conversion resolution and that has been my findings. So results will vary with the selected resolution for example 1 in 4096 or 1 in 1024 will yield different accuracy and repeatability results. The ADC is more of a general purpose unit and certainly not a precision device, which inevitably leads to the fit of an external device. Noise can be a difficult problem to solve, especially if the carrier board has poor earthing and shielding and the power source is noisy; usually an on-board regulator, so that would be my first point of investigation, followed by often poor high frequency power line filtering, as boards often use a single tantalum capacitor with an inherent high induction so it doesn’t remove noise, necessitating a parallel ceramic capacitor. Then if noise is still a problem increasing the time constant of the ADC input with an input smoothing capacitor, and here’s the next problem, that Espressif state the input impedance of each device can vary, they don’t say, but I’d expect a batch spread to remain consistent with each other. So there can be no one value that will work across all devices. It’s difficult to design external circuitry to minimise device spread when the variability is relatively high. I’ve measured the input impedance of many devices and found the spread is huge, but generally assume it to be 180K. So a 1 or 2 sec time constant should give good results, but the ADC input needs an impedance isolation so a series resistance is essential for a smoothing capacitor to work. So a 50K 20uF combination should provide a stable input voltage for test measurements, it sounds like your doing the right thing by averaging readings to reduce quantisation errors, but you may find better results by reducing the resolution setting downwards, it’s all a compromise and a difficult subject to optimise. Hope this helps.

    • @stevel7957
      @stevel7957 Рік тому

      @@G6EJD Many thanks for the thoughts. Let me try a few of these ideas and I'll loop back on what did/didn't work for me.

    • @G6EJD
      @G6EJD  Рік тому

      Hi Steve, I think two simple tests are essential, short the ADC input to ground, then measure the noise, then repeat with the input at Vcc / 3.3 of the cpu supply line, that will indicate if there is an inherent ADC issue or ground issue or supply.

    • @stevel7957
      @stevel7957 Рік тому

      @@G6EJD Hi again David. As suggested, using GPIO36, I measured 0 & 3.3V and the got the following using the default ADC setup... 0V (GND), ADC read 0 with no variance at all over hundreds of readings. Measuring the 3.3V rail, I measured in blocks of 256 readings (sampled at 8msec interval), averaged the readings and repeatedly got 3968.72 with an sdev of 1.27e-11. Ok, that is about as good and I would expect from the ESP32's ADC. Therefore, I think I need to look externally at my setup for the source of "noise".
      My next step is to modify the signal conditioning on the input channels as you suggested previously. In my [automotive] application, I have 5 different analog sensors (temperature resistive, pressure resistive, vacuum 5V and alternator 15V output). I have set up voltage dividers to drop the input ADC voltages to

    • @stevel7957
      @stevel7957 Рік тому

      While I'm on the subject, let me ask you a related question on ADC accuracy. I took under advisement your ADC linearity algorithm in your Tech Note #69 and intend to use that in my application. My sensors resistance can vary widely and I need all the range I can get. But with regard to the measurement accuracy improvement in THIS video using the internal VREF, can BOTH methods be used together or are they effectively redundant? In other words, could I improve that absolute voltage measurement by the ADC by using VREF and then use the linearity algorithm to improve further on the range edges? I'm inclined to believe this to be true but please clarify if I am on the wrong track. Thx in adv!

  • @clementbeschu9711
    @clementbeschu9711 3 роки тому +3

    Thanks for this video ! I was just wondering how did you calculate the 2.174 value (on the github). My board has a on-board voltage divider and it's written on the datasheet to multiply by 2 the data (and not by 2.174). It's the HUZZAH 32 Feather by Adafruit. Thanks

    • @G6EJD
      @G6EJD  3 роки тому

      I covered in the Readme! It’s because of the input impedance of the ESP32 that loads the voltage divider. The only time the resistor ratios could be used (eg 2) is if the value of the voltage divider resistors were very much lower than the ESP32

  • @keen2461
    @keen2461 3 роки тому

    Love your videos.....very useful and well explained. Thanks for sharing.

  • @TheAstronomyDude
    @TheAstronomyDude 3 роки тому +1

    100th like \o/ Seriously helpful video. Thanks David!

  • @fredflintstone1
    @fredflintstone1 3 роки тому +1

    great info and program thank you :-)

  • @NavyPanther54
    @NavyPanther54 3 місяці тому +1

    Having a strange issue here. I have a voltage divider set up so I can read an external battery. With the resistors I picked, I should be getting 1.81 volts according to the calculators. And my multimeter confirms that. My ESP32 reads 1.68 volts. Figured I'd look into calibrating it.
    Problem is, when I run your code it brings my reading DOWN to 1.65. The vref is 1121 apparently. Would it be fine to increase the calibration to 1.094? Or would it make more sense to adjust the vref manually in your calculations? Thanks!
    Going to test some other ESP32 I have too, one is a different board setup so maybe it's just the manufacturer of this board. It's a NodeMCU 32s, v1.1 I think.

    • @G6EJD
      @G6EJD  3 місяці тому

      You can change any content to adjust the calibration as they won’t change the linearity of the calculation. The variability will be a function of the ESP32 ADC input impedance or voltage reference. The process of reading the Vref is to try to remove device variability from the calculations, which for most devices from the same manufacturer should work, but I’ve found quite large variations and this issue has never been addressed by Espressif, and probably never will. So I would change the multiplier by 1.68/1.81 ie reduce it.

    • @NavyPanther54
      @NavyPanther54 3 місяці тому

      @@G6EJD Awesome, thanks a lot man! Appreciate the quick response as well

  • @brianh21858
    @brianh21858 Рік тому +1

    Would you please explain what line 24 does? The code is:
    esp_adc_cal_characteristics_t adc_chars;
    Thanks very much

    • @G6EJD
      @G6EJD  Рік тому +3

      Each ESP32 is factory trimmed / calibrated and the reference value is stored in the microcode, so this function converts an ADC reading to voltage in mV, by taking into account the individual ADC characteristics. This then enables different ESP32 devices to give the correct result.

  • @jankuhlmann9196
    @jankuhlmann9196 3 роки тому

    Thanks David.

  • @JosefZvolanek
    @JosefZvolanek 3 роки тому

    Nice video!

  • @MPElectronique
    @MPElectronique 3 роки тому

    Thanks Dave! :) I will try :)
    Thanks.
    Marc.

    • @G6EJD
      @G6EJD  3 роки тому

      It works!

  • @edycole5543
    @edycole5543 3 роки тому

    Thanks

  • @lucasmontec
    @lucasmontec 3 місяці тому

    Esp just crashes: E (75) ADC: CONFLICT! driver_ng is not allowed to be used with the legacy driver

    • @G6EJD
      @G6EJD  3 місяці тому

      It enough information to even begin to help

  • @blakefl8623
    @blakefl8623 3 роки тому +1

    Have you tried using mega ohm resistors to reduce power consumption in voltage dividers? Was wondering how that also impacts the accuracy of the adc readings.

    • @G6EJD
      @G6EJD  3 роки тому

      A lot as the input impedance of the ESP32 is about 160K and Varies between device to device, that’s my criticism of the DFRobot board they use 2 x 1M resistors for their voltage divider and whilst it works it requires a stable input voltage so the smoothing capacitor can charge and it’s a long time constant, there is no ideal just compromise solution in my experience.

    • @blakefl8623
      @blakefl8623 3 роки тому

      So as a good compromise for a 4.2v 18650 I could do 470k and around 1.2M ohm combination. What do you think?

    • @G6EJD
      @G6EJD  3 роки тому +1

      You need enough input current to the ESP32 ADC, so if it were wired Vin - 470K-ADC-1M-Gnd I’d say ok, but the other way round. I use 2x560K for a /2 voltage divider.

    • @G6EJD
      @G6EJD  3 роки тому +1

      @@blakefl8623 also even after calibration of Vref you will to calibrate against a known good meter you will not find the divider is a an exact value like 2 as the voltage divider loads the ADC and skews the readings downward thereby needing eg 2.2 to compensate.
      With a /2 voltage divider the equation should be:
      Voltage = analogRead(ADC pin) / 4095 * 2;
      But it will be * 2.2 or whatever to calibrate it.
      You can measure input impedance by applying a known voltage and measuring the actual ADC input voltage then you know through kirchoffs law the input current and hence input impedance.

    • @blakefl8623
      @blakefl8623 3 роки тому

      If I use two 560k resistors with an 18650, would a 0.1uf capacitor be necessary ?

  • @ppe4dfw902
    @ppe4dfw902 2 роки тому

    Hi David, been using the code from your Tech Note 069 for about a year. Today I "upgraded" the Espressif core in the Arduino IDE from 1.0.1 to 1.0.6 and now got compiler errors:
    esp32Target.cpp:1499:27: error: 'adcStart' was not declared in this scope
    adcStart(boxXaxis);
    ^
    esp32Target.cpp:1500:32: error: 'adcBusy' was not declared in this scope
    while(adcBusy(boxXaxis)) {;}
    ^
    esp32Target.cpp:1501:34: error: 'adcEnd' was not declared in this scope
    work1 += adcEnd(boxXaxis);
    Any chance you could point me to what to do? Thanks
    ^

    • @G6EJD
      @G6EJD  2 роки тому

      I've just complied the code using 1.0.6, no problems detected, your compiler update/installation is faulty.

    • @ppe4dfw902
      @ppe4dfw902 2 роки тому

      @@G6EJD thanks, I think.... :-(

  • @ButilkaRomm
    @ButilkaRomm 2 роки тому

    Arduino has AREF, so when using it no calibration is needed. Which is better design?

    • @G6EJD
      @G6EJD  2 роки тому

      Arduino

  • @dennycarlyle7826
    @dennycarlyle7826 3 роки тому

    Thanks for the useful solution. I am, so far, unable to find a .zip file for the esp_adc_cal library as a download for the Arduino IDE. I have looked in github and otherwise googled for it but am coming up dry. Can you tell me where I can find it?

    • @G6EJD
      @G6EJD  3 роки тому +1

      The library is included in the ESP32 add-on, you'd need to go to the Espressif github for the add-on, if that' what you mean.

    • @dennycarlyle7826
      @dennycarlyle7826 3 роки тому +1

      @@G6EJD thanks for the prompt response. I figured it was there but I was searching in the wrong place. I’ll try again in the morning.

    • @pedroz.3745
      @pedroz.3745 Рік тому +1

      ​@@dennycarlyle7826 you got it? i am with the same problem, cant find a library... do you found?

    • @G6EJD
      @G6EJD  Рік тому

      There is no equivalent library for the ESP8266

  • @TheModelmaker123
    @TheModelmaker123 3 роки тому

    That good info. I switched from Arduino to ESP32, thinking this was the greatest thing since sliced bread, dual core, 4 times the speed, Bluetooth, WiFi. Then when trying to measure low voltages with the ADC it didn't seem to work as well as the Arduino. Not sure if there is any fix for that.

    • @G6EJD
      @G6EJD  3 роки тому +1

      The resolution is 3.3/4096=0.8mV and I’ve published an accuracy improvement algorithm that gets accuracy to within 1%, that’s as good as it gets. You can measure the full range between 0-3.3v without a voltage divider.

    • @G6EJD
      @G6EJD  Рік тому +2

      I’ve published a polynomial that will bring readings to within 1% across the ADC range and how to read the internal reference voltage that varies between devices (factory trimmed) to get highly accurate results. See my other notes.

    • @G6EJD
      @G6EJD  Рік тому +1

      @@chesshooligan1282 a polynomial is an expression consisting of indeterminates and coefficients, that involves only the operations of addition, subtraction, multiplication, and positive-integer powers of variables. That’s what I implemented.

  • @MPElectronique
    @MPElectronique 3 роки тому

    Dave, a int is : This yields a range of -32,768 to 32,767 ;-( how can this works ?

    • @G6EJD
      @G6EJD  3 роки тому

      Depends on the type which with range is a signed integer the most significant but is the sign bit so a 16-bit integer ranges from 0-65535 but when signed ie can hold -32768 to 32767 it’s the same 16-bits but interpreted in a different way.

  • @solidfuel0
    @solidfuel0 3 роки тому

    Is something similar for esp8266. I'm suffering from random noise jumps every few seconds

    • @G6EJD
      @G6EJD  3 роки тому

      Unfortunately not. The best you can do is fit a capacitor across A0 say 1uF or 0.1uF to slow down any external noise spikes the most likely cause. Short the input to ground and see if you get spikes when reading, do the same to 3.3v and repeat or take 10 readings then divide by 10 to average out noise.
      for(int r=0; r

    • @andrewkieran8942
      @andrewkieran8942 3 роки тому

      @@G6EJD A faster approach is to average 8 readings rather than 10. This avoids slow division routines. You can just shift the result right, four times.

    • @G6EJD
      @G6EJD  3 роки тому

      @@andrewkieran8942 a floating point result?

    • @andrewkieran8942
      @andrewkieran8942 3 роки тому

      @@G6EJD No, I'm talking about summing 8 raw analog readings, before doing any FP math.

    • @G6EJD
      @G6EJD  3 роки тому

      Ok understand, unless a time critical measurement then any averaging process will do. Reminds me that x10 can be achieved by 8x + 2x using just shifts