Arduino TFT Display and Font Library

201,023

125

283

Intro: Arduino TFT Display and Font Library

I am quite a fan of the Arduino as there is so much software already available on the internet, this makes completing new projects easier!

Recently I bought a few cheap 1.8" TFT displays for a project, initially I could not get them working which was frustrating. Eventually I found that the ones I had bought used the Samsung S6D02A1 driver chip and I had been trying to use the wrong library.

After a brief search on the web I came across the Adafruit_QDTech library which worked really well. This library is used in conjunction with the Adafruit_GFX library. After trying some examples I was a little disappointed that only scaled blocky fonts were available - so I have modified the original libraries to add some new fonts and functions.

Update 2/2/2015:

I have now added a driver library below for the 2.2" TFT QVGA 240x320 pixel display with the ILI9341 driver. This has examples included.

Update 3/2/2015:

I have now added a driver library for the 1.8" TFT display based on the ST7735 driver along with examples.

Update 14/6/2015:

I have added a new library for the 2.2" TFT QVGA 240x320 pixel display with the ILI9341 driver. This library is called TFT_ILI9341 and is a stand alone library that does not need the support of another GFX library. Compatibility with the Adafruit GFX library has been maintained. See Step 8 of this Instructable.

Step 1: Wiring It Up

I used the Arduino UNO and linked it to the 1.8" S6D02A1 based display as follows:

  • UNO +5V to display pin 6 (VCC) and pin 7 (BL)
  • UNO 0V (GND) to display pin 8 (GND)
  • UNO digital pin 7 through a 1K2 resistor to display pin 1 (RST)
  • UNO digital pin 8 through a 1K2 resistor to display pin 3 (D/C)
  • UNO digital pin 9 through a 1K2 resistor to display pin 2 (CS)
  • UNO digital pin 11 through a 1K2 resistor to display pin 4 (DIN)
  • UNO digital pin 13 through a 1K2 resistor to display pin 5 (CLK)

The 1K2 resistors are required to protect the display being damaged by the 5V logic levels from the UNO, these limit the current flow. Ideally we could use a level shifter but the resistors work fine.

Update 2/2/2015

You can also now use the 2.2" QVGA TFT SPI display based on the ILI9341 driver. To use this display load the Adatfruit_IL9341_AS and Adafruit_GFX_AS libraries. Connect the display to the UNO as follows:

    • UNO +5V to display pin 1 (VCC)
    • UNO +5V through a 56 Ohm resistor to display pin 8 (LED)
    • UNO 0V (GND) to display pin 2 (GND)
    • UNO digital pin 7 through a 1K2 resistor to display pin 4 (RESET), add a 1K8 resistor from display pin 4 to GND
    • UNO digital pin 8 through a 1K2 resistor to display pin 5 (DC/RS), add a 1K8 resistor from display pin 5 to GND
    • UNO digital pin 9 through a 1K2 resistor to display pin 3 (CS), add a 1K8 resistor from display pin 3 to GND
    • UNO digital pin 11 through a 1K2 resistor to display pin 6 (SDI/MOSI), add a 1K8 resistor from display pin 6 to GND
    • UNO digital pin 13 through a 1K2 resistor to display pin 7 (SCK), add a 1K8 resistor from display pin 7 to GND

    It is important to include the 1K8 resistors to GND with this 2.2" display as otherwise it will not work. The 1K2 and 1K8 resistors are a "potential divider", acting as a logic level shifter so that the logic level at the display is reduced from 5V to around 3V. Pin 9 of the display does not need to be connected up.

    Some displays of this type do not have a LED series resistor built in so the 56 Ohm value above is needed to limit the LED current to about 50mA.

    Update 3/2/2015

    The 1.8" 128x160 pixel display based on the ST7735 driver is now also supported. To use this display load the Adafruit_ST7735_AS and Adafruit_GFX_AS libraries. Connect the UNO to the display as follows:

    • UNO +5V to display pin 1 (VCC) and pin 8 (LED)
    • UNO 0V (GND) to display pin 2 (GND)
    • UNO digital pin 7 through a 1K2 resistor to display pin 4 (RESET)
    • UNO digital pin 8 through a 1K2 resistor to display pin 5 (AO)
    • UNO digital pin 9 through a 1K2 resistor to display pin 3 (CS)
    • UNO digital pin 11 through a 1K2 resistor to display pin 6 (SDI)
    • UNO digital pin 13 through a 1K2 resistor to display pin 7 (SCK)

    Step 2: Loading the Libraries (updated 3/2/15)

    I have modified the Adafruit libraries and added the fonts. The fonts will be stored in FLASH so will use up some program space however a reasonable amount of space is still available, if you run out then use an Arduino Mega board.

    I am actually a hardware designer so the software updates could probably be improved, but they are working!

    The zip file contains the two libraries you will need. These have have new names (_AS appended) so they will coexist with any libraries you already have. There are 3 example programs included in the Adafruit_QDTech_AS library.

    I updated the libraries to version 5 on 2/2/2015, now individual fonts can be disabled to save FLASH memory if they are not all needed. To prevent particular font files being loaded simply edit the "Load_fonts.h" file within the "Adafruit_GFX_AS" library folder. Just comment out the fonts not needed by adding // to the beginning of the respective line. Also, in response to a question from a reader below, I have made the proportional fonts scalable just like the original simple Adafruit, this makes the fonts more blocky but providing the scale factor is not more than 2 the fonts still look reasonable. In the example TFT_Show_Font_ILI9341 I use the commands:

    tft.setTextSize(1); // For normal sized fonts

    tft.setTextSize(2); // For double sized fonts

    Other minor tweaks have been made so that the font background will be drawn as per original Adafruit font. The font drawing speed has also been improved. Minor tweaks have been made to the fonts, Font 4 has been reduced in height slightly to remove superfluous "whitespace" and a full stop "." has been added to the characters available in the large font 6.

    Minor tweaks to the fonts have been made and new example sketches have been added to show all font characters.

    Step 3: Example Programs

    The example programs are:

    • TFT_Rainbow - gives some examples of drawing the fonts on the display
    • TFT_Clock - an analogue clock drawn with the standard Adafruit graphics routines plus a centred line of text in Font 4
    • TFT_Clock_Digital - a digital clock using the 7 segment display font and other font drawing examples.
    • TFT_Show_Font - draws the different fonts and characters on the screen

    Step 4: Library Functions and Fonts

    Here are the library functions that can be called:

    • int drawUnicode(unsigned int uniCode, int x, int y, int size);
    • int drawNumber(long long_num,int poX, int poY, int size);
    • int drawChar(char c, int x, int y, int size);
    • int drawString(char *string, int poX, int poY, int size);
    • int drawCentreString(char *string, int dX, int poY, int size);
    • int drawRightString(char *string, int dX, int poY, int size);
    • int drawFloat(float floatNumber,int decimal,int poX, int poY, int size);

    In summary, the X and Y parameters are the coordinates for the drawing.

    Each function returns the X position delta to the end of the printed characters.

    "size" is the font size:

    • Only font numbers 2,4,6,7 are valid
    • Font 6 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 - . : a p m
    • Font 7 is a 7 segment font and only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : .

    The fonts are proportionally spaced to give an improved appearance.

    The routine for floating point numbers uses a parameter "decimal" which defines the number of decimal places to show, this aids formatting and displaying sensor readings, the number is rounded, so for example if decimal = 3, then 3.14159 will display as 3.142 and 3.14 will display as 3.140

    drawCentreString will centre the string around the x position. convenient for tidy display formatting

    drawRightString will draw the string right justified to the x position, useful for labels that are followed by sensor readings printed afterwards.

    Update 2/2/2015:

    Added new library "Adafruit_ILI9341_AS" so a 2.2" TFT 240x320 pixel display can also be used.

    All fonts can now be scaled:

    tft.setTextSize(1); // For normal sized fonts
    tft.setTextSize(2); // For double sized fonts

    Also:

    drawUnicode(unsigned int uniCode, int x, int y, int size)

    is no longer in the latest libraries, please use:

    drawChar(char c, int x, int y, int size)

    instead.

    Step 5: Have Fun!

    I hope you find this Instructable useful!

    P.S. I am am not connected with Adafruit, but do check out their great products and look for the support on using the standard graphics library functions (these remain within the adapted libraries).

    Step 6: Requests...

    Here we have some responses to requests:

    1. A replacement Font32.c file with the Grave accent being drawn as a degree symbol.

    2. A Sketch that has a function to wrap text to next line or back to the top.

    A faster drawing ILI9341 library to try with any ATmega328 based Arduino can be found attached to my Instructable here.

    Step 7: Displaying Images Stored on an SD Card

    I have now created a new Instructable for drawing bitmap image files stored on an SD Card on the display:

    https://www.instructables.com/id/Arduino-TFT-displa...

    This is compatible with the ILI9341 driver based TFT boards.

    Step 8: New Fast Library for the ILI9341 Based TFT Display With Run Length Encoded Fonts

    This new library is a standalone library that contains the TFT driver as well as the graphics functions and fonts that were in the GFX library. This library has significant performance improvements when used with an UNO (or ATmega328 based Arduino) and MEGA.

    Examples are included with the library, including graphics test programs. The example sketch TFT_Rainbow_one shows different ways of using the font support functions. This library now supports the "print" library so the formatting features of the "print" library can be used, for example to print to the TFT in Hexadecimal, for example:

    tft.println(57005, HEX);

    The larger fonts are now Run Length Encoded (RLE) so that they occupy less FLASH space, this frees up space for the rest of the sketch. A byproduct of the RLE approach is that the font drawing is also speeded up so it is a win-win situation.

    A new 72 point large Font 8 has been added that contains [space]1234567890:. characters.

    To use the F_AS_T performance option the ILI9341 based display must be connected to an UNO as follows:

    • UNO +5V to display pin 1 (VCC) and pin 8 (LED)
    • UNO 0V (GND) to display pin 2 (GND)
    • UNO digital pin 7 through a 1K2 resistor to display pin 4 (RESET), add a 1K8 resistor from display pin 4 to GND
    • UNO digital pin 9 through a 1K2 resistor to display pin 5 (DC/RS), add a 1K8 resistor from display pin 5 to GND
    • UNO digital pin 10 through a 1K2 resistor to display pin 3 (CS), add a 1K8 resistor from display pin 3 to GND
    • UNO digital pin 11 through a 1K2 resistor to display pin 6 (SDI/MOSI), add a 1K8 resistor from display pin 6 to GND
    • UNO digital pin 13 through a 1K2 resistor to display pin 7 (SCK), add a 1K8 resistor from display pin 7 to GND

    When using an UNO the CS line must be connected to pin 10 and DC line to pin 9, this is because the optimised code uses direct port access.

    When using the UNO comment out the MEGA_TFT_ILI9341 #define in the library Run_faster.h file.

    This library only supports hardware SPI, so pins 11 and 13 on the UNO must be used as listed above.

    To use the F_AS_T performance option the ILI9341 based display must be connected to an MEGA as follows:

    • MEGA +5V to display pin 1 (VCC) and pin 8 (LED) UNO 0V (GND) to display pin 2 (GND)
    • MEGA digital pin 44 through a 1K2 resistor to display pin 4 (RESET), add a 1K8 resistor from display pin 4 to GND
    • MEGA digital pin 48 through a 1K2 resistor to display pin 5 (DC/RS), add a 1K8 resistor from display pin 5 to GND
    • MEGA digital pin 47 through a 1K2 resistor to display pin 3 (CS), add a 1K8 resistor from display pin 3 to GND
    • MEGA digital pin 51 through a 1K2 resistor to display pin 6 (SDI/MOSI), add a 1K8 resistor from display pin 6 to GND
    • MEGA digital pin 52 through a 1K2 resistor to display pin 7 (SCK), add a 1K8 resistor from display pin 7 to GND

    When using a MEGA the CS line must be connected to pin 47 and DC line to pin 48, this is because the optimised code uses direct port access.

    When using the MEGA ensure the MEGA_TFT_ILI9341 #define in the library Run_faster.h file in not commented out.

    This library only supports hardware SPI, so pins 51 and 52 on the MEGA must be used as listed above.

    In the library Font 0 (GLCD font), 2, 4, 6 and 8 are enabled. Edit the Load_fonts.h file within the library folder to enable/disable fonts to save space.

    Remember: disabling fonts saves FLASH space, and disabling them means they cannot be displayed!

    TFT_ILI9341 library updated on 1st July 2015 to version 12, this latest version is attached here to step 8:

    1. Minor bug when rendering letter 'T' in font 4 without background fixed
    2. RLE fonts are now rendered without overlap (improves rendering speed and stops flicker of adjacent character)

    Step 9: TFT_ILI9341 Library Updated 31/7/15

    TFT_ILI9341 library has been updated to version 14 beta, this latest version is attached below.

    1. Text algnment, the datum for drawing strings and numbers can be changed with a new function: tft.setTextDatum(datum); See example sketch included "TFT_String_Align"

    2. Performance improvements, in particular line drawing is much faster now (thanks Spellbuilder)

    3. There is a new "User_Setup.h" file inside the library where all the settings can be controlled, eg. pins used for the TFT interface and the fonts loaded. See the comments in the header file. The pins are defined in this header so to invoke the custom library the pin references must be removed from legacy sketches so it reads: TFT_ILI9341 tft = TFT_ILI9341(); // Invoke custom library

    4. The FastPin.h header has been adopted from the FastLED library, this allows any control pins to be used for CS, DC and RST whilst still getting the best pin toggle performance (thanks Marstom)

    This v14b is a beta version as there is a minor bug in the drawFloat() function that I need to fix!

    This library has been developed for my own hobby use. If you do find a problem with it then please report bugs here. TTFN

    Step 10: TFT_ILI9341 Library Now on Github

    As I have been making minor tweaks to the ILI9341 library (and because it has proved to be popular!) I have put the TFT_ILI9341 library on Github. You can down load the latest here:

    https://github.com/Bodmer/TFT_ILI9341

    Using the Download Zip button is probably the easiest method if you do not have a GitHub client loaded.

    A request has been posted to the Arduino team to have it listed in the IDE Library Manager.

    Typically performance is 3 times faster than the standard Adafruit GFX library (see table for speed comparison) and up to 20 times faster than UTFT. So the graphics drawing performance is now about as good as it is going to get on a humble UNO/AVR Arduino!

    Full 320 x 240 screens are cleared in 174ms, raw image files can be pulled off an SD Card and drawn in 400ms using the tweaked version of the SdFat library here:

    https://github.com/Bodmer/TFT_SdFat

    I have also created a touch screen library for the 2.4" ILI9341 TFT display fitted with the XPT2046 touch controller. The touch library can be downloaded here:

    https://github.com/Bodmer/TFT_Touch

    I will be creating a more comprehensive instructable at a future date to document all the font and formatting features of the graphics library.

    Step 11: Update: June 2016 - More Libraries on GitHub

    I have improved the performance of the ST7735 and S6D02A1 libraries. Copies are available here:

    TFT_ST7735 library.

    and here:

    TFT_S6D02A1 library.

    7 People Made This Project!

    Recommendations

    • Audio Contest 2018

      Audio Contest 2018
    • Tiny Home Contest

      Tiny Home Contest
    • Furniture Contest 2018

      Furniture Contest 2018

    283 Discussions

    0
    None
    Rolo664u

    3 years ago on Introduction

    Hi, nice job ! I have it running now on an UNO now with a 2,2 inch display. Never had a library before that fitted in the UNO and had such nice characters !

    I'm now trying to port it to a STM Nucleo board where I have loads of Flash available. In the code I see fonts 1,3, and 5 mentioned but the are not provided. Do you have these fonts available ? Would like to try them when I have the Nucleo up and running. I use the non RLE fonts.

    Thanks !

    1 reply
    0
    None
    BodmerRolo664u

    Reply 3 years ago on Introduction

    Hi, thanks for your feedback.
    The font numbers 1, 3 and 5 were reserved for intermediate sizes of the same font style (aka similar to Helvetica), but I did not need these sizes in the end and never created the required files. If you have a particular need then I may be able to create new files but you will need to be patient as I spend less time tinkering with electronics and software in the summer!

    0
    None
    tolisn63

    5 days ago on Step 9

    Hi, and thanks for this great library.

    1. Where can I find the command syntax of all the commands used it the library ?

    2. Is there anyway to use other fonts ?

    0
    None
    SanjeevkantS

    7 weeks ago

    Dear,

    again thanks for fentastic codes for ST7735. After a deep check I have successed to run all 03

    example......thanks again

    0
    None
    SanjeevkantS

    8 weeks ago

    Dear,

    I just use your good library, first I try "TFT_Clock_ST7735.ino" sketch exmp but I always get an errors " as given.

    Arduino: 1.8.3 (Windows XP), Board: "Arduino/Genuino Uno"

    TFT_Clock_Digital_ST7735:46: error: 'conv2dec' was not declared in this scope

    uint8_t hh=conv2dec(__TIME__), mm=conv2d(__TIME__+3), ss=conv2d(__TIME__+6); // Get H, M, S from compile time

    ^

    C:\DOCUME~1\SANJIV~1\LOCALS~1\Temp\arduino_modified_sketch_510720\TFT_Clock_Digital_ST7735.ino: In function 'void loop()':

    TFT_Clock_Digital_ST7735:68: error: 'ss' was not declared in this scope

    ss++; // Advance second

    ^

    TFT_Clock_Digital_ST7735:71: error: 'mm' was not declared in this scope

    omm = mm;

    ^

    TFT_Clock_Digital_ST7735:98: error: 'mm' was not declared in this scope

    if (omm != mm) { // Only redraw every minute to minimise flicker

    ^

    exit status 1
    'conv2dec' was not declared in this scope

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

    Thanks a lot

    0
    None
    PascalC1

    2 months ago

    Thanks a lot for this great library! It is really fast.

    I use a 128x128 pixel ST7735 TFT however there is an offset of two or three pixels left and top. I have read the tutorial, but found nothing about a offset correction. Furthermore, there is a problem with the positioning of the text after an SD card has been initialised.

    With following code:

    #include // Hardware-specific library

    #include

    #include

    TFT_ST7735 tft = TFT_ST7735(128, 128); // Invoke custom library

    #define SD_CS 37

    Sd2Card card;

    void setup(void) {

    Serial.begin(115200);

    Serial.print("Hello! ST7735 TFT Test");

    // Use this initializer if you're using a 1.8" TFT

    tft.init(); // initialize a ST7735S chip

    tft.setRotation(1); // landscape

    tft.fillScreen(ST7735_BLACK);

    tft.setCursor(0, 0);

    tft.print("TEST:");

    tft.println(" OK");

    tft.println("Init SD card");

    tft.print("SD:");

    boolean initSD = card.init(SPI_HALF_SPEED, SD_CS);

    if (!initSD) {

    tft.println(" NOK");

    } else {

    tft.println(" OK");

    }

    }

    void loop() {}}


    As you can see on the picture, the text "OK" after the text "Test" is ok. The "OK" to "SD:" is some how under the text "DS:".

    I have no idea how to fix that.

    Some idea?

    THX a lot!

    20180718_180506.jpg
    1 reply
    0
    None
    PascalC1PascalC1

    Reply 2 months ago

    SD problem fixed be using the SdFat.h lib.

    Right now just the OFFSET problem ...

    0
    None
    majdi131590

    6 months ago

    Hi Bodmer,

    thank you very much for this work, please check attached pictures, it working fine using tft7735 1.8" and everything alright except, when i use code to read from my sensor: reading= analogRead(A0).

    as you can see from the picture first reading is ok but when i change the potentio-meter numbers not clear as the previous numbers seems not updated, i guess its string char conversion but i stuck and i need help if that ok to clear this.

    Thank you very much

    1.JPG2.JPG
    2 replies
    0
    None
    Bodmermajdi131590

    Reply 4 months ago

    Set the foreground and background colors and the test should overwrite old values.

    0
    None
    Bodmermajdi131590

    Reply 6 months ago

    It looks like you have switched off rendering the font text background?

    Use a line like:

    tft.setTextColor(TFT_WHITE,TFT_BLACK);

    0
    None
    mike246

    5 months ago

    Hi,

    Thanks for the nice libraries.

    I converted some parts to work on the ILI9163 ,works great!

    Draw lines,circles,various colors,write strings...etc.

    But i cannot write a variable value on the tft display.

    I tried the ''drawChar'' from the library ,I use the ITOA function in Avr Studio to write the ADC value ,,,but cannot get it to work with your library and ARDUINO.

    Must I use ITOA or does your library do all the work,I can follow what you do but only up to

    a point ,some of your code gets real deep beyond me.

    I only started C Programming a few months back....many years of playing with Pic's and Assembler.

    Can you please give a small example of how to use this function.

    Thanks Great Work!

    1 reply
    0
    None
    Bodmermike246

    Reply 4 months ago

    The library has evolved, I am not sure which variant you have adapted but the library now has two functions that should do what you want:


    drawNumber(value, x, y, font),


    drawFloat(floatNumber, number_of_decimal_places, x, y, font),

    0
    None
    NagyR1

    5 months ago

    I just want to say one thing. This was the single most usefull arduino tutorial i have ever found.Everything else is well documented always, but this post touched upon every problem i had with these cheap displays. I want to thank you a lot for this post and this library.

    1 reply
    0
    None
    BodmerNagyR1

    Reply 4 months ago

    Thanks for the feedback, I had hoped folk would benefit. Hope your project is a success.

    0
    None
    SteveBar

    1 year ago

    Hi Bodmer,

    Awesome work and quite a long thread! :-) I read through most of it hoping for some info, but didn't.

    I am using a ST7735 display on a TeensyLC. I am using the TFT_ST7735.h lib from github. I get a ton of FastPin errors from the compiler, I added a few below. I tried commenting out the #include <TFT_FastPin.h> in my sketch as well as the TFT_ST7735.h file but no luck. I am using pins 13 for SCLK and 11 for MOSI (SPI0 on the LC) I defined the other 3 pins in the User_Setup.h file. I have a few questions below but feel free to expound on the topic and ignore the Q's. :-)

    1) Can I use this lib on the LC?

    2) Do I need to use FastPin, if yes, is there an LC version?

    3) Does the Adafruit_ST7735_AS.h fix or get around this?

    Thanks so much!

    Steve

    PS It's so nice to see the civil discourse in this thread! Some others are frightening!

    C:\Users\Steve B\Documents\Arduino\libraries\TFT_ST7735-master\TFT_ST7735.cpp: In constructor 'TFT_ST7735::TFT_ST7735(int16_t, int16_t)':

    C:\Users\Steve B\Documents\Arduino\libraries\TFT_ST7735-master\TFT_ST7735.h:83:19: error: 'FastPin' was not declared in this scope

    #define TFT_DC_D FastPin<TFT_DC>::hi()

    ^

    C:\Users\Steve B\Documents\Arduino\libraries\TFT_ST7735-master\TFT_ST7735.cpp:50:3: note: in expansion of macro 'TFT_DC_D'

    TFT_DC_D;

    3 replies
    0
    None
    SteveBarSteveBar

    Reply 1 year ago

    Update: I got the Adafruit_ST7735_AS & Adafruit_GFX_AS.h libs to work. The font draws a ton faster than the orig lib!!! I was wondering if the justification was an issue in this lib. I'm using the display to show the current value of an encoder and the numbers seem to be left justified regardless of the function I use. So as the count goes from 1's to 10's to 100's it displays left to right. So while counting back down the number starts in the hundreds column, and leaves the previous LeastSigDigs visible, making it always look like a 3 digit number. I think it would be a good idea to migrate to the TFT lib. Any help would be appreciated.

    Thanks,

    Steve

    0
    None
    deu1SteveBar

    Reply 8 months ago

    Hi Steve,

    Where did you find the Adafruit_GFX_AS.h library. I have looked all over the web for it. Can't find it. Any help would be appreciated.

    Dan

    deu1@shaw.ca

    0
    None
    Bodmerdeu1

    Reply 8 months ago

    It is in the Libraries_v7.zip file in Step 2 of the Instructable.