Why SSD1306 OLED display get scrambled text when printing messages from tasks pinned to Core0 in RTOS?

Pcborges
Posts: 37
Joined: Thu Aug 09, 2018 9:56 pm

Why SSD1306 OLED display get scrambled text when printing messages from tasks pinned to Core0 in RTOS?

Postby Pcborges » Mon Apr 12, 2021 11:32 am

ESP32 with RTOS, test app with 2 independent tasks. Each prints a message to OLED display. Why text gets frequently scrambled? Mutex have been used to share display resource.

I found that if I put Task01 to run on the same core as Task02 (core 1) it works perfectly. And if I put both to run on core 0 the mess becomes a lot worse.
The problem has clearly something to do when the task running on core 0 tries to write to the display even protected by Mutex.

Code: Select all

#define DEBUG_ESP              //comment out to deactivate debug console verbose
#ifdef DEBUG_ESP
  #define pDBGln(x) Serial.println(x)
  #define pDBG(x)   Serial.print(x)
#else 
  #define pDBG(...)
  #define pDBGln(...)
#endif 

//create handle for the mutex. It will be used to reference mutex
SemaphoreHandle_t  xMutex;

//*********************************SSD1306 OLED Display
#define I2C_SDA              14
#define I2C_SCL              15
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//*****************************************************

void setup() {

  // create mutex and assign it a already create handler 
  xMutex = xSemaphoreCreateMutex();  

  Wire.begin(I2C_SDA,I2C_SCL);
  Serial.begin(115200);
        
   // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    pDBGln("SSD1306 allocation failed - Halt");
    for(;;); // Don't proceed, loop forever
  }else{
    // Show initial display buffer contents on the screen --
    // the library initializes this with an Adafruit splash screen.
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);  
    display.setCursor(0, 0);
    display.clearDisplay(); 
  }

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

    xTaskCreatePinnedToCore(
        task02,             /* Function to implement the task */
        "task02",           /* Name of the task */
        10000,              /* Stack size in words */
        NULL,               /* Task input parameter */
        1,                  /* Priority of the task */
        NULL,               /* Task handle. */
        1);                 /* Core where the task should run */ 
}

void loop() {}

void task01( void * parameter ){
  while(1){
    printToDisplay("Task01..............");
    vTaskDelay(1500);
  }
}

void task02( void * parameter ){
  while(1){
    printToDisplay("Task02..............");
    vTaskDelay(2500);
  }
}

void printToDisplay(String text){
  bool myMutex;
  while(1){
    // take mutex
    myMutex = xSemaphoreTake(xMutex, portMAX_DELAY);
    if(myMutex){ 
      static byte   lineCounter = 0;
      static String displayText[8];
      if(lineCounter>7){
        for(int i=0;i<7;i++){
          displayText[i] = displayText[i+1];
        }
        displayText[7] = text;
        display.clearDisplay();  
        display.setCursor(0, 0);  
        for(int i=0;i<8;i++){
          display.println(displayText[i]);   
        }    
      }else{
        displayText[lineCounter] = text; 
        display.println(displayText[lineCounter]);
        if(lineCounter<8){lineCounter++;}
      }  
      display.display(); 

      // release mutex
      xSemaphoreGive(xMutex); 
      break;
    }
  }
}
The code below uses no RTOS and works perfectly: (my project requires RTOS)

Code: Select all

#ifdef DEBUG_ESP
  #define pDBGln(x) Serial.println(x)
  #define pDBG(x)   Serial.print(x)
#else 
  #define pDBG(...)
  #define pDBGln(...)
#endif 

byte lineCounter = 0;

//*********************************SSD1306 OLED Display
#define I2C_SDA              14
#define I2C_SCL              15
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//*****************************************************

void setup() {

  Wire.begin(I2C_SDA,I2C_SCL);
  Serial.begin(115200);
        
   // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    pDBGln("SSD1306 allocation failed - Halt");
    for(;;); // Don't proceed, loop forever
  }else{
    // Show initial display buffer contents on the screen --
    // the library initializes this with an Adafruit splash screen.
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);  
    display.setCursor(0, 0);
    display.clearDisplay(); 
  }
}

void loop() {
  pDBGln("Start Display Test...");
  task01();
  task02();
}

void task01(){
  printToDisplay("Task01..............");
  delay(500);
}

void task02(){
  printToDisplay("Task02..............");
  delay(500);
}

void printToDisplay(String text){
  static byte   lineCounter = 0;
  static String displayText[8];
  if(lineCounter>7){
    for(int i=0;i<7;i++){
      displayText[i] = displayText[i+1];
    }
    displayText[7] = text;
    display.clearDisplay();  
    display.setCursor(0, 0);  
    for(int i=0;i<8;i++){
      display.println(displayText[i]);   
    }    
  }else{
    displayText[lineCounter] = text; 
    display.println(displayText[lineCounter]);
    if(lineCounter<8){lineCounter++;}
  }  
  display.display(); 
}
Thanks

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: Why SSD1306 OLED display get scrambled text when printing messages from tasks pinned to Core0 in RTOS?

Postby ESP_Sprite » Tue Apr 13, 2021 5:37 am

The only thing I can think of is that display.display() is still doing things even after the call itself returns; as the mutex is unlocked after, perhaps the 2nd thread overwrites some information it uses. You'd need to take a good, hard look at the lib code to see if that's true, though.

Who is online

Users browsing this forum: Google [Bot] and 71 guests