Page 1 of 1

Unstable analogRead() when called from background task

Posted: Wed May 22, 2024 12:00 am
by banderies
I have a very strange problem with an ESP32-S3 board I am working on (Espressif ESP32-S3-WROOM-1-N8 (8 MB QD, No PSRAM)).

I have GPIO_NUM_10 (ADC1 CH 9) connected to a 1S LiPo battery via a voltage divider circuit in order to monitor battery voltage. When I call analogRead() within the main program (ie loop()), everything works exactly as expected. However, I have been wanting to move my battery monitoring code to a background process that executes periodically, so I moved my code to a background process using xTaskCreatePinnedToCore(), which I have used for several other process on this same board with no issues. However, the value that gets returned from analogRead() when called from this background process is highly unstable, returning garbage data. When I call analogRead() from both loop() and my background process, the value that comes from loop() is stable and accurate whereas the value that comes from the background process is essentially noise. I was not able to find mention of this issue anywhere and would greatly appreciate it if anyone could share any insight regarding this strange behaviors. Here is the code in question:

Code: Select all

void background_process_battery(void *parameter)
{
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = pdMS_TO_TICKS(BATTERY_REFRESH);
	xLastWakeTime = xTaskGetTickCount();

	for (;;) // a FreeRTOS task should never return
	{
		int raw_read = analogRead(BAT_V_SENSE_PIN);
		float computed_voltage = raw_read * (3.3 / 4096.0) * 1.03 + 0.80; // Seems to best match actual vbat

		log_v("raw_read: %d, computed_value: %f", raw_read, computed_voltage);

		vTaskDelayUntil(&xLastWakeTime, xFrequency); // non-blocking delay
	}
}
And here is the background task code:

Code: Select all

  xTaskCreatePinnedToCore(
      background_process_battery,             /* Function to implement the task */
      "background_process_battery",           /* Name of the task */
      10000,                                  /* Stack size in words */
      NULL,                                   /* Task input parameter */
      0,                                      /* Priority of the task */
      &TaskHandle_background_process_battery, /* Task handle */
      0);                                     /* Core where the task should run */

Re: Unstable analogRead() when called from background task

Posted: Wed May 22, 2024 11:32 am
by liaifat85
You can slightly increase the task priority to see if it stabilizes the readings.

Re: Unstable analogRead() when called from background task

Posted: Wed May 22, 2024 7:03 pm
by lbernstone
What version of arduino-esp32? I recommend setting your voltage divider so that your output voltage runs in the range 0.4-0.8V (10K/2K2, then do the math to get back to the real value). This is in the linear measuring range of the ADC at the lowest attenuation (0db). The following works for me in v3.0.0-rc1 and v2.0.16

Code: Select all

#define BAT_PIN 9

void battery_bg(void *parameter)
{
  while(true)
  {
    Serial.printf("bgread: %lu\n", analogReadMilliVolts(BAT_PIN));
    delay(2000);
  }
}

void setup() {
  Serial.begin(115200);
  analogSetAttenuation(ADC_0db);
  xTaskCreatePinnedToCore(battery_bg, "battery_bg", 3000, NULL, 1, NULL, 0);  
}

void loop() {
  Serial.printf("loopread: %lu\n", analogReadMilliVolts(BAT_PIN));
  delay(1234);
}