T-Watch. Getting started with the TFT_eSPI library. Display text, shapes, touch detection

Get started with the TFT_eSPI library adapted to the screens of #ESP32 #TTGO @lilygo9 T-Watch. How to display text, shapes, detect pressing on the touch screen. Source code compatible #Arduino and @PlatformIO_Org
Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on email
Share on whatsapp

The LilyGoWatch library includes a pre-configured version of Badmer’s TFT_eSPI library which allows you to display text, basic geometric shapes (rectangle, circle, ellipse, triangle, line, point …), images and lots of ‘other things.

The examples given in this tutorial are adapted to the TFT screens of ESP32 TTGO T-Watch watches . They are compatible with other Arduino, ESP32 or ESP8266 screens and development boards.

 

In this article we will only use the TFT color touch screen present in the T-Watch Touch and T-Watch 2020. However, you should not experience any difficulty using it on models equipped with an eInk screen (T -Block and T-Bot).

If you are new to app development for ESP32 TTGO T-Watch cases and watches from manufacturer LilyGo, you can start by reading this introductory article.

How to use the TFT_eSPI library in an Arduino T-Watch project?

The LilyGoWatch library includes a pre-configured version (source code) of the TFT _eSPI library  from Bodmer . This is loaded at startup with the parameters that correspond to the on-board screen by the T-Watch used.

The TFT_eSPI library supports the eInk and TFT screens of the different T-Watch models.

So you don’t have to do anything! Everything works out of the box 🙂

Color palette

We have a predefined color palette accessible using the following constants

▉ TFT_BLACK
▉ TFT_NAVY (#000080)
▉ TFT_DARKGREEN (#008000)
▉ TFT_DARKCYAN (#008080)
▉ TFT_MAROON (#80000)
▉ TFT_PURPLE #800080)
▉ TFT_OLIVE (#808000)
▉ TFT_LIGHTGREY (#D3D3D3)
▉ TFT_DARKGREY (#808080)
▉ TFT_BLUE (#0000FF)
▉ TFT_GREEN (#00FF00)
▉ TFT_CYAN (#00FFFF)
▉ TFT_RED (#FF0000)
▉ TFT_MAGENTA (#FF00FF)
▉ TFT_YELLOW (#FFFF00)
▢ TFT_WHITE (#FFFFFF)
▉ TFT_ORANGE (#FFB400)
▉ TFT_GREENYELLOW (#B4FF00)
▉ TFT_PINK (#FFC0CB)
▉ TFT_BROWN (#964B00)
▉ TFT_GOLD (#FFD700)
▉ TFT_SILVER (#C0C0C0)
▉ TFT_SKYBLUE (#87CEEB)
▉ TFT_VIOLET (#B42EE2)

Functions of the TFT_eSPI library (API)

Here is a list of the most common functions offered by the TFT_eSPI library. In the absence of official documentation, the functions were extracted directly from the source code of the LilyGoWatch library on GitHub .

Deprecated functions are crossed out.

List of variables used

  • m integer
  • color in hexadecimal format
  • x0, y0, x1, y1 coordinates (in pixels)
  • r, rx, ty rayon (in pixels)
  • w (width) width in pixel
  • h (height) height and pixels

Screen and cursor

  • width() screen width in pixels
  • height() height of the screen in pixels
  • setRotation(uint8_t m) rotates the contents of the screen. Orientation is a number from 0 to 3 and 4 to 7 for a bitmap
    • getRotation() returns the screen orientation
  • invertDisplay(bool i) invert display colors i = 1 invert, i = 0 normal
  • fillScreen(uint32_t color) colors the background of the screen. In fact the function draws a full rectangle taking up the entire surface of the screen
  • setCursor(int16_t x, int16_t y) positions the cursor.
    • getCursorX returns the X coordinate of the cursor
    • getCursorY returns the Y coordinate of the cursor
  • setPivot(int16_t x, int16_t y) screen pivot point
    • getPivotX() X coordinate of the pivot point
    • getPivotY() X coordinate of the pivot point
  • readPixel(int32_t x, int32_t y) Reads the color of a pixel in 565 format

Geometric primitives

  • drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) draws the outline of a circle
  • fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) draws a filled circle
  • drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) draws the outline of an ellipse
  • fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) draws a filled ellipse
  • drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) draws the outline of a rectangle
  • fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) draws a filled rectangle
  • drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) outline of a rectangle with a rounded edge. All angles have the same radius
  • fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) same but full
  • drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) outline of a triangle. You have to pass the coordinates of the three vertices
  • f illTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) same but with a filled triangle.
  • drawPixel(int32_t x, int32_t y, uint32_t color) draw a color pixel
  • drawLine(int32_t x0, int32_t y0 , int32_t x1, int32_t y1 , uint32_t color) draws a line between two arbitrary points
  • drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) vertical line of length
  • drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) horizontal line of length l

Pictures

  • drawBitmap(int16_t x, int16_t y, const uint8_t * bitmap, int16_t w, int16_t h, uint16_t color) displays an image stored in an array
  • drawXBitmap (int16_t x, int16_t y, const uint8_t bitmap [], int16_tw, int16_th, uint16_tcolor) draws a monochrome image stored in an array. For example, you can convert a JPG or PNG image using GIMP to XBM format and retrieve the point array.
  • setBitmapColor(uint16_t c, uint16_t b) assigns the background color of a bitmap image

Fonts

  • fontsLoaded() returns a 16-bit encoded value indicating the loaded fonts
  • fontHeight(int16_t font)  height of the font
  • setFreeFont(const GFXfont * f) Sets the GFX font to use

Text, character, string

  • setTextSize(uint8_t s) sets the size of the text. It must be between 1 and 7 (max.)
  • setTextColor(uint16_t c) assigns the text color. Color in hexadecimal
  • setTextColor(uint16_t c, uint16_t b) same but also defines the background color. Preferred for text that changes often (clock, coordinates, position …), this avoids redrawing the entire screen at each update.
  • setTextWrap(bool wrapX, bool wrapY) does not work …
  • textWidth(const String & string, uint8_t font) returns the width in pixels of a string in a given font
  • drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size) displays (draws) a character at the specified position.

Display of justified string (Datum)

Positions available

  • TL_DATUM 0 // Top left (default)
  • TC_DATUM 1 // Upper center
  • TR_DATUM 2 // Top right
  • ML_DATUM 3 // Left midfielder
  • CL_DATUM 3 // Center left, as above
  • MC_DATUM 4 // Central center
  • CC_DATUM 4 // Center to center, as above
  • MR_DATUM 5 // Right midfielder
  • CR_DATUM 5 // Center right, as above
  • BL_DATUM 6 // Bottom left
  • BC_DATUM 7 // Bottom center
  • BR_DATUM 8 // Bottom right
  • L_BASELINE 9 // Base line of the left character (line on which the character ‘A’ would sit)
  • C_BASELINE 10 // Base line of the central character
  • R_BASELINE 11 // Base line of the right character

Methods

  • setTextDatum(uint8_t d) text reference. Use one of the constants above
  • setTextPadding(uint16_t x_width) inner margin (equivalent to CSS style)
    • getTextPadding() returns the current padding
  • drawString(const String & string, int32_t poX, int32_t poY) draws a string (type String)
  • drawCentreString(const String & string, int32_t dX, int32_t poY, uint8_t font) draws a string (type String) centered on position X
  • drawRightString(const String &string, int32_t dX, int32_t poY, uint8_t font)

Conversions

Some useful conversion methods

  • Colors
    • color8to16(uint8_t color) convert 8 bit color to 16 bit color value 565
    • color16to24(uint16_t color565) convert 16-bit color to 24-bit color value 888
    • color24to16(uint32_t color888) convert a 24 bit color to a 16 bit color value 565
  • Chains
    • decodeUTF8(uint8_t c) Convert an ASCII character to UTF-8 format
    • decodeUTF8(uint8_t * buf, uint16_t * index , uint16_t remaining) Decode a character buffer in extended ASCII format in UTF-8

The library is not yet documented, you have to look directly in the source code.

How to access the functions of the TFT_eSPI library?

In computer science, the LilyGoWatch Library is a wrapper, ie it unifies access to a set of libraries.

The methods offered by the different libraries are accessible from the C ++ TTGOClass object.

To access a device then functions (C ++ methods), we use the arrow operator ->. This is the equivalent of the point. in Javascript for example.

Here is an example of a minimal program that lights the screen and colors the background in red

#include <LilyGoWatch.h>

TTGOClass *ttgo;

void setup() {
    ttgo = TTGOClass::getWatch();
    ttgo->begin();     
    ttgo->openBL();
        
    ttgo->tft->fillScreen(TFT_RED);
}

void loop(){}

We must start by initializing the watch object by calling the getWatch() method. This object will contain all the methods to access the watch peripherals (accelerometer, GPS, RTC clock, TFT or eInk screen, etc.).

watch = TTGOClass::getWatch();

Then we must turn on the TFT screen of the watch by calling the begin() method , then the backlight using the openBL() method.

watch->begin();  // Initialise l'écran couleur TFT
watch->openBL(); // Allume le rétro-éclairage de l'écran

Now we access functions like this

watchobject->driver->function()

Which gives to put the bottom of the screen in red

ttgo->tft->fillScreen(TFT_RED);

Create a TFT_eSPI object containing the screen driver

It is also possible to create an object of type TTGOClass which will contain the screen drivers to reduce the code

TFT_eSPI * tft = ttgo->tft;
tft->fillScreen(TFT_RED);

Know the screen resolution

It is often necessary to know the screen resolution to position the elements. For this, we have the width() and height() methods to know respectively the width and height of the screen in pixels.

  w = ttgo->tft->width();
  h = ttgo->tft->height();
  Serial.printf("Screen size %u * %u", w, h);

How to position the cursor on the screen?

The TFT_eSPI library uses a cursor to position the elements on the screen. The X and Y coordinates of the cursor are determined from the upper left corner of the screen. The origin changes depending on the orientation of the screen.

To manually change the screen orientation, go to this paragraph to learn how.

ttgo t-watch lilygo tft_espi screen oriantation reference pos2

The cursor is used to display text using the standard functions print, println or printf for example.

The getCursorX and getCursorY functions allow you to know the position of the cursor and setCursor to position the latter at the ready pixel.

However, other drawing methods (including drawing text) simply use coordinates.

Detect when user touch screen and retrieve position

The getTouch(x, y) method detects when the user touches the screen. The method returns a boolean and assigns the X and Y coordinates of the touched point on the screen.

The getTouch() method is directly accessible from the ttgo class of the LiLyGoWatch library

The library is delivered with the Touch Pad example in the BasicUnit folder

TTGOClass *ttgo;

char buf[128];

void setup()
{
    ttgo = TTGOClass::getWatch();
    ttgo->begin();
    ttgo->openBL();
    ttgo->tft->fillScreen(TFT_BLACK);
    ttgo->tft->setTextFont(2);
    ttgo->tft->setTextColor(TFT_WHITE, TFT_BLACK);
    ttgo->tft->drawString("T-Watch Touch Test", 62, 90);
}

void loop()
{
    int16_t x, y;
    if (ttgo->getTouch(x, y)) {
        sprintf(buf, "x:%03d  y:%03d", x, y);
        ttgo->tft->drawString(buf, 80, 118);
    }
    delay(5);
}

How does the TFT_eSPI library build the screen?

Before going any further, it’s important to understand how the library constructs the screen. You have to think of the screen as an array of points. When we draw a shape (or text or an image), we “only light” points in the table with a certain color.

That is to say that the order of execution of the functions will have a direct impact on the construction of the display. Here for example the blue circle hides part of the white text placed itself on the green rectangle.

t-watch tft_espi library order draw elements

Even if the TFT_eSPI library is very powerful, it does not manage the graphic elements.

When updating the display, we have two solutions

Rebuild the entire screen with each modificationOnly rebuild what is strictly necessary.

For example erase (give the background color) of the hand of a clock then draw the new position.

AdvantageEasyMore complex
DisadvantageHigh risk of flickering.

The flashing increases with the number of items to be displayed and the refresh rate.

Efficient, little flickering

Display text with the C ++ print(), println() or printf() functions

To display text, you can use the same C ++ methods that write to the serial port print(), println() or printf().

The macro F() which allows to place the string in the Flash memory is supported but it is however of no interest.

The text is displayed at the cursor position. Here for example, we vary the size of the font between 1 and 7 (it is not possible to go beyond).

  TFT_eSPI * tft = ttgo->tft;
  tft->fillScreen(TFT_BLACK);
  tft->setTextColor(TFT_WHITE);
    for (size_t i = 1; i <= 7; i++){  // La taille doit être comprise entre 1 et 7
      tft->setTextFont(1);     // Uniquement 1
      tft->setTextSize(i);     // change la taille        
      tft->setCursor(0, 0);
      txt = "Text with size "; txt += i;
      Serial.print("Display"); Serial.println(txt);
      tft->println(txt);
      delay(1000);
      tft->fillScreen(TFT_BLACK);
    }

Display a scrolling list

In the previous example the cursor remains at the origin (0,0) and the screen is erased (repainted in black) at each iteration of the for loop. The println() method moves the cursor to the next line. However, the TFT_eSPI library does not manage the vertical scrolling of the print function.

To display a list that exceeds the height of the screen, the trick is to test the position of the cursor and return the latter to the top of the screen as soon as the current position exceeds the height of the screen.

We saw previously how to recover the screen resolution.

Here is an example of code that displays a list of 20 items on the screen.

  TFT_eSPI * tft = ttgo->tft;
  tft->fillScreen(TFT_BLACK);
  tft->setTextColor(TFT_WHITE, TFT_BLACK);
  tft->setTextSize(2);
  tft->setCursor(0,0);
  
  for (size_t i = 0; i <= 20; i++) {
    // Renvoi le curseur en haut de l'écran 
    if ( tft->getCursorY() >= h ) {
      tft->fillScreen(TFT_BLACK);
      tft->setCursor(0,0);
    }
    tft->printf("This is the line %u \n", i);
    delay(200);
  }
  tft->setTextSize(1);
  tft->println(" \n *** End of the list ***");

Advanced methods to justify the position of the text

The standard methods do not allow you to manage the justification of the text. That is to say that the text is necessarily positioned on the left.

To justify the text to display, all you have to do is define the desired position using the setTextDatum( DATUM_TYPE ) method . We then display (draw) the text using the drawString() function .

Here is an example of text centered in the center of the screen

ttgo->tft->fillScreen(TFT_BLACK);
ttgo->tft->setTextColor(TFT_WHITE);
ttgo->tft->setTextDatum(MC_DATUM);
ttgo->tft->drawString("Text in center", w / 2, h / 2, 2);

Draw geometric shapes, rectangle, circle, ellipse, line, point …

Now let’s move on to creating simple geometric shapes. The library allows you to draw the outline or fill the following simple shapes: rectangle, triangle, circle, ellipse.

The outline has the same color as the background.

You can also draw arbitrary lines between two points, horizontal or vertical.

Here is an example that draws a horizontal line 10 pixels from the edge of the screen

  tft->drawFastHLine(0, 10, 240, TFT_DARKGREY);

Go to the end of the article to find a complete example.

ttgo t-watch tft_espi dra line rectangle circle triangle point ellipse

Change screen orientation

By default, the LilyGoWatch library orients the screen in the direction of the bracelet for each type of T-Watch. Nothing prevents you from changing the screen orientation for your application. The rotation is done clockwise like this.

Position 0Position 1Position 2 (default)Position 3
ttgo t-watch lilygo tft_espi screen oriantation reference pos0ttgo t-watch lilygo tft_espi screen oriantation reference pos1ttgo t-watch lilygo tft_espi screen oriantation reference pos2ttgo t-watch lilygo tft_espi screen oriantation reference pos3

Here is the source code with which the images were created. It puts into practice most of the concepts discussed previously:

#include <LilyGoWatch.h>

// C++ object which will allow access to the functions of the Watch 
TTGOClass *ttgo;
// C++ object that wil contain TFT_eSPI methods for quick access 
TFT_eSPI *tft;

int w, h, orientation; // Screen resolution and orientation 
int p = 5 ;  // padding | marge

// Prototype
void drawReference();

void setup() {
  Serial.begin(115200);
  // Get ttgp object and set up the display 
  ttgo = TTGOClass::getWatch();
  ttgo->begin();     
  ttgo->openBL();

  // Easy access to TFT library functions  
  tft = ttgo->tft;
  
  // Get Screen resolution | récupère le résolution de l'écran
  w = tft->width();     // width  | largeur
  h = tft->height();    // height | hauteur

  // Current screen orientation 
  orientation = tft->getRotation();
  drawReference();
}

void loop() {
  int16_t x, y;
  if (ttgo->getTouch(x, y)) {
    if ( orientation == 3 ) {
      orientation = 0;
    } else {
      orientation += 1;
    }
    tft->setRotation(orientation);
    Serial.printf("Change screen orientation %u \n", orientation);
    drawReference();
    delay(100);
  }
}

void drawReference(){
    // Clean Screen  
  tft->fillScreen(TFT_BLACK);  // Fill background in black 
  tft->setTextFont(1);
  tft->setTextSize(2);
  tft->setTextColor(TFT_WHITE, TFT_BLACK);
  tft->setCursor(0, 0);

  // Draw reference | dessine le référentiel X/Y
  tft->drawFastHLine(p,p, w - 2*p, TFT_WHITE);
  tft->drawFastVLine(p,p, h - 2*p, TFT_WHITE);

  // Draw X and Y, Use http://www.asciitable.com/ (for example) to find ascii char code
  // drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg, uint8_t size)
  tft->drawChar(w - 3*p, 3*p, 88, TFT_WHITE, TFT_BLACK, 2); // X
  tft->fillTriangle(w, p, w - 2*p, 0, w - 2*p, 2*p, TFT_RED ); // Triangle -> X arrow | flèche X
  tft->drawChar(3*p, w - 3*p, 89, TFT_WHITE, TFT_BLACK, 2);  // Y
  tft->fillTriangle(p, h, 0, h - 2*p, 2*p, h - 2*p, TFT_RED ); // Y arraw | flèche Y
  // Origine
  tft->fillCircle(p,p,p,TFT_RED);

  // Indicate user to touch screen to rotate || 
  tft->setTextDatum(MC_DATUM); 
  tft->drawString("Touch Screen", w / 2, h / 2 - 10, 1);
  tft->drawString("to rotate", w / 2, h / 2 + 10, 1);
  tft->drawString(String(orientation), w / 2, h / 3 + 10, 1);
}

Full code of examples

Here is the complete code for all the examples presented previously.

You can also get the source code directly from the GitHub repository

Getting started with the TFT_eSPI library and the T-Watch

logo github

Screen orientation

logo github

The code is compatible with the Arduino or PlatfomIO IDE.

/* Arduino IDE - uncomment your watch */
//#define LILYGO_WATCH_2019_WITH_TOUCH
//#define  LILYGO_WATCH_2019_NO_TOUCH
//#define LILYGO_WATCH_BLOCK=1
//#define LILYGO_WATCH_2020_V1

/* PlatformIO -> Select your watch in platformio.ini file */
#include <Arduino.h>
#include <LilyGoWatch.h>

// C++ object which will allow access to the functions of the Watch 
TTGOClass *ttgo;
// C++ object that wil contain TFT_eSPI methods for quick access 
TFT_eSPI *tft;

String txt; 
int w = 240;    // Screen width 
int h = 240;    // Screen height 
int16_t x, y;
char buf[128];

/* Prototypes */
void fillScreenBackground();
void displayFontSize();
void drawBasic();
void drawStringDemo();
void screenOrientationDemo();
void printAListToScreen();

void setup() {
    Serial.begin(115200);
    // Get Watch object and set up the display 
    ttgo = TTGOClass::getWatch();
    ttgo->begin();     
    ttgo->openBL();
    tft = ttgo->tft;
    // Uncomment function you want to test 
    fillScreenBackground();
    displayFontSize();
    drawBasic();
    drawStringDemo();
    screenOrientationDemo();
    printAListToScreen();
    
    // Clean screen | efface l'écran 
    tft->fillScreen(TFT_BLACK);
    tft->setTextColor(TFT_WHITE, TFT_BLACK);
    tft->setTextDatum(MC_DATUM);
}

void loop(){
  // Display cursor position each time the screen is touched 
  if (ttgo->getTouch(x, y)) {
    sprintf(buf, "  x:%u  y:%u   ", x, y);
    tft->drawString(buf, w / 2, h / 2);
    Serial.println(buf);
  }
}

// Available colors
/* 
 * TFT_BLACK         0,   0,   0 
 * TFT_NAVY          0,   0, 128 
 * TFT_DARKGREEN     0, 128,   0 
 * TFT_DARKCYAN      0, 128, 128 
 * TFT_MAROON      128,   0,   0 
 * TFT_PURPLE      128,   0, 128 
 * TFT_OLIVE       128, 128,   0 
 * TFT_LIGHTGREY   211, 211, 211 
 * TFT_DARKGREY    128, 128, 128 
 * TFT_BLUE          0,   0, 255 
 * TFT_GREEN         0, 255,   0 
 * TFT_CYAN          0, 255, 255 
 * TFT_RED         255,   0,   0 
 * TFT_MAGENTA     255,   0, 255 
 * TFT_YELLOW      255, 255,   0 
 * TFT_WHITE       255, 255, 255 
 * TFT_ORANGE      255, 180,   0 
 * TFT_GREENYELLOW 180, 255,   0 
 * TFT_PINK        255, 192, 203     
 * TFT_BROWN       150,  75,   0 
 * TFT_GOLD        255, 215,   0 
 * TFT_SILVER      192, 192, 192 
 * TFT_SKYBLUE     135, 206, 235 
 * TFT_VIOLET      180,  46, 226 
*/
void fillScreenBackground(){
    Serial.println("Red");
    tft->fillScreen(TFT_RED);
    delay(1000);
    Serial.println("Green");
    tft->fillScreen(TFT_GREEN);
    delay(1000);
    Serial.println("Black");
    tft->fillScreen(TFT_BLACK);
    delay(1000);
}

void getScreenSize(){
  w = tft->width();
  h = tft->height();
  Serial.printf("Screen size %u * %u", w, h);
}

// Draw primitives 
void drawBasic(){
  int margin = 20;
  int _delay = 500;
  getScreenSize();
  
  Serial.println("Draw a rectangle");
  tft->fillScreen(TFT_BLACK);
  tft->drawRect(margin,margin, w - ( 2* margin ), h - ( 2 * margin),TFT_RED);
  delay(_delay);

  Serial.println("Draw a filled rectangle");
  // fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
  tft->fillRect(2 * margin, 2 * margin, w - ( 4 * margin), h - (4 * margin), TFT_VIOLET);
  delay(_delay);

  Serial.println("Draw a rounded corner rectangle outline");
  //drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color)
  tft->drawRoundRect(3 * margin, 3 * margin, w - ( 6 * margin), h - (6 * margin), 8, TFT_YELLOW);
  delay(_delay);

  Serial.println("Draw a line");
  // drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color)
  tft->drawLine(0, 0, w, h, TFT_DARKGREY);
  delay(_delay);  

  Serial.println("Draw a triangle outline using 3 arbitrary points");
  // drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color)
  tft->drawTriangle(w,h - 1, w - 40 , h, w - 20, h - 30, TFT_PURPLE);
  delay(_delay); 

  Serial.println("Draw a circle outline");
  //drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color)
  tft->drawCircle(w / 2, h / 2, 80, TFT_SKYBLUE);
  delay(_delay);

  Serial.println("Draw a ellipse outline");
  //drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color)
  tft->drawEllipse(w, h, 80, 60, TFT_SKYBLUE);
  delay(_delay);

  Serial.println("Draw horizontal line");
  // drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
  tft->drawFastHLine(0, 0, w, TFT_DARKGREY);
  delay(_delay);  
  
  Serial.println("Draw Vertical line");
  // drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
  tft->drawFastVLine(0, 0, h, TFT_DARKGREY);
  delay(_delay);
  
  Serial.println("Draw A char (ascii 65)");
  //drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size)
  // Use this to find char code http://www.asciitable.com/
  tft->drawChar(margin, margin, 65, TFT_BLUE, TFT_WHITE, 2);
  delay(_delay);

  Serial.println("Draw a string");
  //drawString(const char *string, int32_t poX, int32_t poY)
  tft->drawString("T-Watch",margin, margin * 2);
  delay(_delay);

  Serial.println("Draw a pixel");
  //drawPixel(int32_t x, int32_t y, uint32_t color)
  tft->drawPixel(w / 2 , h / 2, TFT_RED);
  delay(_delay);
  /* Other usefull functions 
      invertDisplay(bool i)
      decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining)
  */
}

// Display font 
void displayFontSize(){
  tft->fillScreen(TFT_BLACK);
  tft->setTextColor(TFT_WHITE);
    for (size_t i = 1; i <= 7; i++){ // Size from 1 to 7 (includes) tft->setTextFont(1);     // Only font 1 is available 
      tft->setTextSize(i);     // Change size         
      tft->setCursor(0, 0);
      txt = "Text with size "; txt += i;
      Serial.print("Display"); Serial.println(txt);
      tft->println(txt);
      delay(1000);
      tft->fillScreen(TFT_BLACK);
    }
}

void drawStringDemo(){
  tft->fillScreen(TFT_BLACK);
  tft->setTextColor(TFT_WHITE);
  tft->setTextSize(2); 
  for (size_t i = 0; i < 12; i++) { tft->setTextDatum(i);
    Serial.printf("Display string with justification %u \n", tft->getTextDatum());
    tft->drawString("TFT_eSPI Demo", w / 2, h / 2, 2);
    delay(1000);
    tft->fillScreen(TFT_BLACK);
  }
}

void screenOrientationDemo(){
  Serial.printf("Current screen orientation %u \n", tft->getRotation());
  tft->fillScreen(TFT_BLACK);
  tft->setTextColor(TFT_WHITE);
  tft->setTextDatum(MC_DATUM);
  tft->setTextSize(2); 
  tft->drawString("Rotate Screen", w / 2, h / 2, 2);
  for (size_t i = 1; i < 4; i++) { // rotate the screen orientation m = 0-3 or 4-7 for BMP drawing //setRotation(uint8_t m) Serial.printf("Rotate the screen to %u \n", i); tft->setRotation(i);
    tft->fillScreen(TFT_BLACK);
    tft->drawString("Rotate Screen", w / 2, h / 2, 2);
    delay(1000);
  }
  
  tft->setRotation(2);
  tft->fillScreen(TFT_BLACK);
  tft->drawString("Rotate Screen", w / 2, h / 2, 2);
}

// Use printf or println to display a list to screen 
void printAListToScreen(){
  //TFT_eSPI * tft = tft;
  tft->fillScreen(TFT_BLACK);
  tft->setTextColor(TFT_WHITE, TFT_BLACK);
  tft->setTextSize(2);
  tft->setCursor(0,0);
  
  for (size_t i = 0; i <= 20; i++) { // Return cursor on the top of the screen if ( tft->getCursorY() >= h ) {
      tft->fillScreen(TFT_BLACK);
      tft->setCursor(0,0);
    }
    tft->printf("This is the line %u \n", i);
    delay(200);
  }
  tft->setTextSize(1);

  tft->println(" \n *** End of the list ***");
  delay(2000);
}

The platformio.ini configuration file

env:ttgo-t-watch]
platform = espressif32
board = ttgo-t-watch
framework = arduino
build_flags =
    ;-D LILYGO_WATCH_2019_WITH_TOUCH=1
    ;-D LILYGO_WATCH_2019_NO_TOUCH=1
    ;-D LILYGO_WATCH_BLOCK=1
    -D LILYGO_WATCH_2020_V1=1
lib_deps =
    TTGO TWatch Library
upload_speed = 2000000
monitor_speed = 115200

And the little demo video that goes well

Updates

2020/11/25 Add drawXBitamp function

2020/11/16 Publication of the article

Version française

Click to rate this post!
[Total: 1 Average: 5]

Are you having a problem with this topic?

Maybe someone has already found the solution, visit the forum before asking your question
Ask your question

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on email
Share on whatsapp

Did you like this project ? Don't miss any more projects by subscribing to our weekly newsletter!

We will be happy to hear your thoughts

      Leave a Reply

      DIY Projects