Highly optimized ILI9341 (320x240 TFT color display) library

Big thanks to both of you for your answers.

My project is a fancy flight/racing sim button box, using the screens to display button labels, as well as some game-specific information if I can (tire temperature for a racing game, for instance).


So far, I've been able to have 4 working displays, sharing the DC line.
I need to do more testing, but it seems to work just fine on the breadboard.

In the end, performance isn't critical in my case. If I have to use another (slower) library for the 5th screen, or a performance-killing hack like a regular pin for CS, I can live with it :)
 
Hi,

Working with an ILI9341 based display, with XPT2046 touch controller and SD card all on-board.

I've got the display itself up and running and SD functionality works, although having both work together is where I'm having issues at the moment.

Has anyone already done this and got them running together and could post an example sketch?

Thanks in advance,
Iestyn.


I'll update this post with my progress as I work on it.

1) SD and display functionality works correctly seperately (using ili9341_t3->graphicsTest and SD->cardInfo examples).
2) Nothing works when two sketches are merged. (using if (!card.init(SPI_HALF_SPEED, chipSelect)) as in cardInfo sketch).
3) Using if (!SD.begin(chipSelect)) as in SD->files sketch, works within the graphicsTest sketch, provided I remove the pinMode(10, OUTPUT) line. Graphics and SD access both seem to work fine together.
4) Having a look, the uTouch library should work for the XPT2046, but in this case I'm going to roll my own SPI based library, so I can run everything on the same bus and use transactions.
5) I've written some SPI transactions code to read x and y data from chip upon the IRQ pin going LOW. It seems to provide consistent values, but it seems the XPT2046 stops responding after a certain number of calls to read from it, requiring power to be removed and reapplied to get it running again?
6) Seems like it was a timing issue. I was struggling to determine from the datasheet the sort of SPI frequency I should be aiming for (http://www.buydisplay.com/download/ic/XPT2046.pdf). Ended up at 1000000 (SPISettings(1000000, MSBFIRST, SPI_MODE0)) and that tentatively, seems to be working fine.
7) Apparently not; it spent a while repeatedly spitting out 0 for the y coordinate, then locked up again.
8) A bit more investigation showed that it wasn't 'locking up', but rather the IRQ line stopped going low. Looking into the control byte, bits 0 and 1 control power down settings, 2 of which settings, disable the IRQ line (leaving it high). Therefore, I suspect that perhaps my connection to the display just isn't quite very solid (using 20cm prototyping wires). If I don't wait for the IRQ line to go low and just continuously poll it for readings, it doesn't fail at all. So I'll put it down to a dodgy connection and put it to the side for now as this is something that should clear up when I put in on PCB. (If not, I'll take a closer look then). Long and short is, I have a set of working code for the XPT2046. Now to bring all three elements together.
9) Display and SD card work together fine, but the touch screen yields some interesting results when brought into the mix. I'm fairly certain however, this is due to bad connections.
 
Last edited:
I don't have a board with that touch controller, but I could not tell from your question if the touch controller is an issue or having issue with SD card? Which libraries are you using (SD, sdFat)?

I have not tried it in awhile, but I believe the Examples program: ili9341_t3/spitftbitmap worked earlier. This reads an image from the card and displays it on the screen. Again it has been several releases since I have tried it.
 
Thanks for the reply, I'm about to look at the touch controller side of it in a moment. Just keeping a log in-case any of this helps anyone else. =)

Wish I'd noticed the spitftbitmap example sooner though, would have shortcut some of the issues I had to deal with haha.

EDIT: Regarding spitftbitmap, it seems to work, although it's rather slow. Loading a 240x240 image takes around 350ms with writeRect or 550ms with pushColor. Upping BUFFPIXEL above 200 seems to have no effect, until you hit 100 at which point the time taken reported via the serial monitor comes right down to 60ms, but the image is corrupted.

Update: Corruption was a simple fix. "uint8_t buffidx = sizeof(sdbuffer);" needed to be uint16_t. Increasing that buffer didn't increase draw speed by any significant amount though, still takes 350ms or so to display an image, so I guess we're limited by SPI speed here?
 
Last edited:
Thanks for your fast answer Paul !

I already tried these connections but it's not working. I'm using a CD4050 as level converter (5v of teensy to 3.3v of ILI9341).
The "graphicstest" of the original Adafruit_ILI9341 Library worked too, so I don't undertand why your library don't work properly.
 
Which teensy? Which display? Teensy 3.x are all mostly 3.3v with 3.1 being 5v tollerant.

Which pins do you have connected to what?
 
Also, when you say it's not working; what exactly is not working? Failing to compile? Doesn't show anything in Serial Monitor? Doesn't display anything?

Need some details in order to help you with regard to this. =)
 
Yes, sorry I didn't explain my problem too much.
I'm using a Teensy 3.1. Does it have 3.3v logic level ??
The screen print nothing but the benchmark work :confused:

Benchmark at 72 mHz : (is the 0xFF normal ?)

ILI9341 Test!
Display Power Mode: 0xFF
MADCTL Mode: 0xFF
Pixel Format: 0xFF
Image Format: 0xFF
Self Diagnostic: 0xFF
Benchmark Time (microseconds)
Screen fill 373475
Text 24033
Lines 97626
Horiz/Vert Lines 30772
Rectangles (outline) 19522
Rectangles (filled) 775569
Circles (filled) 122825
Circles (outline) 117213
Triangles (outline) 23669
Triangles (filled) 260879
Rounded rects (outline) 49929
Rounded rects (filled) 848515
Done!

This is my wiring (in attachment)

I hope this can help you to find where is the problem
 

Attachments

  • Captudfhgfre.PNG
    Captudfhgfre.PNG
    247.6 KB · Views: 629
Last edited:
No ... wait ... it's working !

The only thing I do to fix it, is moving a bit jumpers. I think there was bad connection (due to bad quality jumpers or breadboard).

Thanks for helping me :)
 
I hooked one up following the connections on PJRC direct to a 3.1 and it worked. I soldered mine to perf and then socket jumpers and was right the first time - fast and reliable.
 
This seems to be a good idea but do you have any pic (to reproduce it :) ) ? Because I didn't understand the socket jumpers usage.

Yes Paul I'm very happy now about this ;) Btw you did a great work here !
 
Have been trying to use ILI9341_t3 library along with doing some other SPI stuff but don't get expected results, received bytes are delayed by one byte.
Here is code to reproduce problem. No hardware is connected except for a jumper from pin0 to pin12 to get some values into the SPI register.

Code:
#include <SPI.h>
#include "ILI9341_t3.h"

// For the Adafruit shield, these are the default.
#define TFT_DC  9
#define TFT_CS 10

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

#define	test0		0
#define	test1		1
#define  dontcare      0xaa

uint8_t        spi_received;

void setup() {

  delay(150);
  pinMode(test0, OUTPUT);
  pinMode(test1, OUTPUT);


  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial);
  // wait for serial port to connect. Needed for Leonardo only
  Serial.println("start");

  tft.begin();

  //  tft.fillScreen(ILI9341_BLACK);
  //  tft.setTextColor(ILI9341_YELLOW);
  //  tft.setTextSize(2);
  //  tft.println("Waiting for Arduino Serial Monitor...");
  //  tft.fillCircle(100, 200, 30, ILI9341_MAGENTA);

  tft.drawPixel(150, 22, ILI9341_MAGENTA); //comment this then test SPI works as expected

  digitalWrite(test1, HIGH);    //trigger my scope

  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));

  digitalWrite(test0, LOW);    //connect teensy pin0 to teensy MISO pin12, simulate 0x00

  spi_received = SPI.transfer(dontcare);    //expect to receive 0x00
  Serial.print(spi_received, HEX);
  Serial.println(" expected 0x00");

  digitalWrite(test0, HIGH);                //simulate 0xff

  spi_received = SPI.transfer(dontcare);    //expect to receive 0xFF *************
  Serial.print(spi_received, HEX);
  Serial.println(" expected 0xFF");

  spi_received = SPI.transfer(dontcare);    //expect to receive 0xFF
  Serial.print(spi_received, HEX);
  Serial.println(" expected 0xFF");

  digitalWrite(test0, LOW);                  // simulate 0x00

  spi_received = SPI.transfer(dontcare);    //expect to receive 0x00 *****************
  Serial.print(spi_received, HEX);
  Serial.println(" expected 0x00");

  digitalWrite(test0, HIGH);                //simulate 0xff

  spi_received = SPI.transfer(dontcare);    //expect to receive 0xFF *************
  Serial.print(spi_received, HEX);
  Serial.println(" expected 0xFF");


  SPI.endTransaction();

}

void loop() {

}

Here's the output:

start
0 expected 0x00
0 expected 0xFF
FF expected 0xFF
FF expected 0x00
0 expected 0xFF

And here's the output when i comment out code that writes to the screen
Code:
//tft.drawPixel(150, 22, ILI9341_MAGENTA); //comment this then test SPI works as expected

start
0 expected 0x00
FF expected 0xFF
FF expected 0xFF
0 expected 0x00
FF expected 0xFF
 
This seems to be a good idea but do you have any pic (to reproduce it :) ) ? Because I didn't understand the socket jumpers usage.

I put female socket headers through a perf board and soldered them to mount the display. Then above that crudely soldered between those wires and a second set of socket pins - making some of the hardwire connections for power and the resistor on the LED leg. Then I ran jumper wires from the second socket set to the teensy signal/power pins per the drawing to complete the circuit.

S_2015-04-21s.png
 
messy indeed - I thought I planned ahead for a cleaner job - but that didn't prevent me from learning. One lesson was buy double sided PCB's. And demonstrates that working ugly is better than pretty but bad. Also - labeling pays off. The female socket out the front works well in the end. I Velcro strap the PCB to an adjustable 'cell phone' stand (hiding this ugliness) and it has served me well, tying USB cord down too lets the teensy stand on it. I bought an Amazon 100 mix pack of 6 and 8 LONG pin female headers that are just as malleable and disposable as they were inexpensive, way better value than the cheap perfboards.

At least I used sockets so no harm was done to display or Teensy. I was even too rushed/lazy too find a proper resistor, so I put two in parallel to get down to 140ohms when 100 was called for and two other values were at hand.
 
I can confirm that the bug mentioned by user "ildeann" exists in Tennsy ILI9341 library. We have tested the same sketch with Adafruit ILI9341 library and with Teensy ILI9341 library. With the Adafruit library everything was working as expected. reading touch IC and writing to display was possible without the mentioned problem. But with Teensy library, the behaviour was as described by user "ildeann". Some one really need to look at that.
 
ILI9341 with Teensy Audio Board code example

I have previously used the ILI9341_t3 library successfully with the Teensy Audio Board, using the pinout and code instructions on the ILI9341 store page.
But after some testing today, I realize that I am using an updated version of the library that needs to have MOSI and SCLK specified in the contructor instead of changing the pins with the SPI object directly.
With the updated ILI9341_t3 library the example code for using it with the Teensy Audio Board on the ILI9341 store page could be like this:

Code:
// For using with the Teensy Audio board
#define TFT_DC 20
#define TFT_CS 21
#define TFT_RST 255 // Set to 255 when reset is not used
#define TFT_MOSI 7
#define TFT_SCLK 14
#define TFT_MISO 12

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

void setup() {
  tft.begin();

I know that you are a busy man, Paul. But it would be nice for the next person to have the code up to date on your ILI9341 store page.

I can also make a pull request to the graphicstest.ino example commented out lines with the expanded defines and contructor. I feel this is the main display test code.
 
Last edited:
Back
Top