ADC analysis (Firmware V00L)


I forgot to post last week.  If you read this regularly, I am sorry.

Espressif has released a Version 2.0 of it’s SDK.  I am not quite ready to upgrade to that yet, I will wait until after I get my basic functionality tested.  Also, this is a major release, they might have added a few bugs, I can wait till some are fixed.

Voltage Control loop:

I decided to work on the voltage control loop. First step, get a better understanding of the ADC.  I needed to know if the system calls to read the ADC are blocking or nonblocking. An ADC takes time to finish. If it returns the sample from the previous call, I will have to take a second reading to get the correct value.  If it is blocking, I don’t want to call it from within the interrupt service routine (ISR).

Note:  When you call a blocking function, it finishes it’s job before coming back.  Non blocking starts the job and then comes back.

The SDK API is not specific as whether the system_adc_read() is blocking or not.  So I set up a test. Pin 10 of the programming connector connects back to GPIO14.  If I set GPIO14 high before calling system_adc_read() and set it low before calling it again, I can tell how long the call takes. I created a system timer event in events.c and used it to read the adc.  The system timer just calls an os task so it isn’t like an ISR.  I created a function called adc_read.  I initialized a variable, set GPIO14 high, call system_adc_read() and set GPIO14 low. I then set up the function to enable the timer task, I called it init_adc_timer().  I called this from user_init().  The code built. I uploaded it. I hooked up my scope to Pin 10 of the target header.

I got nothing, I didn’t hook up Vtarget.  I decided it was easier to probe GPIO14 directly on the ESP-12F. The pin was always high.  I checked the pin configuration in user_main.c. Nothing wrong there. I found a copy/paste error in events.c  I had copied the line to change GPIO13 to low and changed it to GPIO14 to set it high but didn’t change the one to set it low.  I fixed this and tried again.  I got the pulses I was looking for on the Oscilloscope.  The high pulse width measured 96.2 μS.  This is much longer than I would put into an ISR.  If i polled this read regularly, It would cause a significant loss in performance.

The Next Step:

I decided to see if I could access the ADC directly through hardware registers.  I couldn’t find any clear documentation on the ADC registers.  In the API, there is also a function call system_adc_read_fast().  This one requires wifi to be turned off when called.  I decided to try it turning Wifi off and back on after around each read.  I modified the code to try this change. Now the pulse width is 21.8 μS. Unfortunately, the wifi disconnects when I disable it. This is a problem.  I tried leaving the wifi enabled and it works. 21.8 μS is longer than I would want in an ISR so I will call it from the os_timer function and use it to make adjustments.  If I call this every 5 mS, it will tie up the processor for about 1/2 of 1% of the time.  This doesn’t seem like a lot, but I want to get as much performance as I can when I am programming a target.  And this control loop will have to be running while programming a target.


The results of my testing are not as good as I had hoped.  Maybe Espressif will come out with a non-blocking way to use the ADC in the future. Ideally, I would call a function to start the conversion, and the system would call back to my function with the result. As a final step I display the menu with the adc reading once every 200 cycles (1 second).  I have uploaded these changes to github click the link in the right column to go check it out.

Do you have any experience with the ESP8266 adc?  Have you found a work around for the blocking call?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.