U8g2 frames blend into each other

I currently work with the u8g2 library. Everything works fine, but when I render a new frame the old content and the new content blend into each other (only the pixels that change between the two frame) instead of having a clear/crisp instant transition.

Is there something I need to tweak in the u8g2 library or can it be a limitation of my LCD display (cheap AliExpress display, with a ST7565R / STM32F030F4P6 driver). Or a limitation of my MCU, a Trinket M0. Maybe there's a more efficient constructor I could use?

I also measured time and parsing the JSON in my sketch below doesn't take even 1 millisecond. But just sending the buffer (u8g2.sendBuffer();) takes 129ms. The whole render() function takes 134ms.

I also tried to tweak the bus clock of the library but that didn't change a lot. I bumped it up from 1000000 (default) to 1500000.

Here my sketch:

#include <Arduino.h>
#include <U8g2lib.h>
#include <SerialCommands.h>
#include <Base64.h>
#include <ArduinoJson.h>

const int SCREEN_WIDTH = 128;
const int SCREEN_HEIGHT = 64;

U8G2_ST7565_ERC12864_F_4W_SW_SPI u8g2(U8G2_R0,/* clock=*/ 2, /* data=*/ 1, /* cs=*/ 3, /* dc=*/ 0, /* reset=*/ 4);

char serial_command_buffer[2048];
SerialCommands serialCommands(&Serial, serial_command_buffer, sizeof(serial_command_buffer), "\n", " ");

String currentContent = "";
typedef struct font_map_entry { const char* name; const uint8_t* font_ref; } font_map_entry;

font_map_entry font_map[] = {
  { "impact11", u8g2_font_ImpactBits_tr },
  { "mono5x8", u8g2_font_5x8_tf },
  { "fur42", u8g2_font_fur42_tf }
};

int font_map_size = sizeof(font_map) / sizeof(struct font_map_entry);

void setup()
{
  u8g2.begin();
  u8g2.setBusClock(1500000);
  u8g2.setContrast(0);

  // Sort the array so that binary search can be used
  qsort(font_map, font_map_size, sizeof(struct font_map_entry), font_entry_cmp);

  // Add commands
  serialCommands.SetDefaultHandler(commandUnrecognized);
  serialCommands.AddCommand(new SerialCommand("set-content", commandSetContent));

  Serial.begin(9600);
}

void loop()
{
  serialCommands.ReadSerial();
}

void commandUnrecognized(SerialCommands* sender, const char* cmd)
{
  serial_printf(sender->GetSerial(), "Unrecognized command [%s]\n", cmd);
}

void commandSetContent(SerialCommands* sender) {
  char* base64ContentStr = sender->Next();

  if (base64ContentStr == NULL) {
      sender->GetSerial()->println("content_param_missing\n");
      return;
  }

  int base64ContentStrLength = strlen(base64ContentStr);

  int decodedLength = Base64.decodedLength(base64ContentStr, base64ContentStrLength);
  char decodedString[decodedLength + 1];
  Base64.decode(decodedString, base64ContentStr, base64ContentStrLength);

  // Render display
  render(sender, decodedString);

  currentContent = base64ContentStr;
  
  serial_printf(sender->GetSerial(), "successful\n\n", base64ContentStr);
}

void render(SerialCommands* sender, const char* content) 
{
  StaticJsonDocument<2048> doc;

  DeserializationError error = deserializeJson(doc, content, strlen(content));
  
  if (error) {
    serial_printf(sender->GetSerial(), "deserialization_failed,reason:%s\n", error.c_str());
    return;
  }

  JsonArray arr = doc.as<JsonArray>();

  u8g2.clearBuffer();

  unsigned long allStart = millis();

  for (JsonVariant value : arr) {
      unsigned long  jsonStart = millis();
    
      JsonObject root = value.as<JsonObject>();

      unsigned long jsonEnd = millis();

      Serial.printf("JSON parse array element: start->%d, end->%d, total->%d\n", jsonStart, jsonEnd, (jsonEnd-jsonStart));

      const char* font = root["font"];
      const char* posX = root["posX"];
      const char* posY = root["posY"];
      const char* text = root["text"];

      if (text == NULL) { continue; }
      if (posY == NULL) { posY = 0; }
      if (posX == NULL) { posX = 0; }
    
      const uint8_t* u8g2_font = find_font(font);

      u8g2.setFont(u8g2_font);

      int strWidth = u8g2.getStrWidth(text);
      int strHeight = u8g2.getAscent();

      int screenX;
      int screenY;

      if (strcmp(posX, "center") == 0) {
        screenX = (SCREEN_WIDTH/2)-(strWidth/2);
      } else if (strcmp(posX, "left") == 0) {
        screenX = 0;
      } else if (strcmp(posX, "right") == 0) {
        screenX = SCREEN_WIDTH-strWidth;
      } else {
        screenX = atoi(posX);

        if (screenX < 0) {
          // Support negative placement
          screenX += SCREEN_WIDTH-strWidth;
        }
      }

      if (strcmp(posY, "top") == 0) {
        screenY = u8g2.getAscent();
      } else if (strcmp(posY, "center") == 0) {
        screenY = (SCREEN_HEIGHT/2)+(strHeight/2);
      } else if (strcmp(posY, "bottom") == 0) {
        screenY = SCREEN_HEIGHT+u8g2.getDescent();
      } else {
        screenY = atoi(posY);

        if (screenY < 0) {
          // Support negative placement
          screenY += SCREEN_HEIGHT;
        } else {
          screenY += strHeight;
        }
      }

      u8g2.setDrawColor(1);
      u8g2.drawStr(screenX,screenY,text);
  }

  unsigned long sendBufferStart = millis();

  u8g2.sendBuffer();
  
  unsigned long allStop = millis();

  Serial.printf("Send buffer: start->%d, stop->%d, total->%d\n", sendBufferStart, allStop, (allStop-sendBufferStart));
  Serial.printf("Complete drawing: start->%d, stop->%d, total->%d\n", allStart, allStop, (allStop-allStart));
}

const uint8_t* find_font(const char* input)
{
  font_map_entry* result = (font_map_entry*) bsearch(&input, font_map, font_map_size, sizeof(struct font_map_entry), font_entry_cmp);

  return (result != NULL) ? result->font_ref : u8g2_font_ncenB08_tr;
}

int font_entry_cmp(const void *v1, const void *v2)
{
  const font_map_entry* entry1 = (const font_map_entry*)v1;
  const font_map_entry* entry2 = (const font_map_entry*)v2;
  return strcmp(entry1->name, entry2->name);
}
 

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.