Suddenly demanding SD library, and there's a conflict

My ESP Now Receiver program is running like a champ, but MAGENTA is too dark. I wanted to change the color.
While I was at it, I tried to add a non-GFX font. It didn’t work, so I deleted all of that stuff. but in the process i had to add the SD library. This TFT has an SD slot, but I’m not using it.
I plan to use SPIFFS to datalog pressure. But I’m not there yet.

But when I put the SD library back into .ini, there’s a conflict. Says wrong platform.

Can you tell me why it’s demanding SD? All of a sudden?
How can I make it stop?

Here’s the code:

#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>
#include "ESPAsyncWebServer.h"
#include <Arduino_JSON.h>
#include "Adafruit_GFX.h"
#include "Fonts/FreeSans9pt7b.h"
#include <MCUFRIEND_kbv.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

#define NTP_OFFSET -14400      // In seconds
#define NTP_INTERVAL 60 * 1000 // In miliseconds
#define NTP_ADDRESS ""
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define BLACK 0x0000
#define PURPLE 0x780F
#define PINK 0xFC9F
#define PINK1 0xF8FF
#define AQUA 0x04FF

// Replace with your network credentials (STATION)
const char *ssid = "TP-Link_7C28";
const char *password = "64411811";

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message
  int id;
  float temperature;
  float humidity;
  float pressure;
  float Gas;
  float CO;
  float smoke;
  float moisture;
  float UV;
  float CO2;
  float NH3;
  float NO2;
  float VOC;
  float TVOC;
  float H2;
  float EtOH;
  int readingId;
} struct_message;

struct_message incomingReadings;

MCUFRIEND_kbv tft;

JSONVar board;

AsyncWebServer server(80);
AsyncEventSource events("/events");

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *incomingData, int len)
  // Copies the sender mac address to a string
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",

           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));

  board["id"] =, len;
  board["temperature"] = incomingReadings.temperature;
  board["humidity"] = incomingReadings.humidity;
  board["pressure"] = incomingReadings.pressure;
  board["Gas"] = incomingReadings.Gas;
  board["CO"] = incomingReadings.CO;
  board["smoke"] = incomingReadings.smoke;
  board["moisture"] = incomingReadings.moisture;
  board["UV"] = incomingReadings.UV;
  board["CO2"] = incomingReadings.CO2;
  board["NH3"] = incomingReadings.NH3;
  board["NO2"] = incomingReadings.NO2;
  board["VOC"] = incomingReadings.VOC;
  board["TVOC"] = incomingReadings.TVOC;
  board["H2"] = incomingReadings.H2;
  board["EtOH"] = incomingReadings.EtOH;
  board["readingId"] = incomingReadings.readingId;
  Serial.printf("Board ID %u: %u bytes\n",, len);

  String jsonString = JSON.stringify(board);
  events.send(jsonString.c_str(), "new_readings", millis());

const char index_html[] PROGMEM = R"rawliteral(
  <title>Monster Laboratories Smart Home</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <link rel="icon" href="data:,">
    html {font-family: Arial; display: inline-block; text-align: center;}
    p {  font-size: 1.2rem;}
    body {  margin: 0;}
    .topnav { overflow: hidden; background-color: #2f4468; color: white; font-size: 1.7rem; }
    .content { padding: 20px; }
    .card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
    .cards { max-width: 3500px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
    .reading { font-size: 2.8rem; }
    .packet { color: #bebebe; }
    .card.temperature { color: #fd7e14; }
    .card.humidity { color: #1b78e2; }
    .card.pressure { color: #17b8e2; }
    .card.UV { color: #17b8e2; }

  <div class="topnav">
    <h3>Monster Laboratories SmartHome- Air Quality</h3>

  <div class="content">
    <div class="cards">
      <div class="card temperature">
        <h4><i class="fas fa-thermometer-half"></i> Pod 1 - TEMPERATURE</h4>
        <p><span class="reading"><span id="t1"></span> &deg;C</span></p>
        <p class="packet">Reading ID: <span id="rt1"></span></p>

       <div class="card humidity">
        <h4><i class="fas fa-tint"></i> Pod 1 - HUMIDITY</h4>
        <p><span class="reading"><span id="h1"></span> &percnt;</span></p>
        <p class="packet">Reading ID: <span id="rh1"></span></p>
      <div class="card pressure">
        <h4><i class="fas fa-tint"></i> Pod 1 - PRESSURE</h4>
        <p><span class="reading"><span id="p1"></span> "Hg</span></p>
        <p class="packet">Reading ID: <span id="rp1"></span></p>

      <div class="card temperature">
        <h4><i class="fas fa-thermometer-half"></i> Pod 3 - TEMPERATURE</h4>
        <p><span class="reading"><span id="t3"></span> &deg;C</span></p>
        <p class="packet">Reading ID: <span id="rt3"></span></p>
      <div class="card UV">
        <h4><i class="fas fa-tint"></i> Pod 3 - UVindex</h4>
        <p><span class="reading"><span id="u1"></span> ... </span></p>
        <p class="packet">Reading ID: <span id="ru1"></span></p>

      <div class="card pressure">
        <h4><i class="fas fa-tint"></i> Pod 3 - PRESSURE</h4>
        <p><span class="reading"><span id="p3"></span> "Hg</span></p>
        <p class="packet">Reading ID: <span id="rp3"></span></p>

if (!!window.EventSource) {
 var source = new EventSource('/events');
 source.addEventListener('open', function(e) {
  console.log("Events Connected");
 }, false);
 source.addEventListener('error', function(e) {
  if ( != EventSource.OPEN) {
    console.log("Events Disconnected");
 }, false);
 source.addEventListener('message', function(e) {
 }, false);
 source.addEventListener('new_readings', function(e) {
  var obj = JSON.parse(;

  document.getElementById("t" = obj.temperature.toFixed(0);
  document.getElementById("h" = obj.humidity.toFixed(0);
  document.getElementById("p" = obj.pressure.toFixed(0);
  document.getElementById("u" = obj.UV.toFixed(0);

  document.getElementById("rt" = obj.readingId;
  document.getElementById("rh" = obj.readingId;
  document.getElementById("rp" = obj.readingId;
  document.getElementById("ru" = obj.readingId;

 }, false);

void setup()
  uint16_t ID = tft.readID();

  // Set the device as a Station and Soft Access Point simultaneously

  // Set device as a Wi-Fi Station
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
    Serial.println("Setting as a Wi-Fi Station..");

  IPAddress local_IP(192, 168, 0, 100);
  Serial.print("Station IP Address: ");
  Serial.print("Wi-Fi Channel: ");

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK)
    Serial.println("Error initializing ESP-NOW");

  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send_P(200, "text/html", index_html); });

  events.onConnect([](AsyncEventSourceClient *client)
    if (client->lastId())
      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
    // send event with message "hello!", id current millis
    // and set reconnect delay to 1 second
    client->send("hello!", NULL, millis(), 10000); });


void loop()
String formattedTime = timeClient.getFormattedTime();

tft.setCursor(1, 20);
tft.print("Station IP : ");
if( == 1){
else if ( == 2){
else if ( == 3){
tft.print("Time: ");
tft.print("Board ID:    ");
tft.print("Temperature: ");
tft.print(incomingReadings.temperature, 1);
tft.println(" °C");
tft.print("Pressure:    ");
tft.print(incomingReadings.pressure, 0);
tft.println(" in Hg");
tft.print("Humidity:    ");
tft.print(incomingReadings.humidity, 0);
tft.println(" %");
tft.print("CO:           ");
tft.print(incomingReadings.CO, 0);
tft.println(" PPM");

tft.print("LPG:         ");
tft.print(incomingReadings.Gas, 0);
tft.println(" PPM");

tft.print("Smoke:     ");
tft.println(incomingReadings.smoke, 0);
tft.print("Uv index:   ");
tft.println(incomingReadings.UV, 0);
tft.print("CO2:         "),
tft.print(incomingReadings.CO2, 0);
tft.println(" PPM");
tft.print("VOC:         ");
tft.print(incomingReadings.VOC, 0);
tft.println(" PPM");
tft.print("TVOC:       ");
tft.print(incomingReadings.TVOC, 0);
tft.println(" PPM");
tft.print("H2:            ");
tft.print(incomingReadings.H2, 0);
tft.println(" PPM");
tft.print("EtOH:        ");
tft.print(incomingReadings.EtOH, 0);
tft.println(" PPM");
tft.print("NH3:         "),
tft.print(incomingReadings.NH3, 0);
tft.println(" PPM");
tft.print("NO2:         "),
tft.print(incomingReadings.NO2, 0);
tft.println(" PPM");
tft.print("Reading ID:  ");
Serial.print("Pressure:    ");
Serial.print(incomingReadings.pressure, 0);
Serial.println(" in Hg");

static unsigned long lastEventTime = millis();
static const unsigned long EVENT_INTERVAL_MS = 5000;
if ((millis() - lastEventTime) > EVENT_INTERVAL_MS)
        events.send("ping", NULL, millis());
        lastEventTime = millis();

Archiving .pio\build\esp32dev\libFrameworkArduinoVariant.a
In file included from .pio/libdeps/esp32dev/ESP32-TFT-Library-ILI9486/src/tft.cpp:3:
.pio/libdeps/esp32dev/ESP32-TFT-Library-ILI9486/src/tft.h:7:10: fatal error: SD.h: No such file or directory

This is the error when SD library is in .ini:
Compiling .pio\build\esp32dev\lib181\SD\utility\SdFile.cpp.o
*** [.pio\build\esp32dev\lib181\SD\File.cpp.o] Error 1
*** [.pio\build\esp32dev\lib181\SD\SD.cpp.o] Error 1
*** [.pio\build\esp32dev\lib181\SD\utility\Sd2Card.cpp.o] Error 1
In file included from .pio/libdeps/esp32dev/SD/src/utility/Sd2Card.h:26,
from .pio/libdeps/esp32dev/SD/src/utility/SdFat.h:29,
from .pio/libdeps/esp32dev/SD/src/utility/SdFile.cpp:20:
.pio/libdeps/esp32dev/SD/src/utility/Sd2PinMap.h:524:2: error: #error Architecture or board not supported.
#error Architecture or board not supported.
*** [.pio\build\esp32dev\lib181\SD\utility\SdFile.cpp.o] Error 1

SD libraries are tricky because they all have the same name… “SD”. However, if you just add SD into the lib_deps, and not arduino-libraries/SD@^1.2.4 juding by the

error, PlatformIO should pick up the correct library, that is, C:\Users\<user>\.platformio\packages\framework-arduinoespressif32\libraries\SD. Make sure to also remove the .pio folder of the project to get a clean build again.

It’s an Arduino library, so not hard to track down.
But I don’t need it.
I’m not doing anything with an SD card.

If you don’t provide the library, compilation of that other library will probably fail, even if you do lib_ignore = SD.

What’s the full platformio.ini.

But it fails either way, with or without SD.

platform = espressif32
board = esp32dev
framework = arduino
debug_tool = esp-prog
debug_init_break = tbreak setup
lib_deps = 
	adafruit/Adafruit GFX Library @ ^1.10.7

Replace that with just


and remove the .pio folder of the project and build again. Does it make a difference?

It’s the principle of the thing. This program runs perfectly without SD. It never wanted SD until I tried to add a non-GFX font.
Something about the TFT called attention to SD cards.
I’m going to paste this code in to a new file and it will compile just fine without SD. But I don’t want to do that.

Yes, using SD worked. It built fine.

Sadly, as soon as library does #include <SD.h> and you don’t have that library added in the build system, compilation will fail even if you don’t use the aspect. That’s the nature of the compilation process.