Why SSD1306 OLED display get scrambled text when printing messages from tasks pinned to Core0 in RTOS?
Posted: 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.
The code below uses no RTOS and works perfectly: (my project requires RTOS)
Thanks
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;
}
}
}
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();
}