What is the external RAM?

The ESP32 chip contains 520KB of RAM. While it’s sufficient for most projects, others may need more memory. To increase the capacity of the microcontroller, the manufacturer can add a memory chip to the board. This external RAM chip is connected to the ESP32 via the SPI bus.

For example, the following boards embed such a chip:

Board External RAM
diymore ESP32 CAM 4 MB
Espressif ESP32-WROVER-KIT 4 MB
HiLetgo ESP32 Camera Module Fisheye 8 MB
KeeYees ESP32-CAM 4 MB
LoLin D32 Pro 8 MB
M5Stack Fire 4 MB
MakerHawk ESP32 Camera 8 MB
TTGO ESP32 Camera 8 MB
TTGO ESP32 WROVER 8 MB
uPesy ESP32 Wrover DevKit 🆕 4 MB

In theory, any SPI memory chip could be used, but in practice, it’s always the same: the ESP-PSRAM32. Because this chip uses a technology known as Pseudostatic RAM (PSRAM), we often use the name “PSRAM” when we should really say “External SPI RAM.”

Using the extended memory requires some extra work from the programmer: you need to call dedicated allocation functions. Instead of the good old malloc(), you must call heap_caps_malloc(MALLOC_CAP_SPIRAM).

How to use the PSRAM with ArduinoJson?

As we just saw, to use the PSRAM, a program must use dedicated allocation functions, which means we cannot use DynamicJsonDocument. Instead, we must use another kind of JsonDocument that calls the appropriate functions.

You can create this new kind of JsonDocument by defining a custom allocator class that you pass as a template parameter to BasicJsonDocument<T>, the base class of DynamicJsonDocument.

The custom allocator must implement two public member functions, allocate() and deallocate(), with the same signatures as malloc() and free().

struct SpiRamAllocator {
  void* allocate(size_t size) {
    return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
  }
  void deallocate(void* pointer) {
    heap_caps_free(pointer);
  }
};

using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;

This snippets defines SpiRamJsonDocument which you can use like any other JsonDocument:

SpiRamJsonDocument doc(1048576);
deserializeJson(doc, input);

You don’t need to do anything else.

See also