Printing out a crash report to an ILI9341 display

clinker8

Well-known member
I recently experienced a Teensy crash/reset while controlling a motor on a lathe. Quite often, there isn't even a console attached, just an ILI9341. Trying to install bread crumbs and whatnot in my code now.

I want to both write to serial AND to overwrite the whole display with the CrashReport output. I think a code crash is important enough to do this. This fault is infrequent, having only happened once in 18 months, so if it's a code problem I want a fighting chance at capturing it.

I'm using @KurtE 's ILI9341_t3n driver. It's been a while since I've set something like this up. The example crash report file prints out character by character, until the logfile is empty. Is the correct method to type out a single character on the display simply
Code:
tft.drawFontChar( char c);
? Does
Code:
tft.setTextWrap(true);
mean that characters that go past the 320 pixels in x, will be automatically wrapped to the next line?

Here's what I have written so far. I call this routine to check if a crash has occurred, any hopefully it would print out the CrashReport and any bread crumbs I set. The LittleFS and tft libraries have been imported in other files, don't want to import them twice.

I logged the data to a small part of the flash, so that it would be retrievable, without modifying units in the field. If I were starting from scratch, maybe I'd use an SD card.
C++:
/* This takes over the tft screen if there's a major crash logged by the Teensy.  Such a crash is a
  big deal and we want to know it happened.  Print out message to serial console if attached and
  take over the tft screen entirely.
*/
void crashreporter() {
  char c;
  File logFile = myfs.open("crashlog.txt");
  if (logFile) {
    tft.fillScreen(thisGREY);
    tft.setCursor(0,0);
    tft.setTextColor(ILI9341_WHITE);
    tft.setTextDatum(TL_DATUM);
    tft.setFont(Arial_10);  // Make text small enought to fit the message
    tft.setTextWrap(true);
         
    while (logFile.available()) {
      c = logFile.read();
      Serial.write(c);
      tft.drawFontChar(c);
    }
    while(1);   // hang forever
  }
  else {
    Serial.println("Sorry, no crashlog.txt stored");
  }
}

Obviously this routine won't work, if the display routines died, but I'm hoping not! A display is always present, but a serial console isn't. I obviously don't have a routine to delete the file, I'll need to write that... If there's a crash report, I'd like to know it happened and the operator knows something serious occurred.

Grateful for any additional insight. This is a tough nut to crack. The application has never crashed before, including when I was operating it at rates that were 17 times faster on the lathe. I'd like to isolate the problem before releasing this latest branch of my code... Thanks.
 
Last edited:
This sort of works. I get it on the display and on the serial console. I don't understand the results. Think I will ask about that in a different thread.
 
I must say the formatting of the serial console and the display are very different. How can I make the display similar to the console. It seems that CR and LF aren't allowed for the display? How can I handle that? I just get a run on sentence on the display, but it looks very readable on the serial console.
 
You might use the write method, like
tft.write(&c, 1),

I think it handles cr lf …
 
try tft.print(c); instead of tft.drawFontChar(c);
Thanks, that worked. Now it is readable.
PXL_20250404_001723333.jpg
 
Last edited:
You might use the write method, like
tft.write(&c, 1),

I think it handles cr lf …
This write method generates a warning about an invalid conversion. It may work, but the tft.print(c) seems adequate for my purpose. Now there's only two line wraps, which is a lot more readable. I'm at 8 point font though! But it's readable, and someone could take a picture of it.
Code:
warning: invalid conversion from 'char*' to 'const uint8_t*' {aka 'const unsigned char*'} [-fpermissive]
   23 |       tft.write( &c, 1 );
      |                  ^~
      |                  |
      |                  char*
      
ILI9341_t3n/src/ILI9341_t3n.h:457:39: note:   initializing argument 1 of 'virtual size_t ILI9341_t3n::write(const uint8_t*, size_t)'
  457 |   virtual size_t write(const uint8_t *buffer, size_t size);
 
Turns out that the write method, calls this one:
size_t ILI9341_t3n::write(uint8_t c) { return write(&c, 1); }

You can probably get rid o warning like:
tft.write((const uint8_t *)&c, 1);
 
Back
Top