ESP_LOG not working on Wemos-S2-Mini but fine on S3 Devkit?

In the category of “other things I burned half a day trying to figure out on my own”… ESP_LOG messages not printing out to monitor with Wemos_S2_Mini.

Since I have been chasing my tail for several weeks trying to get ULP stuff going and have loaded all sorts of expressif stuff, I decided to do a clean reinstall of I did a clean re-install of VSC and PlatformIO. (I removed the VSC app, deleted my c:\users\myname.platformio and .vscode directories, rebooted, and reinstalled VSC using VSCodeUserSetup-x64-1.80.0.exe) I then added in my usual extensions: PlatformIO, Better C++ Syntax, C/C++, C/C++ Extension Pack (which includes: C/C++ Themes, CMake, CMake Tools), Colorful Comments, Diff Tool, indent-rainbow, and Remove Comments.

Now I am running code using the same platformio.ini I usually use and suddenly none of my ESP_LOG messages display on the monitor yet Serial.println() works fine. I am running a Wemos_S2_Mini for which everything else works fine.

So, after first writing this, I decided to try an S3-Devkit card and, with the appropriate platformio.ini, ESP_LOG messages display just fine.

Here is the test code for the Wemos_S2_Mini (which comes up as lolin_s2_mini when starting a new project and selecting the Wemos_S2_Mini. Is there something special about the S2 that I’m not finding on the internet which would keep the ESP_LOG messages from printing?

platformio.ini:

[env:lolin_s2_mini]
platform = espressif32
board = lolin_s2_mini
framework = arduino
monitor_speed = 115200
build_flags = 
	-DCORE_DEBUG_LEVEL=5

Minimal code example:

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }

  delay(5000); // give me time to start the monitor
}

void loop()
{
  static const char *TAG = "loop";
  delay(1000);
  ESP_LOGD(TAG, "LogD");
  ESP_LOGE(TAG, "LogE");
  ESP_LOGI(TAG, "LogI");
  Serial.println("Just a Serial.println");
}

This displays (onlY):

Just a Serial.println
Just a Serial.println
Just a Serial.println
Just a Serial.println

Any clues? Thank you.

It could be the case that the default debug serial is different on an S2 or S3, or their build flags are different (e.g., one might do UART output to a usb-to-serial chip, the other one might be doing native USB CDC).

In any case, just like with the Arduino ESP8266 core, a HardwareSerial type object has the

function, so maybe you just need to call

Serial.setDebugOutput(true);

in setup() to make output appear there?

I have the same problem with this board, using arduino framework. I’ve not had this problem with the various other esp32, esp32s3, esp32c3 boards I’ve used. Since this is the only esp32s2 board I’ve used, I don’t know if it’s something about the s2, the framework support, or this particular board.

Problem: I see no logs on serial monitor when calling ESP_LOGE. I don’t see the usual boot logs either. However Serial.print does work. I have USB CDC enabled and Core Debug Level set appropriately.

I tried the setDebugOutput(true) suggested here but that made no difference.

Since I prefer using the native esp logging anyway, I was able to work around the problem like this:

#define USE_ESP_IDF_LOG

#include <Arduino.h>

int serial_vprintf(const char *format, va_list args) {
  return Serial.vprintf(format, args);
}

void setup() {
  esp_log_set_vprintf(serial_vprintf);
  Serial.begin();
}

void loop() {
  delay(2000);
  ESP_LOGE("Test", "ESP_LOGE %s", "test");
}

Of course I still don’t see the boot logs.

I had the same issue. Here is the solution:

@jr4 Amazingly, all of a sudden my logging changed again. And I waste another afternoon trying to get my ESP_LOGD, etc working again. Your very logical solution above did not work though.

I can’t understand how things just suddenly change from one day to the next with the framework such that simple things like this worked one day and the EXACT SAME CODE built the next day has totally different boot logs and loses the ESP_LOG function…SIGH!!!

I did find the following finally worked…

#include <Arduino.h>

#define LOG_LOCAL_LEVEL  ESP_LOG_DEBUG  // this overrides CONFIG_LOG_MAXIMUM_LEVEL setting in menuconfig
                                        // and must be defined before including esp_log.h
#define MY_GLOBAL_DEBUG_LEVEL  ESP_LOG_DEBUG
#include "esp_log.h"


void setup()
{
  static const char *TAG = "setup";
  esp_log_level_set("*", MY_GLOBAL_DEBUG_LEVEL); // Set log level to include ESP_LOGD messages
...
}

void loop()
{
  static const char *TAG = "loop";
  esp_log_level_set("*", MY_GLOBAL_DEBUG_LEVEL); // Set log level to include ESP_LOGD messages
...
}

// and similar for all functions which need to use ESP_LOG*

Isn’t it amazing how these simple things can get complicated?

In order to get logging working properly, I had to do the following:

This is my main.cpp:

#include <Arduino.h>

#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG // this overrides CONFIG_LOG_MAXIMUM_LEVEL setting in menuconfig
                                      // and must be defined before including esp_log.h
#define MY_GLOBAL_DEBUG_LEVEL ESP_LOG_DEBUG
#include "esp_log.h"

void setup()
{
    static const char *TAG = "setup";
    esp_log_level_set("*", MY_GLOBAL_DEBUG_LEVEL); // Set log level to include ESP_LOGD messages
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    ESP_LOGE(TAG, "This is an error message");
}

void loop()
{
    static const char *TAG = "loop";
    esp_log_level_set("*", MY_GLOBAL_DEBUG_LEVEL); // Set log level to include ESP_LOGD messages
    ESP_LOGV(TAG, "This is an verbose message");
    ESP_LOGD(TAG, "This is an debug message");
    ESP_LOGI(TAG, "This is an info message");
    ESP_LOGW(TAG, "This is an warn message");
    ESP_LOGE(TAG, "This is an error message");
    delay(1000);
}

Note the

Serial.setDebugOutput(true);

If you omit this, no output is generated at all (at least for me).

However, in order to see more than just the error messages, you also need to add the following to the build_flags in platformio.ini

build_flags = 
	-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE

(ARDUHAL_LOG_LEVEL_VERBOSE equals to 5)

This was tested on a LolinS2-mini.

However, what I actually wanted to achieve was to redirect the log output to some non-standard Serial output, because I want to use the USB-Serial for other purposes. If someone stumbles over this thread (likely me, in 2 years…), here’s what needs to be done:

platformio.ini:

[platformio]
default_envs = lolin_s2_mini

[common]  

[env:lolin_s2_mini]
platform = espressif32
framework = arduino
monitor_speed = 115200
upload_speed = 115200
lib_ldf_mode = deep
board = lolin_s2_mini
upload_port = COM11
monitor_port = COM10

build_flags = 
	-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE

And here is my main.cpp:

#include <HardwareSerial.h>
#include "esp_log.h"

#define RXPIN 3             // Define the RX pin
#define TXPIN 5             // Define the TX pin
#define BAUDRATE 115200     // define speed. It must be the same as in platformio.ini->monitor_speed
#define LOG_BUFFER_SIZE 256 // Define the log buffer size

HardwareSerial AuxSerial(1);

/**
 * @brief Outputs a formatted log message to the auxiliary serial interface.
 *
 * This function formats a log message using a variable argument list and writes
 * the formatted message to the auxiliary serial interface.
 *
 * @param fmt The format string for the log message.
 * @param args The variable argument list containing the values to format.
 * @return The number of characters written to the auxiliary serial interface,
 *         or a negative value if an error occurs.
 */
int aux_log_output(const char *fmt, va_list args)
{
    char buf[LOG_BUFFER_SIZE]; // Buffer for storing log message
    int len = vsnprintf(buf, sizeof(buf), fmt, args);
    if (len > 0)
    {
        AuxSerial.write(reinterpret_cast<uint8_t *>(buf), len);
    }
    return len;
}

/**
 * @brief Initializes the auxiliary serial communication and logging system.
 *
 * This function sets up the auxiliary serial communication with the specified
 * baud rate, data format, RX and TX pins. It also enables debug output for the
 * auxiliary serial and sets the logging function for the ESP logging system.
 * The global debug level is set to include ESP_LOGD messages.
 *
 * @note The function uses the following constants and variables:
 * - BAUDRATE: The baud rate for the auxiliary serial communication.
 * - SERIAL_8N1: The data format for the auxiliary serial communication.
 * - RXPIN: The RX pin for the auxiliary serial communication.
 * - TXPIN: The TX pin for the auxiliary serial communication.
 * - aux_log_output: The logging function for the ESP logging system.
 * - GLOBAL_DEBUG_LEVEL: The global debug level for the ESP logging system.
 */
void setup()
{
    AuxSerial.begin(BAUDRATE, SERIAL_8N1, RXPIN, TXPIN);
    AuxSerial.setDebugOutput(true);

    esp_log_set_vprintf(aux_log_output);

    constexpr const char *TAG = "setup";
    esp_log_level_set("*", ESP_LOG_ERROR);
}

/**
 * @brief Main loop function that logs messages at various log levels.
 *
 * This function logs messages with different severity levels using the ESP_LOG
 * macros. It logs a verbose, debug, info, warn, and error message, then delays
 * for 1000 milliseconds before repeating.
 *
 * Log levels used:
 * - ESP_LOGV: Verbose message
 * - ESP_LOGD: Debug message
 * - ESP_LOGI: Info message
 * - ESP_LOGW: Warn message
 * - ESP_LOGE: Error message
 *
 * The function runs indefinitely, logging the messages and delaying in each iteration.
 */
void loop()
{
    constexpr const char *TAG = "loop";

    ESP_LOGV(TAG, "This is a verbose message");
    ESP_LOGD(TAG, "This is a debug message");
    ESP_LOGI(TAG, "This is an info message");
    ESP_LOGW(TAG, "This is a warn message");
    ESP_LOGE(TAG, "This is an error message");

    delay(1000);
}

However, what does not work for me is changing the log level at runtime, so the line

    esp_log_level_set("*", ESP_LOG_ERROR);

in the setup() does not do anything. :-/