I'm using ADC1 on the ESP32-S3 in Continuous mode, 10kHZ sample rate, 11dB attenuation, and I'm getting some weird noise or "ringing" in the troughs of the trace below:
Here's an analog logic probe capture of the exact same signal (measured near the IO pin):
The signal is generated by a current transformer measuring a 60Hz mains supply to a halogen lamp.
Has anyone seen this sort of thing before, and have any tips? I know averaging is possible but I'd like to clean up the raw input a bit more before I go there.
Here's another pair of traces (from when the lamp is first turned on):
My code is using ESP-IDF. I'm pretty sure the problem is a configuration or code issue, because when I reverted to an earlier version that uses CircuitPython and a series of one-shot samples (also at ~10kHz) I get a cleaner result:
I'm guessing the CircuitPython libraries are doing some tricks my rudimentary ESP-IDF code (which was copied from the ADC continuous_read example) is not.
ADC1 noise at low voltages
Re: ADC1 noise at low voltages
I also tested some one-shot code under MicroPython and am getting clean results. I'm not clear why the continuous mode samples have the artifact.
I've been trying to set up the ADC registers by hand in MicroPython, using mem32(), but have found my writes to registers like APB_SARADC_CTRL_REG and APB_SARADC_CTRL2_REG are having no effect. Writes to the GPIO registers work as expected. Is there anything I need to do first in order to successfully write to the ADC registers?
I've been trying to set up the ADC registers by hand in MicroPython, using mem32(), but have found my writes to registers like APB_SARADC_CTRL_REG and APB_SARADC_CTRL2_REG are having no effect. Writes to the GPIO registers work as expected. Is there anything I need to do first in order to successfully write to the ADC registers?
Re: ADC1 noise at low voltages
OK, I haven't solved the low-voltage noise problem, but I did make headway obtaining direct-register control of the ADC.
Turns out you need to de-assert the peripheral's RESET line (and probably enable it's clock) via the undocumented bit #28 of these two registers: SYSTEM_PERIP_RST_EN0_REG and SYSTEM_PERIP_CLK_EN0_REG.
The Technical Reference Manual (latest version 1.1) fails to mention this, and lists those bits as "(reserved)". But if you dive into the framework (v5.0) library code you can find #defines for them in system_reg.h. I reported the errata to EspressIf, hopefully someone there will bulk up their ADC documentation.
Turns out you need to de-assert the peripheral's RESET line (and probably enable it's clock) via the undocumented bit #28 of these two registers: SYSTEM_PERIP_RST_EN0_REG and SYSTEM_PERIP_CLK_EN0_REG.
The Technical Reference Manual (latest version 1.1) fails to mention this, and lists those bits as "(reserved)". But if you dive into the framework (v5.0) library code you can find #defines for them in system_reg.h. I reported the errata to EspressIf, hopefully someone there will bulk up their ADC documentation.
Re: ADC1 noise at low voltages
After a month of on-and-off work, I made some major breakthroughs. I started from scratch with a new Micropython project and manually configured DMA by hand via registers.
Here's a capture from it (using an 80Khz sample rate!):
And the corresponding trace from my analog logic probe:
The data is saved to one giant DMA buffer (via chained descriptors), so the CPU is free to do whatever it wants during the capture.
I'm starting to suspect there might be something buggered with the continuous_read example project from IspressIf, which caused the artifacts seen in my original post. Here's what it produced when I tried some quick and dirty changes to take a capture at ~80KHz:
Here's a capture from it (using an 80Khz sample rate!):
And the corresponding trace from my analog logic probe:
The data is saved to one giant DMA buffer (via chained descriptors), so the CPU is free to do whatever it wants during the capture.
I'm starting to suspect there might be something buggered with the continuous_read example project from IspressIf, which caused the artifacts seen in my original post. Here's what it produced when I tried some quick and dirty changes to take a capture at ~80KHz:
-
- Posts: 94
- Joined: Tue Sep 07, 2021 12:07 pm
Re: ADC1 noise at low voltages
Interesting. I'm doing something very similar and continuous reading 4 channels interleaved on esp32. The interleave pattern was predictable up to about 270K total samples/sec. Above that the pattern gets scrambled, repeating, skipping. I take the raw 16 bit samples and split each sample into a 4-bit channel ID and a 12-bit value. You might be seeing something similar if your 80kHz is per channel for 4 or more channels (320K samples/sec). I'm using 264K at the moment. Fast enough for 60Hz power line monitoring.
Experiment, using esp-idf/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c
mod for esp32 to read 4 channels in sequence, original low freq, works fine
mod for 280K, this is too high, the channel ordering is puzzling
mod down to 270K, the channel ordering makes sense again
My original working prototype at a lower frequency assumed the channel order would be stable. Ver 2 ran at a higher frequency and the unexpected scrambled channel ordering meant sometimes I'd get a volt reading when I thought I was reading amps.
https://community.jmp.com/t5/Uncharted/ ... a-p/562554
Experiment, using esp-idf/examples/peripherals/adc/dma_read/main/adc_dma_example_main.c
mod for esp32 to read 4 channels in sequence, original low freq, works fine
Code: Select all
static adc_channel_t channel[4] = {ADC1_CHANNEL_7,ADC1_CHANNEL_6,ADC1_CHANNEL_5,ADC1_CHANNEL_4};
I (8651) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (8651) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (8661) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (8661) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (8671) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (8681) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (8681) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (8691) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (8691) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (8701) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (8701) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (8711) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (8711) ADC DMA: Unit: 1, Channel: 7, Value: 0
mod for 280K, this is too high, the channel ordering is puzzling
Code: Select all
.sample_freq_hz = 280 * 1000,
I (4481) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (4491) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (4491) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (4501) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (4501) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (4511) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (4511) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (4521) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (4521) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (4531) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (4541) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (4541) ADC DMA: Unit: 1, Channel: 6, Value: 0
mod down to 270K, the channel ordering makes sense again
Code: Select all
.sample_freq_hz = 270 * 1000,
I (3341) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (3341) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (3351) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (3351) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (3361) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (3361) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (3371) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (3371) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (3381) ADC DMA: Unit: 1, Channel: 7, Value: 0
I (3381) ADC DMA: Unit: 1, Channel: 4, Value: 0
I (3391) ADC DMA: Unit: 1, Channel: 5, Value: 0
I (3401) ADC DMA: Unit: 1, Channel: 6, Value: 0
I (3401) ADC DMA: Unit: 1, Channel: 7, Value: 0
My original working prototype at a lower frequency assumed the channel order would be stable. Ver 2 ran at a higher frequency and the unexpected scrambled channel ordering meant sometimes I'd get a volt reading when I thought I was reading amps.
https://community.jmp.com/t5/Uncharted/ ... a-p/562554
Craige
Who is online
Users browsing this forum: No registered users and 38 guests