I took the ESP32 web server through web socket example from the book and added a 128×32 I2C 1306 OLED display as a project to basically display what I sent from the web page through the web socket.
The issue I had, (I basically resolved it) is when the system was writing to the display, I was getting corrupt text most of the time. I say most of the time since a few random times I actually got readable text. After spending a number of hours searching on the web and trying different things. I resolved the issue and wanted to post this for others who may have the same problem.
I believe it boils down to how the web socket library checks to see if there is a new connection or incoming message. I believe that it is interrupt driven and it interrupts the I2C write process in the middle of that library writing lines to the display.
My solution was to move both the initialization from setup() and the writing into a thread that I ran on the second CPU in the ESP32 module. By both initializing and writing in that core seemed to keep that process separated from the actions happening in the other core and I now get clean readable text on the display.
I got the example on how to run a program in the other core by a simple web search.
The final solution was to have a global variable that the web socket incoming data gets written to. In the other core’s while(true) loop I test to see if the text changes then write it to the display and save that string as the new temporary variable to test against for new changes. Piece of cake.
Hi Carey.
Thank you so much for sharing that.
So, you basically used the two ESP32 cores, right? One to build the web server and the other to display on the OLED.
Can you share the snippet of code you used to put the OLED display on the other core. If you don’t mind, of course.
It may be useful for other people.
Thank you so much for sharing.
Regards,
Sara
Below are the OLED specific code examples if you are unfamiliar with how to setup and write to an OLED display.
This link is a good example from https://randomnerdtutorials.com/guide-for-oled-display-with-arduino/
Utilizing the second Core in an ESP32 try this example https://randomnerdtutorials.com/esp32-dual-core-arduino-ide/
I hope you find this helpful.
// These are thee libraries that you need to add to your project.
//
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//OLED stuff to establish some parameters about your device
//
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Globals for Oled
// The global variables below are the two strings that I join and write out
// to the OLED display, I pre set the values here since I use the “Ready”
// string to indicate that the module is running and ready.
String GlobalVar1= “Ready”;
String GlobalVar2 = “”;
// This is the core number that I want to run the routine on
// by default the ESP32 runs the main code in core 1
static int threadCore = 0;
// For dual CPU use the above goes into the code as normal.
// Find a good OLED only example if you are unfamiliar with this
// The function below is my main routine that I will run core 0
void coreTask( void * pvParameters ){
// below is everything I wanted to do for setting up the function
String taskMessage = “Task running on core “;
// I preset the variables to some random string
String tempVar1=”None”;
String tempVar2=”None”;
//
taskMessage = taskMessage + xPortGetCoreID();
Serial.println(taskMessage);
// This setup below is from the OLED1306 demo
// normally you would make this call in the setup() function
// putting it in this function guarantees that it will run
// in the memory space for core 0 isolated from the activity
// running in core 1
Serial.println(“Setting up the display”);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128×64
Serial.println(F(“SSD1306 allocation failed”));
for(;;);
}
delay(2000);
// below is the main loop for this core think of it like the loop()
// function for the main code but isolated to a separate core
// Since I enter values into the Web page and write them back to the
// web socket using javascript
// The web socket parses the data and creates two strings that I assign
// to the global variables, this routine simply compares them to what is in the temp
// values if they are different calls my function and sets the new temp values
// to the current values.
// all functions and global variables you declare are available to the second core
while(true){
if((tempSuit != GlobalVar1 ) || (tempValue != GlobalVar2) ){
Serial.println(“Thread writing Card”);
CallMyFunction();
tempSuit = GlobalVar1;
tempValue = GlobalVar2;
}
delay(1000);
}
}
I missed one thing you need to also do in your setup() function
This tells the processor to enable the second core and what function to run.
xTaskCreatePinnedToCore(coreTask,”coreTask”, 10000, NULL, 0, NULL,threadCore); /* Core where the task should run */
Serial.println(“Thread created…”);