External ADC Question
External ADC Question
Is anybody used an external adc with esp32?
I want to use the MCP33131D SPI adc.
https://www.microchip.com/wwwproducts/en/MCP33131D-10
Any toughts?
I want to use the MCP33131D SPI adc.
https://www.microchip.com/wwwproducts/en/MCP33131D-10
Any toughts?
-
- Posts: 166
- Joined: Wed Aug 01, 2018 12:06 pm
Re: External ADC Question
How is it better then
?The ESP32 integrates two 12-bit SAR (Successive Approximation Register) ADCs supporting a total of 18 measurement channels (analog enabled pins).
https://docs.espressif.com/projects/esp ... s/adc.html
Re: External ADC Question
ESP's internal ADC is crap in itself.
I can not measure properly in it.
I was used the adc1 with i2s dma before, and the signal was noisy A.F.
I realized that i need to pull the gpio36 and 39 down because of the noise.
So i lost two pins because of just that.
After that i realized that if i get any interrupt on any of the ADC1 pins, the i2s goes crazy.
So if i want to read analog values with the internal adc i have to use all the channels just for that.
This is not satisfying at all.
I can not measure properly in it.
I was used the adc1 with i2s dma before, and the signal was noisy A.F.
I realized that i need to pull the gpio36 and 39 down because of the noise.
So i lost two pins because of just that.
After that i realized that if i get any interrupt on any of the ADC1 pins, the i2s goes crazy.
So if i want to read analog values with the internal adc i have to use all the channels just for that.
This is not satisfying at all.
-
- Posts: 166
- Joined: Wed Aug 01, 2018 12:06 pm
Re: External ADC Question
I get great results from the built in A:D's
and an example of the way I am using the ADC.
and an example of the way I am using the ADC.
Code: Select all
#include <driver/adc.h>
setup()
{
// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
// set up A:D channels
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);
// adc1_config_width(ADC_WIDTH_12Bit);
// adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_11db);
/*
When VDD_A is 3.3V: 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.3V
*/
}
////
void TaskAnalogVoltRead_LIDAR( void *pvParameters )
{
// String localBuffer;
// localBuffer.reserve ( StringBufferSize300 );
int iBit = 1;
float ADbits = 4095.0f;
float offSET = 1.0f;
float r1 = 100800.0f; // R1 in ohm, 100k = 100,800.0 //
float r2 = 38780.0f; // R2 in ohm, 38k = 38000.0 //actual 38780K
float uPvolts = 3.3f;
// ADC1 channel 0 is GPIO36
// ADC1 channel 1 is GPIO37
// ADC1 channel 6 is GPIO34
// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
// to get resistor R2 go to:
// http://www.ohmslawcalculator.com/voltage-divider-calculator
// used 12 volts for the input voltage to calculate R2, used 100K for R1
for (;;)
{
// group handle, WaitForBits, ClearOnExitBit, WaitForAllBits, TicksToWait
xEventGroupWaitBits( eg, evtAnalogVoltReadTask_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY );
// // read the input
iBit = iBit << 1;
// // Serial.println ( iBit );
if ( iBit == 1073741824 )
{
if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
{
ptrVbatt_LIDAR[0] += ( ((( uPvolts * adc1_get_raw(ADC1_CHANNEL_6)) / ADbits) / r2 * ( r1 + r2)) + offSET );
ptrVbatt_LIDAR[0] = ptrVbatt_LIDAR[0] / 2; // average readings
} // if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
iBit = 1;
} // if ( iBit == 1073741824 )
}
vTaskDelete( NULL );
}
-
- Posts: 32
- Joined: Sun Nov 25, 2018 10:05 pm
- Contact:
Re: External ADC Question
I just posted some code for ADC readings for the ESP32.
It takes values from an array and smooths them out.
viewtopic.php?f=18&t=13053
I get good results after smoothing out the values and using 0.1 uF capacitors.
See this in Espressif documentation:
https://docs.espressif.com/projects/esp ... s/adc.html
Multisampling and capacitors help a lot.
Idahowalker's advice that I got a while back about using the code in post I mentioned above is also good versus using analogRead commands of Arduino IDE.
It takes values from an array and smooths them out.
viewtopic.php?f=18&t=13053
I get good results after smoothing out the values and using 0.1 uF capacitors.
See this in Espressif documentation:
https://docs.espressif.com/projects/esp ... s/adc.html
Multisampling and capacitors help a lot.
Idahowalker's advice that I got a while back about using the code in post I mentioned above is also good versus using analogRead commands of Arduino IDE.
- Attachments
-
- Photodiodes ADC values with .1 uF capacitors.jpg (2.43 MiB) Viewed 12472 times
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2
https://grabcad.com/has-2
-
- Posts: 166
- Joined: Wed Aug 01, 2018 12:06 pm
Re: External ADC Question
Also, I found that by sampling the ADC regularly once a mS or so, and applying the Simple Kalman filter to the results https://github.com/denyssene/SimpleKalmanFilter, the output gets real smooth. Even if the A:D converter values are not displayed regularly, like once a second, getting several readings per second and apply the simple Kalman with each sampling does a real good job.
The simple Kalman results are better with an accurate time between iterations.
Here I use the time of task iteration.
Here I use the 64 bit ESP32 uS clock to get time iterations.
The simple Kalman results are better with an accurate time between iterations.
Here
Code: Select all
SimpleKalmanFilter X_KF( (float)iX_Posit90, (float)iX_Posit90, float(ServoDelay12mS) / 1000.0f );
Here I use the 64 bit ESP32 uS clock to get time iterations.
Code: Select all
void fDo_AudioReadFreq( void *pvParameters )
{
int64_t EndTime = esp_timer_get_time();
int64_t StartTime = esp_timer_get_time(); //gets time in uSeconds like Arduino Micros
for (;;)
{
xEventGroupWaitBits (eg, evtDo_AudioReadFreq, pdTRUE, pdTRUE, portMAX_DELAY);
EndTime = esp_timer_get_time() - StartTime;
// the other code stuff thing do's
// and more code thing do's
// and even more code thing do's
StartTime = esp_timer_get_time();
// }
}
vTaskDelete( NULL );
} // fDo_ AudioReadFreq( void *pvParameters )
Re: External ADC Question
I was using the adc with i2s dma. My code looks like this:
I2S config:
Read from DMA BUFFER and plot the results to web:
The problem with this is that i can not do anything on that core. And the results are noisy.
I don't know how the task semaphores or the task events are working.
I2S config:
Code: Select all
void configure_i2s(){
//pinMode(36,INPUT);
i2s_config_t i2s_config =
{
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN), // I2S receive mode with ADC
.sample_rate = 144444, // sample rate
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // 16 bit I2S
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, //I2S_CHANNEL_FMT_ALL_LEFT, // only the left channel
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), // I2S format
.intr_alloc_flags = 0, // none
.dma_buf_count = 2, // number of DMA buffers
.dma_buf_len = 1024, // number of samples
.use_apll = 0, // no Audio PLL
};
adc1_config_channel_atten(ADC_CHANNEL, ADC_ATTEN_11db);
adc1_config_width(ADC_WIDTH_12Bit);
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_adc_mode(ADC_UNIT_1, ADC_CHANNEL);
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL2_REG, SYSCON_SARADC_SAR1_INV);
i2s_adc_enable(I2S_NUM_0);
vTaskDelay(3000/portTICK_RATE_MS);
}
Code: Select all
static const inline void Plot_DMA_Buffer(){
int Vmax = 0;
int Vmin = 4095;
uint16_t Buffer[NUM_SAMPLES];
for(int i = 0;i<NUM_SAMPLES;i++){
Buffer[i] = i2s_read_buff[i];
if(i != NUM_SAMPLES)
{
if((i2s_read_buff[i]<i2s_read_buff[i+1])&&i2s_read_buff[i]<Vmin){
if(constrain(i2s_read_buff[i],Vmin-300,Vmin+300)){
Vmin = i2s_read_buff[i];
}
}else if((i2s_read_buff[i]>i2s_read_buff[i+1])&&i2s_read_buff[i]>Vmax){
if(constrain(i2s_read_buff[i],Vmax-300,Vmax+300)){
Vmax = i2s_read_buff[i];
}
}
}
}
int Vamp = (Vmax) - (Vmin);
if(millis() - Start_Millis >= 1000){
Start_Millis = millis();
Send_Amplitude(Vamp);
if(olvasunk_e){
for(int k = 0;k<NUM_SAMPLES;k++){
if(!olvasunk_e){
break;
}else{
String data = (String)Buffer[k]+"}";
webSocket.broadcastTXT(data.c_str(), data.length());
}
}
}
}
}
Code: Select all
static const inline void Base_Setups_Core1(){
Serial.begin(115200);
SPIFFS.begin() ? Serial.println("SPIFFS.OK") : Serial.println("SPIFFS.FAIL");
configure_i2s();
/** Ethernet wifi stack **/
WiFi.onEvent(WiFiEvent);
ETH_begin();
ethernet.config(ip1, nm1, gw1);
TCP_Requests();
server.begin();
ws.onEvent(onWsEvent);
server.addHandler(&ws);
External_Interrupts();
xTaskCreatePinnedToCore ( loop0, "v_getIMU0", 1024, NULL, 0, &TaskHandle_1, 1 );
xTaskCreatePinnedToCore ( loop1, "v_getIMU1", 15048, NULL, 0, &TaskHandle_2, 0 );
}
static const inline void Main_Loop(){
if(!Ota_is_Started){
Plot_DMA_Buffer(); // RETRIVE DATA FROM i2s_read_buff FOR CALCULATION AND VISUALIZATION / COMPUTE THE AVERAGE AMPLITUDE
}
}
static void loop0(void * pvParameters){
for( ;; ){
i2s_read(I2S_NUM_0, (char*)i2s_read_buff,NUM_SAMPLES * sizeof(uint16_t), &bytes_read, portMAX_DELAY);
}
}
I don't know how the task semaphores or the task events are working.
- jgustavoam
- Posts: 165
- Joined: Thu Feb 01, 2018 2:43 pm
- Location: Belo Horizonte , Brazil
- Contact:
Re: External ADC Question
Hi,
If you are interested, take a look at my project.
ESP32 Digital Voltmeter
https://www.elektormagazine.com/labs/es ... -voltmeter
https://github.com/Gustavomurta/ESP32-DVM
ESP32 - Digital Voltmeter using old style ADC conversion method. High precision, good stability , negative and positive Voltages !
Range -2V to +2V . Method of Voltage measurement - Dual slope integrating ADC conversion. Sample rate = 12 samples/sec.
TLC7135 is a high precision monolithic 4 1/2 digit A/D converter. Dual slope conversion reliability
is combined with ±1 in 20,000 count accuracy and a 2.0000V full scale capability. It features high impedance differential inputs, nearly ideal differential linearity, true ratiometric operation, auto zero and auto-polarity.
If you are interested, take a look at my project.
ESP32 Digital Voltmeter
https://www.elektormagazine.com/labs/es ... -voltmeter
https://github.com/Gustavomurta/ESP32-DVM
ESP32 - Digital Voltmeter using old style ADC conversion method. High precision, good stability , negative and positive Voltages !
Range -2V to +2V . Method of Voltage measurement - Dual slope integrating ADC conversion. Sample rate = 12 samples/sec.
TLC7135 is a high precision monolithic 4 1/2 digit A/D converter. Dual slope conversion reliability
is combined with ±1 in 20,000 count accuracy and a 2.0000V full scale capability. It features high impedance differential inputs, nearly ideal differential linearity, true ratiometric operation, auto zero and auto-polarity.
Retired IBM Brasil
Electronic hobbyist since 1976.
Electronic hobbyist since 1976.
Who is online
Users browsing this forum: No registered users and 86 guests