Page 1 of 1

OLED display refresh unsuccessful - is it a task problem?

Posted: Sat Dec 05, 2020 6:52 pm
by wereworm
Hi,

I'm currently working on a small project where I use an ESP32 as a webserver and have a SSD1306 OLED display attached to it using the Adafruit SSD1306 library (via platform io).

The screen is supposed to show some information, like the device's name, the IP and a little icon indicating if a client has connected to the websocket (hence the webserver)

the initial screen looks fine, it shows the information as expected. But when I connect to the ESP websocket and the "onWsEvent" is fired the screen needs to be updated. It does update but it looks just quite a bit off:
photo_2020-12-05_19-38-39.jpg
photo_2020-12-05_19-38-39.jpg (118.54 KiB) Viewed 3415 times
Here's the onWsEvent function (i deleted everything irrelevant in there):

Code: Select all

void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data,
               size_t len) {
    switch (type) {
        case WS_EVT_CONNECT:
            Serial.printf("WebSocket client #%u connected from %s\n", client->id(),
                          client->remoteIP().toString().c_str());

            Serial.printf("Core ID: %i\n", xPortGetCoreID());
            Serial.printf("Task Name: %s\n", pcTaskGetTaskName(NULL));

            wsConnectedCallback();
            break;
        case WS_EVT_DISCONNECT:
            Serial.printf("WebSocket client #%u disconnected\n", client->id());
            wsDisconnectedCallback();
            break;
    }
}
two things are to mention in particular here:
1st - a callback method is called that continues in my main.cpp and changes the display information
2nd - I added an output that shows the task name

And the output shows what I expected: All correct changes are made within the loopTask, when it is changed from the async_tcp task, it shows the problems as seen in the image.

I also have the same output in my method to change the display. here's the output:

WebSocket client #1 connected from 192.168.86.35
Core ID: 1
Task Name: async_tcp <- from onWsEvent
Core ID: 1
Task Name: async_tcp <- from display method because of the connect ws event
WebSocket client #1 disconnected
Core ID: 1
Task Name: async_tcp <- from display method because of the disconnect ws event
Core ID: 1
Task Name: loopTask <- from display method because i updated the screen from a serial monitor input

I am not very experienced with C++ and what's going on in the background in memory etc. i have only some basic understanding from my vocational training 15 years ago. But i know that in other areas the UI can only be updated from the main thread, which makes sense. Does this also apply to here?
How can I fix this and is there a way to execute code from the loopTask coming from another task? Or do I need to handle all display changes on a separate task?


thanks for your help!

Re: OLED display refresh unsuccessful - is it a task problem?

Posted: Mon Dec 07, 2020 1:47 am
by ESP_Sprite
Sounds like you may indeed have two threads trying to update the display at the same time. If that is the case, you can solve this by either having a FreeRTOS mutex to moderate who can update the screen, or a FreeRTOS queue to shuttle the data to your main task and do all updating there.

Re: OLED display refresh unsuccessful - is it a task problem?

Posted: Tue Dec 15, 2020 3:02 pm
by wereworm
Hi, I implemented a separate "UI Task" that checks frequently for new queue messages and it apparently works quite well. I haven't had any of these fragments anymore.