Continuous ADC reading with bare esp32-wroom-32 and sending the results to web. PROBLEM
Posted: Thu Sep 12, 2019 1:27 pm
Hello guys!
I want to measure a 4kHZ frequency with my bare ESP32 chip with it's internal ADC and then send the results to it's web server for chartJS.
Everything is working properly, except the continuous part.
My basic idea for the ADC was that:
- Create a task on the 0th core for the adc reading function.
- Measure the 4khz external signal ( from a signal generator for now ) at 8khz in a loop in that task with disabled interrupts on core 0.
- Create a fast function ( on core 1 ) for reading the measured data at some interval ( like 0.5 sec or it doesn't matter ) from the adc
buffer for further working.
- Create a normal function ( on core 1 ) to send the data to web ChartJS for visualization at modifiable intervals ( 1 to 10 sec, depends
on the user settings).
The idea in my code:
The problem:
Like this the measure function is measuring 100 datas at once and wait delay(1) and god knows how many milisec while it is turning back into the measure function again to measure that 100 data again. The problem is that is not async and not continous. The program can not do anything else during the measure and if it is done , it has to wait because of the watchdog timer and other task that runs on the core0 background. I attached a some pictures how the data looks on the web like this. It is fine, just not continous.
I want to measure a 4kHZ frequency with my bare ESP32 chip with it's internal ADC and then send the results to it's web server for chartJS.
Everything is working properly, except the continuous part.
My basic idea for the ADC was that:
- Create a task on the 0th core for the adc reading function.
- Measure the 4khz external signal ( from a signal generator for now ) at 8khz in a loop in that task with disabled interrupts on core 0.
- Create a fast function ( on core 1 ) for reading the measured data at some interval ( like 0.5 sec or it doesn't matter ) from the adc
buffer for further working.
- Create a normal function ( on core 1 ) to send the data to web ChartJS for visualization at modifiable intervals ( 1 to 10 sec, depends
on the user settings).
The idea in my code:
Code: Select all
/** ANALOG DIGITAL CONVERTER SETTINGS **/
#define CHANNEL 34
//uint16_t offset = 1757; //middle DC level reading (unused)
uint16_t vReal[200];
double samplingFrequency = 80000;
unsigned long microseconds;
unsigned int sampling_period_us = round(1000000*(1.0/samplingFrequency));
uint16_t samples = 100;
/* VARIABLES */
long getfastdatamillis;
uint16_t vRealBuff[100];
boolean FastGetData = false;
int Frissit = 10000; // Refresh rate of the send data function
/* ACTUAL ADC READ FUNCTION */
static const inline void ADC_Meres() {
if (olvasunk_e == true) { // User can turn on/off the read on the web
microseconds = micros(); // Starting micros for the sampling period
uint32_t volatile register ilevel = XTOS_DISABLE_ALL_INTERRUPTS; // Disable everything that can interrupt the measurement
for (int i = 0; i < samples; i++) { // Start Sampling
vReal[i] = analogRead(CHANNEL); // Read analog to buffer
while (micros() - microseconds < sampling_period_us) {} // Wait for sampling period us for 8Khz
microseconds += sampling_period_us;
}
XTOS_RESTORE_INTLEVEL(ilevel); // Restore Interrupts
}
}
/* Fast get data from the vReal buffer for data processing */
void IRAM_ATTR Fast_Get_Data(){
FastGetData = false;
int hanyadik = 0;
int nulla = 0;
portENTER_CRITICAL_ISR(&timerMux); // Critical section for fast reading from buffer to buffer
olvasunk_e = false; // Turn off actual ADC measure function for read the current datas
for(int i = 0;i < adatszelessegint;i++){ // Start filling the process buffer (vRealBuff) while cheking it with user adjustable
u16_t Szuro = vReal[i]; // minimum data. ( default is 0 )
if(Szuro >= MinErtek){
for(hanyadik;hanyadik < 200;hanyadik++){
vRealBuff[nulla] = vReal[hanyadik];
nulla++;
}
break;
}
hanyadik++;
}
olvasunk_e = true;
portEXIT_CRITICAL_ISR(&timerMux);
FastGetData = true;
}
/* Sending the data to the web with webSocket for fast sending in "json" form. */
static inline void Send_Data(){
if(FastGetData == true){
for (int i = 0; i < adatszelessegint; i++) {
String json = "";
json += String(vRealBuff[i] / (float)40.95);
json += "}";
if(Nemkell == false){
webSocket.broadcastTXT(json.c_str(), json.length());
}
}
FastGetData = false;
}
}
void setup(){
/* Create a task on core0 for the adc read function. */
xTaskCreatePinnedToCore ( loop0, "v_getIMU0", 30000, NULL, 10, &TaskHandle_2, 0 );
/* Starting millis for the fast get data */
getfastdatamillis = millis();
}
/* loop0 task on core0 for the ADC read function. */
static void loop0(void * pvParameters){
for( ;; ){
vTaskDelay(1); // REQUIRED TO RESET THE WATCH DOG TIMER
ADC_Meres(); // 8Khz ANALOG READ
if(millis() - getfastdatamillis >= Frissit){
getfastdatamillis = millis();
Fast_Get_Data();
}
}
}
void loop(){
currentMillis = millis();
if (currentMillis - getNullMag >= Frissit)
{
Send_Data();
getNullMag = currentMillis;
}
}
Like this the measure function is measuring 100 datas at once and wait delay(1) and god knows how many milisec while it is turning back into the measure function again to measure that 100 data again. The problem is that is not async and not continous. The program can not do anything else during the measure and if it is done , it has to wait because of the watchdog timer and other task that runs on the core0 background. I attached a some pictures how the data looks on the web like this. It is fine, just not continous.