[SOLVED] 3.5 TFT not stable at power up !

Hello,

I'm testing a 3.5 TFT I bought from Aliexpress which runs ILI9488 chip.

3.5inch SPI Module ILI9488

I tested it with the code in the attachment. It's a long example code so I attached it.

I launched the display and it's working but the problems I get are:

  • The power up process isn't stable every time ! I have to plug/unplug the 5V power adapter several times until it launches correctly.
  • Some times when it launches, it misses stuff and shows interfered colors.

My question is that why that happens ? and what I can do to ensure stable operation ?

This is a picture I took when it got interfered colors.

Please :

  1. post a link to the display that you have bought e.g. Ebay sale page
  2. quote library and version number by name (or link) e.g, from Library Manager
  3. quote library example by name. Only paste any altered lines e.g. constructor
  4. quote Arduino by name or link e.g. Uno, Zero, Due, ...
  5. attach wiring schematic e.g. photo
  6. if custom code attach sketch or link

Anyone who has followed this forum knows that this information is always requested.
It takes a few minutes for the OP to create the original message.
But those minutes are much less than waiting days for a solution.

David.

  1. post a link to the display that you have bought e.g. Ebay sale page

3.5 inch TFT LCD Module with Touch Panel ILI9488 Driver 320x480 SPI port serial interface (9 IO) Touch ic XPT2046 for ard stm32

  1. quote library and version number by name (or link) e.g, from Library Manager

jaretburkett / ILI9488

  1. quote library example by name. Only paste any altered lines e.g. constructor
class ILI9488 : public Adafruit_GFX {

 public:

  ILI9488(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK,
		   int8_t _RST, int8_t _MISO);
  ILI9488(int8_t _CS, int8_t _DC, int8_t _RST = -1);

  void     begin(void),
           setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1),
           setScrollArea(uint16_t topFixedArea, uint16_t bottomFixedArea),
           scroll(uint16_t pixels),
           pushColor(uint16_t color),
           pushColors(uint16_t *data, uint8_t len, boolean first),
           drawImage(const uint8_t* img, uint16_t x, uint16_t y, uint16_t w, uint16_t h),
           fillScreen(uint16_t color),
           drawPixel(int16_t x, int16_t y, uint16_t color),
           drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
           drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
           fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
             uint16_t color),
           setRotation(uint8_t r),
           invertDisplay(boolean i);
  uint16_t color565(uint8_t r, uint8_t g, uint8_t b);

  /* These are not for current use, 8-bit protocol only! */
  uint8_t  readdata(void),
    readcommand8(uint8_t reg, uint8_t index = 0);
  /*
  uint16_t readcommand16(uint8_t);
  uint32_t readcommand32(uint8_t);
  void     dummyclock(void);
  */

  void     spiwrite(uint8_t),
    writecommand(uint8_t c),
    write16BitColor(uint16_t color),
    writedata(uint8_t d),
    commandList(uint8_t *addr);
  uint8_t  spiread(void);

 private:
  uint8_t  tabcolor;



  boolean  hwSPI;

#if defined (__AVR__) || defined(TEENSYDUINO)
  uint8_t mySPCR;
  volatile uint8_t *mosiport, *clkport, *dcport, *rsport, *csport;
  int8_t  _cs, _dc, _rst, _mosi, _miso, _sclk;
  uint8_t  mosipinmask, clkpinmask, cspinmask, dcpinmask;
////This def is for the Arduino.ORG M0!!!
//#elif defined(ARDUINO_SAM_ZERO)
//    volatile PORT_OUT_Type *mosiport, *clkport, *dcport, *rsport, *csport;
//    int32_t  _cs, _dc, _rst, _mosi, _miso, _sclk;
//    PORT_OUT_Type  mosipinmask, clkpinmask, cspinmask, dcpinmask;
#elif defined (__STM32F1__) || defined (_VARIANT_ARDUINO_STM32_) || defined (STM32F100xE) || defined (STM32F101xE) || defined (STM32F101xG) || defined (STM32F103xE) || defined (STM32F103xG) || defined (STM32F105xC) || defined (STM32F107xC)
    uint8_t mySPCR;
    volatile uint32_t *mosiport, *clkport, *dcport, *rsport, *csport;
    int32_t  _cs, _dc, _rst, _mosi, _miso, _sclk;
    uint32_t  mosipinmask, clkpinmask, cspinmask, dcpinmask;
#elif defined (__arm__)
    volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport;
    int32_t  _cs, _dc, _rst, _mosi, _miso, _sclk;
    uint32_t  mosipinmask, clkpinmask, cspinmask, dcpinmask;
#elif defined (ESP8266)
    int32_t  _cs, _dc, _rst, _mosi, _miso, _sclk;
#else
    int8_t  _cs, _dc, _rst, _mosi, _miso, _sclk;
#endif
};
  1. quote Arduino by name or link e.g. Uno, Zero, Due, ...

Arduino nano - old boatloader

  1. attach wiring schematic e.g. photo

The problems:

  1. When I press RESET button on the Arduino board the example app hangs up and not responding to the reset action.
  2. Some times I have to plug/unplug the power adapter to get it start working

But basically the tft + example code are working. My issues are when sometimes it won't launch perfectly ?

You have never quoted the example by name. I am guessing:

...
#define TFT_CS         PA1
#define TFT_DC         PB3
#define TFT_LED        PB0
#define TFT_RST        PB4

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9488 tft = ILI9488(TFT_CS, TFT_DC, TFT_RST);
...

Please copy-paste these lines from your edited sketch. Obviously this example has defines for a STM32 and you have an AVR.

That library should work fine on your Nano. Albeit fairly SLOW.

Although your photo is pretty good, I can't identify all the wires. e.g. Where does the TFT_RST signal go to.

David.

david_prentice:
You have never quoted the example by name. I am guessing:
https://github.com/jaretburkett/ILI9488/blob/master/examples/graphicstest/graphicstest.ino

Please copy-paste these lines from your edited sketch. Obviously this example has defines for a STM32 and you have an AVR.

#include "SPI.h"
#include <Adafruit_GFX.h>
#include <ILI9488.h>

#define TFT_DC 9
#define TFT_CS 10        


// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9488 tft = ILI9488(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9488 tft = Adafruit_ILI9488(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

That library should work fine on your Nano.

Is there a better library than this one ?

So when you say

Albeit fairly SLOW.

Does that mean the following:

  1. the library would run slow because of the programming system ?
  2. the nano is basically slow for this tft ?

Although your photo is pretty good, I can’t identify all the wires. e.g. Where does the TFT_RST signal go to.

David.

The rst is pulled to 3.3V high all the time, I’m not considering to reset it right now ?

Or that could be the reason that the tft isn’t resetting with the nano board ?! I thought when resetting the nano, then just that would reset the app code. Or both the nano and the tft must reset by hardware and not just counting on the nano reset?

If you don't specify a TFT_RST pin I am surprised that anything works at all.
You should always connect RST to a GPIO pin and use the TFT_RST argument in the constructor.

I would never connect RST directly to 3.3V
Connecting with a 10k pullup to 3.3V is better.
Nor would I connect it to Arduino RESET pin (but that probably works)

David.

Yep ! Actually connecting the RST pin solved the hang problem.

I thought I don't have to connect it and assumed that if the arduino resets, then the program loop should reset the tft code.

Now the setup is more sensitive ! The small wires cause the example to reset to any movement !

This setup should be done in a PCB for more stable connections.

I have a question about this library:

In .cpp file there's a definition called "ARDUINO_ARCH_ARC32" in this part:

// If the SPI library has transaction support, these functions
// establish settings and protect from interference from other
// libraries.  Otherwise, they simply do nothing.
#ifdef SPI_HAS_TRANSACTION
static inline void spi_begin(void) __attribute__((always_inline));
static inline void spi_begin(void) {
#if defined (ARDUINO_ARCH_ARC32)
  // max speed!
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
#else
    // max speed!
  SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
#endif
}
static inline void spi_end(void) __attribute__((always_inline));
static inline void spi_end(void) {
  SPI.endTransaction();
}
#else
#define spi_begin()
#define spi_end()
#endif

Now I want to know where this definition is defined basically ? I searched everywhere ! In core libraries, hardware and main "libraries" folder. Nothing ! Just in this part it's asking if it's defined.

Let's assume that it isn't defined anywhere, so the answer that it isn't defined so the speed of spi would be 24Mhz which is not arduinos clock speed, so what is going on exactly ?


Edit:
I have another question, why did the programmer put the attribution "always_inline" for spi begin function as it would be called only once at the start of the program ?

Adafruit support many targets. ARDUINO_ARCH_ARC32 refers to a Arduino 101(Intel board)

The 24MHz argument just means "set SPI speed to a maximum 24MHz"
i.e. it will be 8MHz on a 16MHz Uno
or 24MHz on a 48MHz Cortex-M4 if possible

Note that most TFTs will run happily with 24MHz SPI.
But the XPT2046 Touch controller can only run at maximum 2.5MHz

This is why you can use different speeds, format etc with beginTransaction()

David.

david_prentice:
Adafruit support many targets. ARDUINO_ARCH_ARC32 refers to a Arduino 101(Intel board)

The 24MHz argument just means "set SPI speed to a maximum 24MHz"
i.e. it will be 8MHz on a 16MHz Uno
or 24MHz on a 48MHz Cortex-M4 if possible

I want to know how's that should work in the if statement:

#if defined (ARDUINO_ARCH_ARC32)
  // max speed!
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
#else
    // max speed!
  SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
#endif

I know it's working as it should be, but I'm confused that if ARDUINO_ARCH_ARC32 is true then the speed should be 24000000 not 16000000 !
I thought the opposite it the right sequence of the if statement and #else should handle that if it's not the arduino 101.

Note that most TFTs will run happily with 24MHz SPI.

yep tft need a very fast mcu for smooth operation, I'm now just starting with the nano.

But the XPT2046 Touch controller can only run at maximum 2.5MHz

yeah this controller is different than the tft driver, and should be handled with another code with its dedicated speed.

I know it’s working as it should be, but I’m confused that if ARDUINO_ARCH_ARC32 is true then the speed should be 24000000 not 16000000 !
I thought the opposite it the right sequence of the if statement and #else should handle that if it’s not the arduino 101.

Adafruit code supports many controllers.

In theory setClock() or beginTransaction() should set the SPI frequency to 24MHz or fastest that is <= 24MHz.
e.g. 21MHz on a 84MHz Due
e.g. 8MHz on a 16MHz Nano

Some Cores do not do setClock() properly. Which might be why Adafruit has that conditional.
In real life the ILI9341 will run fine at 24MHz.

David.

OK, I think I got some points to understand in this library.

What I’m able to understand until now and by going back to the library and the way the author sat up the initialization of SPI.

First of all, at the beginning of the source code, the author put this conditional SPI initialization that I think supports specific boards other than Arduino boards.

// If the SPI library has transaction support, these functions
// establish settings and protect from interference from other
// libraries.  Otherwise, they simply do nothing.
#ifdef SPI_HAS_TRANSACTION
static inline void spi_begin(void) __attribute__((always_inline));
static inline void spi_begin(void) {
#if defined (ARDUINO_ARCH_ARC32)
  // max speed!
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
#else
    // max speed!
  SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
#endif
}
static inline void spi_end(void) __attribute__((always_inline));
static inline void spi_end(void) {
  SPI.endTransaction();
}
#else
#define spi_begin()
#define spi_end()
#endif
#if defined (ARDUINO_ARCH_ARC32)
  // max speed!
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));

means if we have the arduino 101 board that is using the intel chip, so this is only specified for this only board.

#else
    // max speed!
  SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));

I actually don’t know what this speed should cover ! which boards ? is it for boards that are using ESP, STM chips ? anything that isn’t AVR related.

Then in the begin function there’s a SPI.begin call that I think it covers all arduino boards which are AVR chips. at lines 219-220

  if(hwSPI) { // Using hardware SPI
    SPI.begin();

also after these two lines this:

#ifndef SPI_HAS_TRANSACTION
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
  #if defined (_AVR__)
    SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (full! speed!)
    mySPCR = SPCR;
  #elif defined(TEENSYDUINO) || defined (__STM32F1__)
    SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (full! speed!)
  #elif defined (__arm__)
    SPI.setClockDivider(11); // 8-ish MHz (full! speed!)
  #endif
#endif

so this check starts with checking if it’s using arduino SPI library, if it’s another SPI library not the one in arduino core libraries folder, then this check is passed.

so this sets the speed for AVR, STM, ARM and TEENSYDUINO.

but also I don’t understand this author, why he/she would put SPI initialization/speed configuration at the beginning of the source file and in the void “ILI9488::begin(void)” function ?

The source file in attachment, the parts I’m asking about are:

  1. first part of checking 37-55
  2. second part of checking 203-233

thanks for the help

ILI9488.cpp (24 KB)

but also I don't understand this author, why he/she would put SPI initialization/speed configuration at the beginning of the source file and in the void "ILI9488::begin(void)" function ?

That would be a nightmare.

The OLED / TFT controller has practical limits to SPI speed. e.g. about 27MHz
The nasty conditionals just ensure that everything is about right.

In the days of only Uno / Mega2560 speed was never a problem. You could never write "too fast" to the hardware because AVR was max F_CPU = 16MHz.

A 600MHz Teensy is obviously different.
It is wise to make library examples work out of the box.

TFT_eSPI supports the SPI ILI9488 on ESP8266, ESP32, STM32

David.

With AVR your TFT will be too limited. ESP32 may be a good alternative, but there will still be some limits to overcome.

With Teensy 4 or 4.1 and the ILI9488_t3 library that comes in the installer for the arduino IDE, you will get the best possible combination to get the most out of that SPI screen.

Best of all, you can use the SDIO reader (with a breakout on the teensy 4 or with the microSD reader built into the teensy 4.1) to upload BMP images, based on the spitftbitmap example with some minor adjustments or JPG images using the JPEGDEC library.

In both cases, you can manage the opening of files with the SdFat beta library, which, being optimized for these MCUs, provides an extra speed for loading images.

BMP test: ILI9488 3.5" + teensy 4 + external SDIO reader

TFTLCDCyg:
With AVR your TFT will be too limited. ESP32 may be a good alternative, but there will still be some limits to overcome.

I have ESP32 boards and I know it's fast enough, but I want begin with the nano board, I downloaded the library and run it on the nano with level shifters from 5V to 3.3V and it worked and also solved the RST pin problem.

With Teensy 4 or 4.1 and the ILI9488_t3 library that comes in the installer for the arduino IDE, you will get the best possible combination to get the most out of that SPI screen.

I don't know if the ILI9488_t3 if the one I have but I downloaded it from Github. And I like the programmer style; simple and clear.

Best of all, you can use the SDIO reader (with a breakout on the teensy 4 or with the microSD reader built into the teensy 4.1) to upload BMP images, based on the spitftbitmap example with some minor adjustments or JPG images using the JPEGDEC library.

In both cases, you can manage the opening of files with the SdFat beta library, which, being optimized for these MCUs, provides an extra speed for loading images.

BMP test: ILI9488 3.5" + teensy 4 + external SDIO reader

That's what I want to achieve, of course I want to use all the stuff comes with this tft, the touch and the SD reader.
And thanks for pointing me the required libraries that are needed for touch and SD.
Also thanks for the YouTube link, that channel is full of TFT demos :slight_smile:

But I still have a concern regarding the adjustment of SPI speed.

I have a question regarding LED pin of the ILI9488 module.

I know all pins except VCC are not 5V tolerant. But what about LED pin, can I drive it at 5V for more brightness, and maybe connect a 100ohm resistor in series ?

The picture of the pcb in #0 link shows Qi and U1. i.e. a transistor Q1 for LED and a 3.3V voltage regulator U1.

Please compare the pcb on your desk with the photo in the link.

So yes, you can use any digital signal to switch the LED with Q1. Any series resistor from 0R to 4k7 will probably turn the LED full on. If you want a variable backlight you can use PWM.

Many older Red SPI displays do not have Q1. And the LED is driven directly from the LED pin. In which case you use a series resistor to vary the current e.g. 2R2 to 100R

David.

david_prentice:
The picture of the pcb in #0 link shows Qi and U1. i.e. a transistor Q1 for LED and a 3.3V voltage regulator U1.

Please compare the pcb on your desk with the photo in the link.

So yes, you can use any digital signal to switch the LED with Q1. Any series resistor from 0R to 4k7 will probably turn the LED full on. If you want a variable backlight you can use PWM.

Many older Red SPI displays do not have Q1. And the LED is driven directly from the LED pin. In which case you use a series resistor to vary the current e.g. 2R2 to 100R

David.

The U1 662K and Q1 U3Y. Yep, you're right, that's why the brightness is low powering the LED pin with 3.3V because it's not enough to power a 3.3V regulator with 3.3V. The proper I guess is to power the LED with 5V.
But is powering the LED pin with 5V directly the same as putting 100R in series ? Is it the same brightness ?

This is my dev board for testing displays and some modules and maybe couple sensors.

My questions:

  1. Do I need to add any capacitors ? or every module is packed with necessary stuff ?
  2. I want to wire the touch and SD modules of the 3.5 tft module, are they following the 3.3V as the other pins or they are 5V tolerant ?

The U1 662K and Q1 U3Y. Yep, you're right, that's why the brightness is low powering the LED pin with 3.3V because it's not enough to power a 3.3V regulator with 3.3V. The proper I guess is to power the LED with 5V.
But is powering the LED pin with 5V directly the same as putting 100R in series ? Is it the same brightness ?

From the link in #0, there is a jumper J1 next to U1.
You short this jumper if you supply the whole display with 3.3V.
You leave it open if you supply with 5.0V

I guess that the LED is supplied via the output from U1 i.e. 3.3V
So the LED brightness is fixed. Q1 can only turn it on or off. PWM is the only way to vary the brightness.

I guess that if you connect VCC pin to 3.3V with J1 open, the U1 output would be less than 3.3V. Hence a dim backlight.

  1. Do I need to add any capacitors ? or every module is packed with necessary stuff ?

You always need 100nF capacitors with digital integrated circuits. Extra do no harm.
Most display modules have already got them on their pcbs

  1. I want to wire the touch and SD modules of the 3.5 tft module, are they following the 3.3V as the other pins or they are 5V tolerant ?

The XPT2046 is 5V tolerant. ILI9488 and SD are not tolerant.
You can run TFT, SD, XPT2046 with 3.3V GPIO logic and all on the same SPI bus.

Arduino Nano has 5V logic. You must provide level shifters on every signal.
It is much easier to use proper 3.3V board like Due, Zero, ESP32, STM32, Teensy 3.x, ...

David.