I need to use system_adc_read_fast (uint16 *adc_addr, uint16 adc_num, uint8 adc_clk_div)
to get a sampling rate close to 100 ksps. I am able to achieve that using adc_clk_div = 32
.
However, when I print out the values stored in adc_addr
, I always get 1024
. Why is this?
I have a NodeMCU v3. I have connected an electret microphone to it. The +ve terminal is connected to 3.3 V through 10 kΩ; GND is connected to GND. The +ve terminal is connected to A0 on NodeMCU.
schematic
simulate this circuit – Schematic created using CircuitLab
It works fine when I use system_adc_read()
(except the sampling rate is then 10 ksps which is not desirable).
Sketch:
// Expose Espressif SDK functionality - wrapped in ifdef so that it still
// compiles on other platforms
#ifdef ESP8266
extern "C" {
#include "user_interface.h"
}
#endif
ADC_MODE(ADC_TOUT);
#define num_samples 512
uint16_t adc_addr[num_samples]; // point to the address of ADC continuously fast sampling output
uint16_t adc_num = num_samples; // sampling number of ADC continuously fast sampling, range [1, 65535]
uint8_t adc_clk_div = 32; // ADC working clock = 80M/adc_clk_div, range [8, 32], the recommended value is 8
int i = 0;
unsigned long start = 0;
unsigned long total = 0;
unsigned long tim = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
#ifdef ESP8266
// Serial.println(system_get_sdk_version());
wifi_set_opmode(NULL_MODE);
system_soft_wdt_stop();
ets_intr_lock( ); //close interrupt
noInterrupts();
start = micros();
// Serial.println(system_adc_read());
system_adc_read_fast(adc_addr, adc_num, adc_clk_div);
unsigned int tot = micros() - start;
interrupts();
ets_intr_unlock(); //open interrupt
system_soft_wdt_restart();
tim += tot;
total += num_samples * 1000000.0 / tot;
i++;
for (int j=0; j<adc_num; j++) {
Serial.println(adc_addr[j]);
}
if (i == 100) {
// Serial.print("Sampling rate: ");
// Serial.println(total / 100);
// Serial.print("It lasted: ");
// Serial.println(tim / 100);
i = 0;
tim = 0;
total = 0;
}
#endif
}
-
Please add a schematic of your wiring: the behaviour you are describing doesn't look correctRoberto Lo Giacco– Roberto Lo Giacco2018年01月11日 01:27:33 +00:00Commented Jan 11, 2018 at 1:27
-
the analog pin input range is 0-1.0v - perhaps your circuit results in voltage always > 1?Jaromanda X– Jaromanda X2018年01月11日 03:10:02 +00:00Commented Jan 11, 2018 at 3:10
-
The ADC works fine when I use system_adc_read(). So, I'm sure the voltage is < 1.Ashish Ranjan– Ashish Ranjan2018年01月11日 03:12:52 +00:00Commented Jan 11, 2018 at 3:12
-
max value of adc_clk_div is 23user97484– user974842024年04月05日 16:26:27 +00:00Commented Apr 5, 2024 at 16:26
1 Answer 1
I created a test circuit using an AC transformer to produce a 50 cycles / second sine wave signal and tried a number of variations on the system_adc_read_fast sample program in the Espressif SDK manual "2C-ESP8266_Non_OS_SDK_API_Reference__EN".
The ESP8266 ADC returned realistic values for adc_clk_div = 8 and 16, but, as you found, the values returned were always 1024 when I tried 32.
I found that the ADC unit was capable of performing ADC conversions in about 6-10 microseconds...
In a test program to collect data for a 40 millisecond period (ie two complete sine waves - I used a diode to chop off the negative halves) I called the system_adc_read_fast function 40 times collecting 116 samples in each call (using "number of samples" = 116).
I collected all the readings in a two-dimensional array before printing any values because the Serial.print function causes long delays between calls to the ADC converter. The "gaps" in the chart represent the changes in the sine wave signal between successive calls to the ADC read function. Chart of ESP8266 ADC values over a 40 millisecond period
-
Wow! Thanks dude. This is awesome. I've been able to verify this myself. Don't know why I missed this in the first place!? Again, thank you so much.Ashish Ranjan– Ashish Ranjan2018年05月22日 16:40:32 +00:00Commented May 22, 2018 at 16:40