adc_continuous_read not behaving as expected
Posted: Mon Mar 18, 2024 4:43 pm
Hi everyone, an absolute newbie (who decided to skip basic "hello_world" examples and go straight to adc dma ) here.
I'm working on a project in which i need to periodically sample sinusoidal signal (f = 50kHz) with a frequency of at least 100kHz. After some research i found out adc dma should allow high sempling frequencies, so consulting documentation available at https://docs.espressif.com/projects/esp ... nuous.html as well as some other examples found on this forum, i tried implementing it myself...
The goal is to have main part of the program that deals with multiplexers (not shown here), once selected mux channel, program is supposed to call function that takes 200 samples of a sine signal and calculates its rms. My idea was for that function to start continuous adc, and read values using adc_continuous_read for 2ms (which should be enough to collect 200 samples at 100ksps) and upon stopping adc calculates rms.
However, it didn't go quite as i planned, so I'd appreciate if any of you could take a look and help me out. I keep getting -1 as output, so apparently i messed something up using continuous read...
Also, am not completely sure about parameters used for configuration of AdcHandle, if i got it right, frame should be composed of 200 conversion results, and length of each should be 4 bytes?
Lastly, can't seem to find the description of ADC_DIGI_OUTPUT_FORMAT_TYPE1, so idk if data read from buffer should be shifted (to obtain only bits relative to raw data) before being converted into voltage values.
Attached is the code, I'm using esp32 Dev_KitC_v4 with Espressif IDE v5.1.2.
Thank you in advance
I'm working on a project in which i need to periodically sample sinusoidal signal (f = 50kHz) with a frequency of at least 100kHz. After some research i found out adc dma should allow high sempling frequencies, so consulting documentation available at https://docs.espressif.com/projects/esp ... nuous.html as well as some other examples found on this forum, i tried implementing it myself...
The goal is to have main part of the program that deals with multiplexers (not shown here), once selected mux channel, program is supposed to call function that takes 200 samples of a sine signal and calculates its rms. My idea was for that function to start continuous adc, and read values using adc_continuous_read for 2ms (which should be enough to collect 200 samples at 100ksps) and upon stopping adc calculates rms.
However, it didn't go quite as i planned, so I'd appreciate if any of you could take a look and help me out. I keep getting -1 as output, so apparently i messed something up using continuous read...
Also, am not completely sure about parameters used for configuration of AdcHandle, if i got it right, frame should be composed of 200 conversion results, and length of each should be 4 bytes?
Lastly, can't seem to find the description of ADC_DIGI_OUTPUT_FORMAT_TYPE1, so idk if data read from buffer should be shifted (to obtain only bits relative to raw data) before being converted into voltage values.
Attached is the code, I'm using esp32 Dev_KitC_v4 with Espressif IDE v5.1.2.
Thank you in advance
Code: Select all
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <sdkconfig.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <esp_adc/adc_continuous.h>
#include <esp_event.h>
#include <nvs_flash.h>
#include <math.h>
#define NUM_SAMPLES 200
#define SAMPLING_FREQ 100000
uint8_t buf [NUM_SAMPLES * SOC_ADC_DIGI_DATA_BYTES_PER_CONV];
uint32_t out_length = 0;
esp_err_t result;
static adc_channel_t channel = 32;
static adc_continuous_handle_t AdcHandle = NULL;
static esp_err_t ADC_Init(adc_channel_t channel, adc_continuous_handle_t *out_handle) {
adc_continuous_handle_cfg_t AdcHandleConfig = {
.max_store_buf_size = 4,
.conv_frame_size = NUM_SAMPLES*SOC_ADC_DIGI_DATA_BYTES_PER_CONV,
};
if (adc_continuous_new_handle(&AdcHandleConfig, &AdcHandle) != ESP_OK) { printf("Failed to create ADC Handle. "); return !ESP_OK; }
adc_continuous_config_t AdcConfig = {
.sample_freq_hz = SAMPLING_FREQ,
.conv_mode = ADC_CONV_SINGLE_UNIT_1,
.format = ADC_DIGI_OUTPUT_FORMAT_TYPE1,
};
adc_digi_pattern_config_t AdcPattern = { 0 };
AdcConfig.pattern_num = 1;
AdcPattern.atten = ADC_ATTEN_DB_11;
AdcPattern.channel = channel & 0x7;
AdcPattern.unit = ADC_UNIT_1;
AdcPattern.bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
AdcConfig.adc_pattern = &AdcPattern;
if (adc_continuous_config(AdcHandle, &AdcConfig) != ESP_OK) { printf("Failed to set ADC Config. "); return !ESP_OK; }
*out_handle = AdcHandle;
// Set Response.
return ESP_OK;
}
float measure (){
int i = 0;
float SumSquared = 0;
float voltage;
adc_continuous_start(AdcHandle);
result = adc_continuous_read(AdcHandle, buf, NUM_SAMPLES*SOC_ADC_DIGI_DATA_BYTES_PER_CONV, &out_length, 2);
if (result == ESP_OK){
adc_continuous_stop(AdcHandle);
for (i=0; i< out_length;i++){
voltage = buf[i] * 3.3 / 2048.;
SumSquared += voltage*voltage;
}
return sqrt(SumSquared/out_length);
}
else
return -1;
}
void app_main(void)
{
ADC_Init(channel, &AdcHandle);
float result;
while (1) {
result = measure();
printf("RMS value: %f\n", result);
sleep(1);
}
}