Graphics library for NodeMCU (ESP8266), ESP32 and serial+parallel TFT displays

Did you ever try the plane spotter sketch? Regards, Stan

Hi Stan,

Yes, I put a hacked version here that has some improvements.

bodmer, Could you turn on issue tracking for the color weatherstation project? https://github.com/Bodmer/esp8266-weather-station-color While I could clone it do a fix and then a pull request for an issue, I think it would be useful to enable issue reporting so that users could report issues. The issue I have (and probably many others) is that esp8266-weather-station-color.ino does not compile "as is". The file "ArialRoundedMTBold_14.h" does not exist. The file in the repository is named "ArialRoundedMtBold_14.h" so non neutered operating systems will not find the header file. The .ino could be changed to include the actual name of the file but more than likely the real solution is to simply re-name the header file in the repository to what I assume was the intended name that has the upper-case T.

--- bill

Hi Bill,

Issue reporting has been switched on, the project is still a WIP so some bugs are expected and the ReadMe is not very complete.

I have commented out the #include Arduino.h as that does not seem to be needed and corrected the header file name for the font, it seems that the Windows based Arduino IDE that I use (and the one used by original author - Daniel Eichhorn) is tolerant of file name letter case errors.

Thanks for your feedback.

bodmer: Hi Bill,

Issue reporting has been switched on, the project is still a WIP so some bugs are expected and the ReadMe is not very complete.

Great. One area that would be nice to get updated in the ReadMe is the Software Requirements/Libraries. There are a few more than what is listed.

it seems that the Windows based Arduino IDE that I use (and the one used by original author - Daniel Eichhorn) is tolerant of file name letter case errors.

It isn't the IDE, it is Windows. While NT is fully capable of handling the filename characters properly, Microsoft chose to keep the case insensitivity as a default in filenames that they inherited all the way back from MS DOS which came from CPM. But even on Windows, there can be issues as some tools, even the Arduino IDE, will sometimes do actual filename matching/comparing without explicitly forcing all the characters in the filename to a particular case before doing the compare. So getting the actual names correct is a good thing even on Windows.

For me it was an issue, as I rarely ever use Windows, and even when I do run it, I never let it boot or run on real hardware. I only allow Windows to run inside VMs.

--- bill

bperrybap: One area that would be nice to get updated in the ReadMe is the Software Requirements/Libraries. There are a few more than what is listed.

Yes. I'm busy at the moment but will update the ReadMe soon and probably add links to all the libraries required in the main sketch header.

The TFT_eSPI library has been updated on Github.

The main change is that the screenshot client sketch that runs under Processing on a PC and the server sketch that runs on the ESP8266 have been upgraded to support 16 bit or 24 bit colour transfers automatically. The screen dimensions are provided to the client sketch so landscape and portrait orientations are also handled automatically now.

The screenshot capture performance has also improved so that pixels are transferred to the PC at a speed very close to the theoretical serial port limit (e.g. 1.67s for a 320x240 pixel 16 bit colour exchange at 921600 baud, and 2.5s for 24 bit pixels)

Bill,

The weather station project ReadMe has been updated to add some more instructions and list the libraries needed.

I have had the sketch lock-up when trying to update the weather but I have not investigated why this happens, I suspect a time-out is needed if the Weather Underground website fails to provide an update on request, but this is just a guess at the moment.

Post an issue on Github if you find and/or track down any issues.

Forgot to mention that the TFT_eSPI library allows custom fonts to be added more easily. The font files are placed in a custom font folder, then added to a User_Custom_Fonts file. The new fonts can then be used in a sketch.

Custom fonts in the required "Adafruit" compatible format can be created using the utility here..

Edit: I have now added a new example for the custom fonts.

bodmer: Hi Stan,

You will have to wait and see if the DST time is automatically applied on the correct day for your time zone :-)

Hi, The DST worked, it set itself and the display reads EDT. The sketch has beenrunning for several weeks with no issues.

I have the plane spotter running, it is an awesome project. I live in an active flight area and it shows a lot of activity. It would be nice if it could run on a larger display like a 3.6 or 3.9 display.

The weather station sketch has also been working with no issues for a couple of weeks now.

Thanks for all your great work!!

Regards, Stan

Hi Stan,

All the really hard work was done by Daniel Eichhorn. He has some great projects getting the ESP8266 talking to the web and has produced an online book. He designed the splash screen:

He is also knows how to use web API's to for example download images and maps, which I failed to get working in the past:

The weather station code is a great example where the weather icons are fetched from a server.

P.S. You may notice some duff pixels in the images above which were grabbed off the screen. The problem was that reading pixels at 40MHz SPI rate does not work totally reliably. To be fair though that clock rate is well above the ILI9341 specified limits and thus is "over-clocking" it significantly. So use 27MHz SPI rate if the pixel read functions are going to be used!

Stan_S: It would be nice if it could run on a larger display like a 3.6 or 3.9 display.

Hi Stan,

3.95" SPI displays are mostly targeted at Raspberry Pi. Some can be easily used with ESP8266, if the connector is not an issue. And the 3.3V interface is ok with ESP8266 (UNO needs level converter).

The one from Waveshare should be usable, I use a Waveshare clone.

And then there is the Waveshare 7" display with RA8875 controller, that I just happen to successfully use with Adafruit_RA8875 over SPI with Wemos D1 and Wemos D1 mini, with a small change in the library to use 4Mhz SPI, at least for initial connection.

Jean-Marc

The TFT_eSPI library has undergone a few tweaks and bug fixes.

It is also now possible to use the MISO line for the Data/Command (DC) or Chip Select (CS) for projects that are pin constrained and where reading from the display is not needed. This means that for some displays it is possible to get down to using just three I/O pins for SCK, MOSI and DC, with CS tied low to GND and RESET connected to the NodeMCU RST pin.

The background is now correctly sized for rendering the Adafruit "Free Fonts" when using the drawString() member function, here extra width padding has been applied to the plotted numbers with the library setTextPadding() member function, this means old numbers get over-written automatically:

Using the print() method does not use background for technical reasons:

All fonts can be rendered relative to a selected datum, which helps when designing a screen layout:

Online instructions for using the library and features is "in development" and should be available soon!

Hi Jean-Marc,

Support will be provided in the TFT_eSPI library in due course for the serial RPi displays based on this type of interface schematic:

|500x463

This will allow larger resolution displays to be used. I have a ILI9481 based 480 x 320 touch screen display from China that appears to be well made and is being used for development.

Hi Bodmer,

These are very welcome news!

Seems we are on a similar track, but I am still a beginner in this field.

My design has evolved a bit:

#ifndef _GxIO_H_
#define _GxIO_H_

#include <Arduino.h>
#include <SPI.h>

class GxIO
{
  public:
    GxIO() {};
    const char* name = "GxIO";
    virtual void reset();
    virtual void init();
    virtual uint8_t transferTransaction(uint8_t d);
    virtual uint16_t transfer16Transaction(uint16_t d);
    virtual uint8_t readDataTransaction() 
    {
      return 0;
    };
    virtual uint16_t readData16Transaction() 
    {
      return 0;
    };
    virtual void writeCommandTransaction(uint8_t c);
    virtual void writeDataTransaction(uint8_t d);
    virtual void writeData16Transaction(uint16_t d, uint32_t num = 1);
    virtual void writeCommand(uint8_t c);
    virtual void writeData(uint8_t d);
    virtual void writeData(uint8_t* d, uint32_t num);
    virtual void writeData16(uint16_t d, uint32_t num = 1);
    virtual void writeAddrMSBfirst(uint16_t d);
    virtual void startTransaction();
    virtual void endTransaction();
    virtual void setBackLight(bool lit);
};

#if defined(__AVR) || defined(ESP8266)

class GxIO_SPI : public GxIO
{
  public:
    GxIO_SPI(SPIClass& spi, int8_t cs, int8_t dc, int8_t rst = -1, int8_t bl = -1);
    const char* name = "GxIO_SPI";
    void reset();
    void init();
    uint8_t transferTransaction(uint8_t d);
    uint16_t transfer16Transaction(uint16_t d);
    uint8_t readDataTransaction();
    uint16_t readData16Transaction();
    void writeCommandTransaction(uint8_t c);
    void writeDataTransaction(uint8_t d);
    void writeData16Transaction(uint16_t d, uint32_t num = 1);
    void writeCommand(uint8_t c);
    void writeData(uint8_t d);
    void writeData(uint8_t* d, uint32_t num);
    void writeData16(uint16_t d, uint32_t num = 1);
    void writeAddrMSBfirst(uint16_t d);
    void startTransaction();
    void endTransaction();
    void setBackLight(bool lit);
  protected:
    SPIClass& _SPI;
    int8_t _cs, _dc, _rst, _bl; // Control lines
};

class GxIO_SPI3W : public GxIO
{
  public:
    GxIO_SPI3W(SPIClass& spi, int8_t cs, int8_t dc, int8_t rst = -1, int8_t bl = -1,
               // defaults are for RA8875
               uint8_t cmd_read = 0xC0, uint8_t data_read = 0x40, uint8_t cmd_write = 0x80, uint8_t data_write = 0x00);
    const char* name = "GxIO_SPI3W";
    void reset();
    void init();
    uint8_t transferTransaction(uint8_t d);
    uint16_t transfer16Transaction(uint16_t d);
    uint8_t readDataTransaction();
    uint16_t readData16Transaction();
    void writeCommandTransaction(uint8_t c);
    void writeDataTransaction(uint8_t d);
    void writeData16Transaction(uint16_t d, uint32_t num = 1);
    void writeCommand(uint8_t c);
    void writeData(uint8_t d);
    void writeData(uint8_t* d, uint32_t num);
    void writeData16(uint16_t d, uint32_t num = 1);
    void writeAddrMSBfirst(uint16_t d);
    void startTransaction();
    void endTransaction();
    void setBackLight(bool lit);
  protected:
    SPIClass& _SPI;
    uint8_t _cmd_read, _data_read, _cmd_write, _data_write;
    int8_t _cs, _dc, _rst, _bl; // Control lines
};

and

// GxCTRL.h

#ifndef _GxCTRL_H_
#define _GxCTRL_H_
#include "GxIO.h"

class GxCTRL
{
  public:
    GxCTRL(GxIO& io) : IO(io) {};
    const char* name = "GxCTRL";
    virtual void init();
    virtual void setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
    virtual void setRotation(uint8_t r);
    virtual void invertDisplay(boolean i) {IO.writeCommandTransaction(i ? 0x21 : 0x20);};
  protected:
    GxIO& IO;
};

But for RA8875 the separation of display class and controller class not really makes sense.

Jean-Marc

Btw, your schematics corresponds to the display I know as Waveshare clone/knock off, marked "3.5 inch RPI LCD V3.0 HVGA 480X320". I use it with my "second version" of IO class and display class. It is on the way to be used with my third version.

Jean-Marc

Hi Jean-Marc,

My RPi display is off eBay, typical cost is about $15. There seems to be write a few different TFT interface designs out there for the RPi, but the one in post #93 is really convenient for the ESP8266 to drive.

Hi Bodmer,

It's the same that I have. I bought 2 from 2 different shops:

https://www.aliexpress.com/item/New-26-pin-3-5-inch-Raspberry-Pi-LCD-TFT-Touchscreen-Display-kit-RPI-Touch-Shield/32526486667.html

https://www.aliexpress.com/item/3-5-TFT-LCD-Touch-Screen-Module-320-x-480-SPI-RGB-Display-For-Raspberry-Pi/32661117216.html

and there are more sellers for these on AliExpress.

Avoid the 3.5" tfts marked KeDei, it uses 3 wire SPI, and no schematics can be found.

My attempts to use it with Arduino failed; I have some idea from observing on Raspi with logic analyzer, and may give it another try with my new IO class. Controller is unknown, polarity is reversed, etc.

Jean-Marc

The library has been updated to support Raspberry Pi 480 x 320 displays based on the ILI9486 TFT driver and with a 16 bit interface.

This is an example of the compatible display.

The display must be of the same interface design comprising 74HC04, 74HC4040 and 2 off 74HC4094 devices. These are commonly 3.5" TFTs compatible with the Waveshare design.

See also Jean-Marc's web links and post #93.

Since 16 bits has to be sent for every transaction there is a small overhead and thus the display draw performance is constrained.

The performance is reasonable, the TFT interface built onto the back of the TFT will only support a 20MHz rate unless modifications are made. This is a limit of the display interface design.

The UTFT Demo runs in 3s

Typical 480 x 320 results at 20MHz SPI for the GFX graphicstest sketch are:

TFT_eSPI library test!
Benchmark                Time (microseconds)
Screen fill              625771
Text                     37269
Lines                    502658
Horiz/Vert Lines         58450
Rectangles (outline)     32978
Rectangles (filled)      1511987
Circles (filled)         359877
Circles (outline)        290419
Triangles (outline)      104101
Triangles (filled)       599591
Rounded rects (outline)  132635
Rounded rects (filled)   1726473
Done!

For a 320 x 240 display the equivalent results would be:

TFT_eSPI library test!
Benchmark                Time (microseconds)
Screen fill              312986
Text                     24360
Lines                    150932
Horiz/Vert Lines         28403
Rectangles (outline)     18591
Rectangles (filled)      641954
Circles (filled)         137072
Circles (outline)        88468
Triangles (outline)      36436
Triangles (filled)       251335
Rounded rects (outline)  47381
Rounded rects (filled)   734838
Done!

The library has been updated to add support for a Raspberry Pi ILI9486 480x320 display with a modification made to the circuit that adds a directly controlled write strobe:

This allows fast writing of blocks of repeated colour pixels. The complete 480x320 screen can then be cleared in 23ms and the Run Length Encoded fonts render very fast too (1.2ms for a 72 pixel high digit). Other graphics functions that write sequences of the same colour to the screen are also speeded up significantly.

The 480x320 adapted "UTFT" graphics test sketch now runs in 1.6s and the Adafruit GFX style graphicstest runs 3x faster at 1.95s:

Benchmark                Time (microseconds)
Screen fill              115291
Text                     28714
Lines                    393270
Horiz/Vert Lines         11581
Rectangles (outline)     8164
Rectangles (filled)      279258
Circles (filled)         186516
Circles (outline)        240076
Triangles (outline)      78149
Triangles (filled)       167982
Rounded rects (outline)  94215
Rounded rects (filled)   348198
Done!
Total = 1.9496

Update: The diode must be a low capacitance type, so power diodes are not suitable for the mod circuit. A 1N4148 diode works fine and has been tested at 27MHz SPI clock rate without problems. However I have replaced it with a lower Voltage drop BAT85 schottky diode, this achieves a lower logic "0" voltage when the TFT_WR line is pulled low by the NodeMCU.