Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display corruption when using both ESP32 cores? #326

Closed
mbariola opened this issue Feb 4, 2021 · 4 comments
Closed

Display corruption when using both ESP32 cores? #326

mbariola opened this issue Feb 4, 2021 · 4 comments

Comments

@mbariola
Copy link

mbariola commented Feb 4, 2021

Hi,

I have changed a sketch in which the SSD1306 worked fine to use both cores. At that point, "garbage" started appearing on the screen. Here's the minimal sketch showcasing the issue. I am running the sketch on a ttgo lolin esp32 with an integrated SSD1306 display.

Expected behavior: first line of text on display stays the same, 2nd and 3rd line swap between them (see displayText call in loop() and in core0synchronousOps(), where the order of operands 2 and 3 are swapped)

Actual behavior: garbled pixels on display

compiling sketch on PlatformIO

#include <Arduino.h>
#include <SSD1306Wire.h>
#include <WiFi.h>

#define OLEDRESETPIN 16

const unsigned int checkIntervalMs = 3000; // how often the checker will be called
char DisplayHeader[20] = "HeartBeat";
char DisplayLine1[20] = "WiFi: ?? Ext: ??";
char DisplayLine2[20] = "Router: ?? Net: ??";
// display
SSD1306Wire display(0x3c, 4, 15); // define the display



TaskHandle_t Core0Sync;


// Callback methods prototypes

void diplayText(char[], char[], char[]);
void displayText(char line1[], char line2[], char line3[])
{
  display.clear();
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.setFont(ArialMT_Plain_16);
  display.drawStringMaxWidth(64, 0, 128, line1);
  display.setFont(ArialMT_Plain_10);
  display.drawStringMaxWidth(64, 26, 128, line2);
  display.drawStringMaxWidth(64, 42, 128, line3);
  display.display();
}

void core0synchronousOps(void * pvParameters)
{

  for (;;)
  {
      Serial.print("core0synchronousOps running on core ");
      Serial.println(xPortGetCoreID());
      displayText(DisplayHeader, DisplayLine1, DisplayLine2);
    delay(checkIntervalMs);
  }
}


void setup() { 
  Serial.begin(460800);

  // reset & init display
  delay(50);
  Serial.println("Prepping Display...");
  pinMode(OLEDRESETPIN, OUTPUT);   // OLED reset pin
  digitalWrite(OLEDRESETPIN, LOW); // set GPIO16 low to reset OLED
  delay(50);
  digitalWrite(OLEDRESETPIN, HIGH); // while OLED is running, must set GPIO16 in high
  delay(50);
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);
  displayText("HeartBeat", "Initializing.", "Please Stand By...");
  delay(1000);
  xTaskCreatePinnedToCore(
      core0synchronousOps, 
      "Core0Sync",         
      10000,               
      NULL,                
      1,                   
      &Core0Sync,          
      0);                  
}

void loop()
{
  delay(1000);
      Serial.print("loop running on core ");
      Serial.println(xPortGetCoreID());
  displayText(DisplayHeader, DisplayLine2, DisplayLine1);
  delay(checkIntervalMs);
}

@mbariola
Copy link
Author

mbariola commented Feb 5, 2021

Probably connected to #299

@Rotzbua
Copy link
Contributor

Rotzbua commented Apr 29, 2021

As I understand you run the code on both cores without managing the access. So it works as expected and you corrupt the memory.
Embedded libraries are in general not multi-thread/core enabled because every MCU has its own implementation. You have manage the access to the library, so that there is only 1 core that interacts with the library.

@thijstriemstra
Copy link
Contributor

Thanks for the suggestion @Rotzbua. Was running into same issue and pinning the task to a different core fixed the oled corruption.

@mbariola
Copy link
Author

@Rotzbua thanks. I did the same as @thijstriemstra and basically now I have a core which does scheduled activities (incl the OLED refresh) and another for realtime callback based stuff, with some variables read by one core and written by the other to keep a shared state.

NorthernMan54 added a commit to NorthernMan54/OpenMQTTGatewayProd that referenced this issue Oct 22, 2022
Added to Heltec board display code logic to reduce corruption of messages on the display

Two piece of defensive code were added

- Only display messages to the display when operating on Core 1 ( Default Arduino ESP32 CONFIG_ARDUINO_RUNNING_CORE )

- Only display one character/string at a time

In the event of failure, default to Serial output.

PS SSD1306 driver similar issues

ThingPulse/esp8266-oled-ssd1306#326
ThingPulse/esp8266-oled-ssd1306#352
1technophile pushed a commit to 1technophile/OpenMQTTGateway that referenced this issue Oct 23, 2022
Added to Heltec board display code logic to reduce corruption of messages on the display

Two piece of defensive code were added

- Only display messages to the display when operating on Core 1 ( Default Arduino ESP32 CONFIG_ARDUINO_RUNNING_CORE )

- Only display one character/string at a time

In the event of failure, default to Serial output.

PS SSD1306 driver similar issues

ThingPulse/esp8266-oled-ssd1306#326
ThingPulse/esp8266-oled-ssd1306#352
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants