Waveshare 2.9" E-ink Display with GxEPD library: Void loop slows considerably after first partial update

Dear people,

I am working with the GxEPD library of @ZinggJM and it has thus far saved my life. I am busy working on my Thesis project in which I am printing strings of text ("Tasks") to the E-ink display. However, once my display has done a partial update it slows my void loop considerably. While I only call the partial update when there is a new task. The display powers down after 1 minute of inactivity, and does a full refresh after receiving a task then. Even after the powerdown, my loop is still slowed. Because the display is part of a bigger project using NFC and Bluetooth among other things, it is important my loop is not slowed too much. Does anyone have an idea what it could be?

My display: https://www.waveshare.com/2.9inch-e-paper-module.htm
Display library: #include <GxDEPG0290BS/GxDEPG0290BS.h> 2.9" b/w Waveshare
Working with Arduino Mega 2560.

The code below shows all the relevant code regarding the E-ink display:

#include <Wire.h>
#include <Adafruit_PN532.h>
#include <EEPROM.h>
#include <GxEPD.h>
#include <Adafruit_GFX.h>

// Display libraries
#include <GxDEPG0290BS/GxDEPG0290BS.h> //2.9" b/w Waveshare
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/FreeMono9pt7b.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include "displayBitmaps.h"

// Initialization Display pins
GxIO_Class io(SPI, /*CS=*/ SS, /*DC=*/ 8, /*RST=*/ 9);
GxEPD_Class display(io, /*RST=*/ 9, /*BUSY=*/ 7);

const char* name = "FreeMonoBold9pt7b";
const GFXfont* displayFont = &FreeMonoBold9pt7b;

String Task = "";
unsigned long lastTimeTextPrinted = 0;
const unsigned long displayResetInterval = 5000;
bool blankDisplaySet = false;
unsigned long lastInteractionTime = 0;
const unsigned long displayPowerdownInterval = 60000; // 1 minute

Void setup() {
Serial.begin(38400);  // Serial in IDE
Serial.println("Serial setup complete");

//Display init
  display.init(38400);
  showPartialUpdatePaged();
  Serial.println("Display initialized");
}

My functions in the loop relevant for the E-ink display:

void loop() {
newLoop = millis();
Serial.print("Result newLoop - lastLoop = ");
Serial.println(newLoop - lastLoop);
lastLoop = millis();

/*If new task received:*/processReceivedTask(); 
setBlankDisplay();
powerdownDisplay();
}

My functions:

// Function to process received tasks
void processReceivedTask() {
  Task = currentMessage.substring(1); // Removes the "T"
  currentMessage = "";
  taskPaired = false; 

  Serial.println("Received task: " + Task);
  const char* text = Task.c_str();
  display.drawPagedToWindow(showTextInBox, 20, 20, 256, 88, text);
}

void showTextInBox(const char* text)
{
    uint16_t box_x = 20;
    uint16_t box_y = 0;
    uint16_t box_w = 276;
    uint16_t box_h = 128;
    uint16_t textHeight = 18; // Adjust according to your font size

    display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);

    String line = "";
    String word = "";

    // Calculate the number of lines needed to display the text
    int numLines = 1; // Start with at least one line
    for (size_t i = 0; i < strlen(text); i++) {
        if (text[i] == ' ' || text[i] == '\0') {
            if (line.length() + word.length() + 1 <= 22) {
                line += " ";
                line += word;
            } else {
                numLines++; // Increment line count
                line = word; // Start new line
            }
            word = ""; // Reset word
        } else {
            word += text[i];
        }
    }

    // Calculate vertical offset to center the text
    uint16_t totalTextHeight = numLines * textHeight;
    uint16_t cursor_y = box_y + (box_h - totalTextHeight) / 2 + textHeight; // Center vertically

    // Reset the line and word variables for actual printing
    line = "";
    word = "";

    // Print the text with line breaks
    for (size_t i = 0; i < strlen(text); i++) {
        if (text[i] == ' ' || text[i] == '\0') {
            if (line.length() + word.length() + 1 <= 22) {
                if (line.length() > 0) {
                    line += " ";
                }
                line += word;
            } else {
                // Print the current line
                display.setCursor(box_x, cursor_y);
                display.print(line);
                cursor_y += textHeight; // Move cursor down for the next line

                line = word; // Start new line
            }
            word = ""; // Reset word
        } else {
            word += text[i]; // Add character to word
        }
    }

    // Print the last line if any
    if (line.length() > 0) {
        if (line.length() + word.length() + 1 <= 22) {
            if (line.length() > 0) {
                line += " ";
            }
            line += word;
        }
        display.setCursor(box_x, cursor_y);
        display.print(line);
    }
    lastTimeTextPrinted = millis();
    blankDisplaySet = false;
}


void showPartialUpdatePaged()
{
  uint16_t box_x = 20;
  uint16_t box_y = 0;
  uint16_t box_w = 276;
  uint16_t box_h = 128;
  String startup = "System Started";
  const char* text = startup.c_str();
  
  display.setFont(displayFont);
  display.setTextColor(GxEPD_BLACK);
  
  // draw background
  display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground));

  // partial update to full screen to preset for partial update of box window (this avoids strange background effects)
  display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_partial_update);

  // show updates in the update box
  // reset the background
  display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_partial_update);
  display.setRotation(1);
  display.drawPagedToWindow(showTextInBox, box_x, box_y, box_w, box_h, text);
}

void setBlankDisplay(){
  if (!blankDisplaySet){
    if (millis() - lastTimeTextPrinted >= displayResetInterval) {
      lastTimeTextPrinted = millis();
      display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_default | GxEPD::bm_partial_update);
      blankDisplaySet = true;
    }
  }
}

void powerdownDisplay(){
  if (millis() - lastInteractionTime >= displayPowerdownInterval) {
    lastInteractionTime = millis();
    display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_default | GxEPD::bm_partial_update);
    display.powerDown();
  }
}

My Serial output:

_PowerOn : 91944
_Update_Full : 5097924
_Update_Part : 734740
_Update_Part : 734908
_Update_Part : 734336
Display initialized
Result newLoop - lastLoop = 14678
Result newLoop - lastLoop = 56
Result newLoop - lastLoop = 57
Result newLoop - lastLoop = 57
Result newLoop - lastLoop = 56
//etc...
Received task: task 1
_Update_Part : 734444 //Printing task
Result newLoop - lastLoop = 6484
Result newLoop - lastLoop = 521
Result newLoop - lastLoop = 520
Result newLoop - lastLoop = 520
Result newLoop - lastLoop = 521
Result newLoop - lastLoop = 521
Result newLoop - lastLoop = 520
Result newLoop - lastLoop = 520
Result newLoop - lastLoop = 520
_Update_Part : 734964 //setBlankDisplay function
Result newLoop - lastLoop = 2040
Result newLoop - lastLoop = 521
Result newLoop - lastLoop = 520
Result newLoop - lastLoop = 521
Result newLoop - lastLoop = 521
Result newLoop - lastLoop = 520
Result newLoop - lastLoop = 520
//etc...

I want to thank you in advance! I hope I have provided all the necessary information.

Sanne

Seem to get called unconditionally.

No, post you complete code.

Here is my complete code:

#include <Wire.h>
#include <Adafruit_PN532.h>
#include <EEPROM.h>
#include <GxEPD.h>
#include <Adafruit_GFX.h>

// Display libraries
#include <GxDEPG0290BS/GxDEPG0290BS.h> //2.9" b/w Waveshare
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/FreeMono9pt7b.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include "displayBitmaps.h"

// Initialization Display pins
GxIO_Class io(SPI, /*CS=*/ SS, /*DC=*/ 8, /*RST=*/ 9);
GxEPD_Class display(io, /*RST=*/ 9, /*BUSY=*/ 7);

const char* name = "FreeMonoBold9pt7b";
const GFXfont* displayFont = &FreeMonoBold9pt7b;

unsigned long lastTimeTextPrinted = 0;
const unsigned long displayResetInterval = 4000;
bool blankDisplaySet = false;
unsigned long lastInteractionTime = 0;
const unsigned long displayPowerdownInterval = 6000; // 1 minute

// Define the I2C connection for the NFC module
#define PN532_SDA 20
#define PN532_SCL 21

Adafruit_PN532 nfc(PN532_SDA, PN532_SCL);

// Define a structure to hold UID-task pairs
struct UIDTaskPair {
  uint8_t uid[7];
  uint8_t uidLength;
  char task[150];  // Adjust the size based on your needs
};

// Array to hold UID-task pairs
#define MAX_PAIRS 15
UIDTaskPair uidTaskPairs[MAX_PAIRS];
int numPairs = 0;

// Temporary storage Task functions
String currentMessage = "";
String Task = "";
String finishedTask = "";

bool taskPaired = false;
bool finishTaskRequested = false;
bool taskFinishedComplete = false;
bool endSent = false;

const int chunkSize = 1;
int currentIndex = 0;

// Connections
unsigned long lastBTConnectionCheckSendTime = 0;
const unsigned long BTConnectionCheckInterval = 5000;
int connectionCount = 0;

// NFC variables
uint8_t success;
uint8_t uid[7];
uint8_t uidLength;
bool NFCDetected = false;
unsigned long TaskParingTimeNFC = 500;
unsigned long TaskReadTimeNFC = 50;

// EEPROM storage addresses
#define EEPROM_SIZE 4096
#define EEPROM_PAIRS_ADDR 0
#define EEPROM_NUM_PAIRS_ADDR (EEPROM_PAIRS_ADDR + sizeof(UIDTaskPair) * MAX_PAIRS)

// Button constants and variables
const int buttonPin = 22;
int lastButtonState = HIGH;
int readingButton;
int buttonState;

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers


unsigned long lastLoop = 0;
unsigned long newLoop = 0;

void setup() {
  Serial.begin(38400);  // Serial in IDE
  Serial3.begin(9600);  // Serial for BT communication to MIT app Inventor
  Serial.println("Serial setup complete");

  pinMode(buttonPin, INPUT);

  // Load UID-task pairs from EEPROM
  loadPairsFromEEPROM();

  // Initialize NFC module
  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (!versiondata) {
    Serial.println("Didn't find PN532 board");
    while (1); // halt
  }

  nfc.SAMConfig();
  Serial.println("NFC Initialized.");

  //Display init
  display.init(38400);
  showPartialUpdatePaged();
  Serial.println("Display initialized");
}

void loop() {
  newLoop = millis();
  Serial.print("Looptime: ");
  Serial.println(newLoop - lastLoop);
  lastLoop = millis();
  
  BTconnectionCheck();

  // Bluetooth communication
  while (Serial3.available() > 0) {
    char incomingByte = Serial3.read();  
    currentMessage += incomingByte;

    if (incomingByte == '\n') {
      currentMessage.trim();  // Remove the newline character
      if (currentMessage.charAt(0) == 'T') { // Indicates a task
        processReceivedTask();
      } 
    }
  }

  handleButton();

  // NFC detection and handling
  NFCDetected = detectNFC();

  if (NFCDetected) {
    if (finishTaskRequested) {
      handleFinishTask();
      finishTaskRequested = false;
    } else if (Task.length() > 0 && !taskPaired) {
      pairTaskWithUID();
      taskPaired = true;
    } else {
      printTaskForUID();
    }
  }
  setBlankDisplay();
  powerdownDisplay();
}

// -----------------------FUNCTIONS--------------------------

// Function to send a connection check message
void BTconnectionCheck() {
  if (millis() - lastBTConnectionCheckSendTime >= BTConnectionCheckInterval) {
    lastBTConnectionCheckSendTime = millis();
    Serial3.read();
    Serial3.print("C");
    Serial.println("ConnectionCheck");
  }
}

// Function to process received tasks
void processReceivedTask() {
  Task = currentMessage.substring(1); // Removes the "T"
  currentMessage = "";
  taskPaired = false; // Task is not paired to stone yet

  Serial.println("Received task: " + Task);
  const char* text = Task.c_str();
  display.drawPagedToWindow(showTextInBox, 20, 20, 256, 88, text);
}

// Function to detect NFC tag
bool detectNFC() {
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, Task.length() > 0 ? TaskParingTimeNFC : TaskReadTimeNFC);
  if (success) {
    // Serial.print("NFC tag detected with UID: ");
    for (uint8_t i = 0; i < uidLength; i++) {
      // Serial.print(uid[i], HEX);
      // Serial.print(" ");
    }
    // Serial.println();
  } else {
    // Commented out for less noise
    // Serial.println("No NFC tag detected.");
  }
  return success;
}

// Function to pair task with NFC UID
void pairTaskWithUID() {
  // Check if UID already exists
  for (int i = 0; i < numPairs; i++) {
    
    if (uidLength == uidTaskPairs[i].uidLength && memcmp(uid, uidTaskPairs[i].uid, uidLength) == 0) {
      // Update the existing task
      Task.toCharArray(uidTaskPairs[i].task, 100);
      Serial.println("To do is paired");
      display.drawPagedToWindow(showTextInBox, 20, 20, 256, 88, "To do is paired");
      Serial3.println("P"); // Tells MIT pairing is done
      Task = "";
      savePairToEEPROM(i); // Save updated pair to EEPROM
      return;
    }
  }

  // If UID does not exist, add a new pair
  if (numPairs < MAX_PAIRS) {
    // Copy the current UID and task into the uidTaskPairs array
    memcpy(uidTaskPairs[numPairs].uid, uid, uidLength);
    uidTaskPairs[numPairs].uidLength = uidLength;
    Task.toCharArray(uidTaskPairs[numPairs].task, 100);
    numPairs++;
    Serial.println("To do is paired");
    display.drawPagedToWindow(showTextInBox, 20, 20, 256, 88, "To do is paired");
    Serial3.read();
    Serial3.println("P"); // Tells MIT pairing is done
    Serial.println("Paired");
    Task = "";
    savePairToEEPROM(numPairs - 1); // Save new pair to EEPROM
    saveNumPairsToEEPROM(); // Save the updated number of pairs
    for (uint8_t i = 0; i < uidLength; i++) {
      // Serial.print(uid[i], HEX);
      // Serial.print(" ");
    }
    // Serial.println();
  } else {
    Serial.println("Error: Maximum number of pairs reached.");
  }
}

// Function to print task for detected NFC UID
void printTaskForUID() {
  for (int i = 0; i < numPairs; i++) {
    if (uidLength == uidTaskPairs[i].uidLength && memcmp(uid, uidTaskPairs[i].uid, uidLength) == 0) {
      Serial.println("Task on stone: " + String(uidTaskPairs[i].task));
      return;
    }
  }
  Serial.println("Stone is unpaired");
}

// Function to handle button press
void handleButton() {
  
  readingButton = digitalRead(buttonPin);
  
  // If the switch changed, due to noise or pressing:
  if (readingButton != lastButtonState) {
    lastDebounceTime = millis(); // reset the debouncing timer
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    if (readingButton != buttonState) {
      buttonState = readingButton;

      if (buttonState == LOW) {
        finishTaskRequested = true;
        Serial.println("Button Pressed: Finish task requested");
      }
    }
  }
  lastButtonState = readingButton;
}

// Function to handle finishing a task
void handleFinishTask() {
  Serial.println("F");
  Serial3.read();
  Serial3.print("F");
  for (int i = 0; i < numPairs; i++) {
    if (uidLength == uidTaskPairs[i].uidLength && memcmp(uid, uidTaskPairs[i].uid, uidLength) == 0) {
      finishedTask = String(uidTaskPairs[i].task);
      
      currentIndex = 0;  // Reset the index for chunking
      endSent = false;   // Reset the flag for sending END
      sendTaskInChunks();
      
      removeTask(i);
      return;
    }
  }
  Serial.println("No task found to finish");
}

void sendTaskInChunks() {
  while (currentIndex < finishedTask.length()) {
    String chunk = finishedTask.substring(currentIndex, currentIndex + chunkSize);
    Serial3.print(chunk);  // Send the chunk
    Serial.print(chunk);
    currentIndex += chunkSize;
  } 
  
  if (!endSent) {
    Serial3.println("%");  // Send the termination message
    Serial.println("%");
    endSent = true;          // Set the flag to indicate "END" has been sent
  }
}

// Function to remove a task from the list
void removeTask(int index) {
  for (int i = index; i < numPairs - 1; i++) {
    uidTaskPairs[i] = uidTaskPairs[i + 1];
  }
  numPairs--;
  saveNumPairsToEEPROM();
  savePairsToEEPROM();
}

// Function to save all UID-task pairs to EEPROM
void savePairsToEEPROM() {
  for (int i = 0; i < numPairs; i++) {
    savePairToEEPROM(i);
  }
}

// Function to save a specific UID-task pair to EEPROM
void savePairToEEPROM(int index) {
  EEPROM.put(EEPROM_PAIRS_ADDR + sizeof(UIDTaskPair) * index, uidTaskPairs[index]);
}

// Function to save the number of pairs to EEPROM
void saveNumPairsToEEPROM() {
  EEPROM.put(EEPROM_NUM_PAIRS_ADDR, numPairs);
}

// Function to load UID-task pairs from EEPROM
void loadPairsFromEEPROM() {
  for (int i = 0; i < MAX_PAIRS; i++) {
    EEPROM.get(EEPROM_PAIRS_ADDR + sizeof(UIDTaskPair) * i, uidTaskPairs[i]);
  }
  EEPROM.get(EEPROM_NUM_PAIRS_ADDR, numPairs);
}

void showTextInBox(const char* text)
{
    uint16_t box_x = 20;
    uint16_t box_y = 0;
    uint16_t box_w = 276;
    uint16_t box_h = 128;
    uint16_t textHeight = 18; // Adjust according to your font size

    display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);

    String line = "";
    String word = "";

    // Calculate the number of lines needed to display the text
    int numLines = 1; // Start with at least one line
    for (size_t i = 0; i < strlen(text); i++) {
        if (text[i] == ' ' || text[i] == '\0') {
            if (line.length() + word.length() + 1 <= 22) {
                line += " ";
                line += word;
            } else {
                numLines++; // Increment line count
                line = word; // Start new line
            }
            word = ""; // Reset word
        } else {
            word += text[i];
        }
    }

    // Calculate vertical offset to center the text
    uint16_t totalTextHeight = numLines * textHeight;
    uint16_t cursor_y = box_y + (box_h - totalTextHeight) / 2 + textHeight; // Center vertically

    // Reset the line and word variables for actual printing
    line = "";
    word = "";

    // Print the text with line breaks
    for (size_t i = 0; i < strlen(text); i++) {
        if (text[i] == ' ' || text[i] == '\0') {
            if (line.length() + word.length() + 1 <= 22) {
                if (line.length() > 0) {
                    line += " ";
                }
                line += word;
            } else {
                // Print the current line
                display.setCursor(box_x, cursor_y);
                display.print(line);
                cursor_y += textHeight; // Move cursor down for the next line

                line = word; // Start new line
            }
            word = ""; // Reset word
        } else {
            word += text[i]; // Add character to word
        }
    }

    // Print the last line if any
    if (line.length() > 0) {
        if (line.length() + word.length() + 1 <= 22) {
            if (line.length() > 0) {
                line += " ";
            }
            line += word;
        }
        display.setCursor(box_x, cursor_y);
        display.print(line);
    }
    lastTimeTextPrinted = millis();
    blankDisplaySet = false;
}


void showPartialUpdatePaged()
{
  uint16_t box_x = 20;
  uint16_t box_y = 0;
  uint16_t box_w = 276;
  uint16_t box_h = 128;
  String startup = "System Started";
  const char* text = startup.c_str();
  
  display.setFont(displayFont);
  display.setTextColor(GxEPD_BLACK);
  
  // draw background
  display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground));

  // partial update to full screen to preset for partial update of box window (this avoids strange background effects)
  display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_partial_update);

  // show updates in the update box
  // reset the background
  display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_partial_update);
  display.setRotation(1);
  display.drawPagedToWindow(showTextInBox, box_x, box_y, box_w, box_h, text);
}

void setBlankDisplay(){
  if (!blankDisplaySet){
    if (millis() - lastTimeTextPrinted >= displayResetInterval) {
      lastTimeTextPrinted = millis();
      display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_default | GxEPD::bm_partial_update);
      blankDisplaySet = true;
      lastInteractionTime = millis();
    }
  }
}

void powerdownDisplay(){
  if (millis() - lastInteractionTime >= displayPowerdownInterval) {
    lastInteractionTime = millis();
    display.drawExampleBitmap(whiteBackground, sizeof(whiteBackground), GxEPD::bm_default | GxEPD::bm_partial_update);
    display.powerDown();
  }
}

try

  Serial.println(millis() - lastLoop);
  setBlankDisplay();
  powerdownDisplay();

to analyze.

What did you want me to observe differently than I already did previously?
Before:

newLoop = millis();
Serial.print("Result newLoop - lastLoop = ");
Serial.println(newLoop - lastLoop);
lastLoop = millis();

I now implemented your suggestion:

Serial.print("To observe: ");
Serial.println(millis() - lastLoop);
lastLoop = millis();

Serial monitor:

Display initialized
To observe: 14676
To observe: 57
To observe: 57
To observe: 56
To observe: 58
To observe: 56
//etc.
Received task: task 1
_Update_Part : 734412
To observe: 6483
To observe: 521
To observe: 520

So it's not a different output than before. Thanks for responding so quickly btw!

I just saw that it does not slow down when it does the setBlankDisplay() after the initialization and also not after the partial updates in the setup. So only when it receives a task in the loop and then after receiving it slows down from avg 60ms to 520 ms.

Where is the output from

now?

To see if the time is spent before or in these two calls.

ah okey.

Is this what you meant?

void loop() {
  newLoop = millis();
  Serial.print("begin of loop (newLoop) = ");
  Serial.println(newLoop);
  Serial.print("Looptime = newLoop - lastLoop: ");
  Serial.println(newLoop - lastLoop);
  lastLoop = millis();
  Serial.print("End of loop time (lastLoop): ");
  Serial.println(lastLoop);
  
  BTconnectionCheck();

  // Bluetooth communication
  while (Serial3.available() > 0) {
    char incomingByte = Serial3.read();  
    currentMessage += incomingByte;

    if (incomingByte == '\n') {
      currentMessage.trim();  // Remove the newline character
      if (currentMessage.charAt(0) == 'T') { // Indicates a task
        processReceivedTask();
      } 
    }
  }

  handleButton();

  // NFC detection and handling
  NFCDetected = detectNFC();

  if (NFCDetected) {
    if (finishTaskRequested) {
      handleFinishTask();
      finishTaskRequested = false;
    } else if (Task.length() > 0 && !taskPaired) {
      pairTaskWithUID();
      taskPaired = true;
    } else {
      printTaskForUID();
    }
  }
  setBlankDisplay();
  powerdownDisplay();
}

//Serial output:
begin of loop (newLoop) = 21280
Looptime = newLoop - lastLoop: 66
End of loop time (lastLoop): 21281
Received task: task 1 is slow..
_Update_Part : 734540
begin of loop (newLoop) = 27783
Looptime = newLoop - lastLoop: 6502
End of loop time (lastLoop): 27784
begin of loop (newLoop) = 28313
Looptime = newLoop - lastLoop: 529
End of loop time (lastLoop): 28315
begin of loop (newLoop) = 28845
Looptime = newLoop - lastLoop: 530
End of loop time (lastLoop): 28846

No, now this is missing

Sorry, I don't have more time for this.

1 Like

Thanks for your responses anyway!

I have found my problem! It had nothing to do with the display, but with my NFC function. But due to the update function of the display my timings were off and therefore things stopped working correctly.

Thanks @silentobserver for your effort. It helped me to find the problem.

Maybe my code can help others with other problems. Good luck with your projects people!