Skip to content

ESP32 Min Free Heap Diminished During HTTP Requests #10261

@seansimmons74

Description

@seansimmons74

Board

ESP32 DevKit V1

Device Description

ESP32 DevKit V1, from Upload Terminal output: Chip is ESP32-D0WDQ5-V3 (revision v3.1)
Purchased here

Hardware Configuration

For this example, the only connection to the ESP32 is the Micro USB connector. No debugger or other external connections at this time.

Version

v3.0.4

IDE Name

PlatformIO

Operating System

macOS Sonoma 14.3.1

Flash frequency

40MHz

PSRAM enabled

no

Upload speed

460800

Description

While conducting HTTP requests, I am tracking my min free heap and notice that it drops by quite a bit when I conduct either GET or POST requests. In this simplified version of my code, I am just looping an HTTP POST request to grab a JWT that I generate in the cloud. The message size is always less than 250 characters so it isn't an incoming payload size issue.
This simplified version also outputs Free Heap, Heap Integrity, ESP Free Heap, Min Free Heap, and Task Count in a separate function.
I notice that the initial drop in min free heap is the worst (approx. 50k) and then it is followed by many, small drops (maybe 1k at most) with some later requests resulting in some medium sized drops (around 10k) mixed in. There is also a roughly 45k drop when WiFi connects initially but maybe this is expected?

Am I correct in assuming that the min free heap should "return" to previous levels after the http.end() function is called? Shouldn't this free up resources? What is an "acceptable" min free heap level for the aforementioned operations?

I have added a ton of Serial outputs in the main.cpp file and I have also made some changes in the HTTPClient to hopefully find where the issue may be.

In a less simplistic scenario, I will be conducting POST and GET operations every minute to different endpoints in my cloud along with many other things. This issue is a blocker for future plans as I intend to run multiple FreeRTOS tasks at the same time that handle things aside from those HTTP requests such as reading/writing to an SD card, taking sensor readings, and much more so seeing my min free heap drop by a substantial amount and continue to deplete is preventing me from using valuable resources for other duties.

My hunch as of right now: I believe the issue is buried somewhere in the HTTPClient, NetworkClient, or maybe the WiFi library.

I initially commented on a different issue when I noticed they had a similar drop in heap (issue: #10220)
I also updated to V3.0.4 as suggested in that issue but the problems mentioned above continue.

Finally, thank you to @Jason2866 and @me-no-dev for responding promptly on the #10220 issue. I'm still fairly new to all this and appreciate any help I get.

**EDIT: As requested, I've shortened my sketch here to focus mainly on the HTTP POST. The WiFiConnect() is pretty standard and the getHealth() function prints out heap values as you'll see in the Serial output.

Sketch

////See bottom of this sketch for the changes I made to HTTPClient.cpp

#include <Arduino.h>
#include "WiFi.h"
#include <HTTPClient.h>
#include "ArduinoJson.h"

const char* ssid;
const char* password;
String deviceID;
String userEmail;
char* JWT;

void getJWT() {
  Serial.println("Printing millis() at beginning of HTTP Request Function: " + String(millis()));
  Serial.println("Min Free Heap before getJWT: " + String(esp_get_minimum_free_heap_size()));
  
  char output[200];
  char jwtAPI[] = "https://myapi-api.us-west-2.amazonaws.com/production/"; 

  if (WiFi.status() != WL_CONNECTED) {
      WiFiConnect(ssid, password);
  }
  
  JsonDocument doc;
  doc["uuid"] = deviceID;
  doc["email"] = userEmail;

  serializeJson(doc, output);
  doc.clear();
  Serial.println("output for JWT: " + String(output));

  HTTPClient http; 
  http.begin(jwtAPI);
  http.addHeader("Content-Type", "application/json");

  //Problem is between min free heap check 1 and min free heap check 2
  Serial.println("Min Free Heap before HTTP POST: " + String(esp_get_minimum_free_heap_size()));
  int httpCode = http.POST(output);
  Serial.println("Min Free Heap after HTTP POST: " + String(esp_get_minimum_free_heap_size()));
  //End of area of concern - Notice heap tanks on requests performed and remains stable on remaining items in function
  if (httpCode > 0) {
    if (httpCode == HTTP_CODE_OK) {
      http.end();
      Serial.println("Printing millis() after HTTP Request Success: " + String(millis()));
      Serial.println("Min Free Heap after HTTP Request Success: " + String(esp_get_minimum_free_heap_size()));
      return; 
    } else {
      http.end();
      Serial.println("Printing millis() after HTTP Request Failure: " + String(millis()));
      Serial.println("Min Free Heap after HTTP Request Failure: " + String(esp_get_minimum_free_heap_size()));
      return;    
    }
  } else {
    http.end();
    Serial.println("Min Free Heap after HTTP Code < 1: " + String(esp_get_minimum_free_heap_size()));
    return;
  }
}

void setup() {
  delay(1000);
  pinMode(2,OUTPUT); //LED

  Serial.begin(9600);
  delay(500);
  Serial.println("Serial Test");
  delay(5000);
  Serial.println("ESP32 Arduino Core Version: " + String(ESP_ARDUINO_VERSION));

  ssid = "mywifi";
  password = "mywifipass";
  userEmail = "myemail@gmail.com";
  deviceID = "abc-123-xyz";

  while (true) {
    Serial.println("Printing millis() at top of While loop: " + String(millis()));

    getHealth();
    delay(1000);

    getJWT();
    delay(180000); //adding this delay in for @TD-er
  }
}

void loop() {}


///////////////////Below this line are the edits (Serial prints) I made to the HTTPClient.cpp file to narrow down where the heap issues may be: 

//sendRequest(), roughly line 577:
    Serial.println("Min Free Heap in HTTPClient before if !connect(): " + String(esp_get_minimum_free_heap_size()));
    // connect to server
    if (!connect()) {
      return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
    }
    Serial.println("Min Free Heap in HTTPClient after if !connect(): " + String(esp_get_minimum_free_heap_size()));



//connect(), roughly line 1110.  This was the end of the road for me.  Couldn't serial print anything beyond this point in the NetworkClient.cpp...
////////////
Serial.println("Min Free Heap in HTTPClient.connect() before if client connect(): " + String(esp_get_minimum_free_heap_size()));
  if (!_client->connect(_host.c_str(), _port, _connectTimeout)) {
    log_d("failed connect to %s:%u", _host.c_str(), _port);
    return false;
  } 
   Serial.println("Min Free Heap in HTTPClient.connect() after if client connect(): " + String(esp_get_minimum_free_heap_size()));
///////////

Debug Message

Serial Test
ESP32 Arduino Core Version: 196612
Printing millis() at top of While loop: 6555
Free heap: 253436 :: Heap Integrity: 1 :: ESP Free Heap: 299068 :: Minimum Free Heap: 247768 :: Task Count: 6
Printing millis() at beginning of HTTP Request Function: 7679
Min Free Heap before getJWT: 247752
SSID: mywifi
Password: mywifipass
WiFi Connection Attempt #: 1
WiFi Connected!
output for JWT: {"uuid":"abc-123-xyz","email":"myemail@gmail.com"}
Min Free Heap before HTTP POST: 197712
Min Free Heap in HTTPClient before if !connect(): 197712
Min Free Heap in HTTPClient.connect() before if client connect(): 197712
Min Free Heap in HTTPClient.connect() after if client connect(): 151156
Min Free Heap in HTTPClient after if !connect(): 151156
Min Free Heap after HTTP POST: 151156
Printing millis() after HTTP Request Success: 12524
Min Free Heap after HTTP Request Success: 151156
Printing millis() at top of While loop: 192652
Free heap: 206628 :: Heap Integrity: 1 :: ESP Free Heap: 252260 :: Minimum Free Heap: 151156 :: Task Count: 10
Printing millis() at beginning of HTTP Request Function: 193776
Min Free Heap before getJWT: 151156
output for JWT: {"uuid":"abc-123-xyz","email":"myemail@gmail.com"}
Min Free Heap before HTTP POST: 151156
Min Free Heap in HTTPClient before if !connect(): 151156
Min Free Heap in HTTPClient.connect() before if client connect(): 151156
Min Free Heap in HTTPClient.connect() after if client connect(): 147688
Min Free Heap in HTTPClient after if !connect(): 147688
Min Free Heap after HTTP POST: 147688
Printing millis() after HTTP Request Success: 195419
Min Free Heap after HTTP Request Success: 147688
Printing millis() at top of While loop: 375547
Free heap: 206628 :: Heap Integrity: 1 :: ESP Free Heap: 252260 :: Minimum Free Heap: 147688 :: Task Count: 10
Printing millis() at beginning of HTTP Request Function: 376671
Min Free Heap before getJWT: 147688
output for JWT: {"uuid":"abc-123-xyz","email":"myemail@gmail.com"}
Min Free Heap before HTTP POST: 147688
Min Free Heap in HTTPClient before if !connect(): 147688
Min Free Heap in HTTPClient.connect() before if client connect(): 147688
Min Free Heap in HTTPClient.connect() after if client connect(): 147688
Min Free Heap in HTTPClient after if !connect(): 147688
Min Free Heap after HTTP POST: 147688
Printing millis() after HTTP Request Success: 378295
Min Free Heap after HTTP Request Success: 147688
Printing millis() at top of While loop: 558422
Free heap: 206628 :: Heap Integrity: 1 :: ESP Free Heap: 252260 :: Minimum Free Heap: 147688 :: Task Count: 10
Printing millis() at beginning of HTTP Request Function: 559546
Min Free Heap before getJWT: 147688
output for JWT: {"uuid":"abc-123-xyz","email":"myemail@gmail.com"}
Min Free Heap before HTTP POST: 147688
Min Free Heap in HTTPClient before if !connect(): 147688
Min Free Heap in HTTPClient.connect() before if client connect(): 147688
Min Free Heap in HTTPClient.connect() after if client connect(): 147688
Min Free Heap in HTTPClient after if !connect(): 147688
Min Free Heap after HTTP POST: 147688
Printing millis() after HTTP Request Success: 561191
Min Free Heap after HTTP Request Success: 147688
Printing millis() at top of While loop: 741319
Free heap: 206628 :: Heap Integrity: 1 :: ESP Free Heap: 252260 :: Minimum Free Heap: 147688 :: Task Count: 10
Printing millis() at beginning of HTTP Request Function: 742443
Min Free Heap before getJWT: 147688
output for JWT: {"uuid":"abc-123-xyz","email":"myemail@gmail.com"}
Min Free Heap before HTTP POST: 147688
Min Free Heap in HTTPClient before if !connect(): 147688
Min Free Heap in HTTPClient.connect() before if client connect(): 147688
Min Free Heap in HTTPClient.connect() after if client connect(): 147688
Min Free Heap in HTTPClient after if !connect(): 147688
Min Free Heap after HTTP POST: 147688
Printing millis() after HTTP Request Success: 743867
Min Free Heap after HTTP Request Success: 147688

----end of my serial output----

Other Steps to Reproduce

This is not board specific as I've seen the exact same results on different boards. This is also not a memory fragmentation issue as this seems to happen even on the first HTTP request that the program performs (its my understanding that fragmentation happens after long runtimes). I verified that this is not a POST or GET specific issue as both have this problem.
I have also tried disconnecting WiFi after each request finishes and waiting for 3 minutes before reconnecting as well as throwing http.end() everywhere possible.

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions