PlatformIO Community

TFT with WeMos R32

Hey Gang,
This project would complete my smart home project. I’ve been kinda putting it off, but I finally jumped the Analog pins as described in this TFT library:

Of course, of course and of course of course, nothing is declared.
I only tried one example, and there were only two things in the first run of the build for the error list.

Would you please help me declare ‘header’ and ‘drawDatum’?

If it works, I’ll be able to display two sensor pods coming via ESP Now.

/*
  This example draws fonts (as used by the Adafruit_GFX library) onto the
  screen. These fonts are called the GFX Free Fonts (GFXFF) in this library.
  Other True Type fonts could be converted using the utility within the
  "fontconvert" folder inside the library. This converted has also been
  copied from the Adafruit_GFX library.
  Since these fonts are a recent addition Adafruit do not have a tutorial
  available yet on how to use the utility.   Linux users will no doubt
  figure it out!  In the meantime there are 48 font files to use in sizes
  from 9 point to 24 point, and in normal, bold, and italic or oblique
  styles.
  This example sketch uses both the print class and drawString() functions
  to plot text to the screen.
  Make sure LOAD_GFXFF is defined in the User_Setup.h file within the
  TFT_eSPI library folder.
  #########################################################################
  ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
  #########################################################################
*/

#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>

#include "Free_Fonts.h" // Include the header file attached to this sketch

TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height

unsigned long drawTime = 0;

void setup(void)
{

  tft.begin();

  tft.setRotation(1);
}

void loop()
{

  int xpos = 0;
  int ypos = 40;

  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // Select different fonts to draw on screen using the print class
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  tft.fillScreen(TFT_NAVY); // Clear screen to navy background

  header("Draw free fonts using print class");

  // For comaptibility with Adafruit_GFX library the text background is not plotted when using the print class
  // even if we specify it.
  tft.setTextColor(TFT_YELLOW, TFT_BLACK);
  tft.setCursor(xpos, ypos); // Set cursor near top left corner of screen

  tft.setTextFont(GLCD);           // Select the orginal small GLCD font by using NULL or GLCD
  tft.println();                   // Move cursor down a line
  tft.print("Original GLCD font"); // Print the font name onto the TFT screen
  tft.println();
  tft.println();

  tft.setFreeFont(FSB9); // Select Free Serif 9 point font, could use:
  // tft.setFreeFont(&FreeSerif9pt7b);
  tft.println(); // Free fonts plot with the baseline (imaginary line the letter A would sit on)
  // as the datum, so we must move the cursor down a line from the 0,0 position
  tft.print("Serif Bold 9pt"); // Print the font name onto the TFT screen

  tft.setFreeFont(FSB12);       // Select Free Serif 12 point font
  tft.println();                // Move cursor down a line
  tft.print("Serif Bold 12pt"); // Print the font name onto the TFT screen

  tft.setFreeFont(FSB18);       // Select Free Serif 12 point font
  tft.println();                // Move cursor down a line
  tft.print("Serif Bold 18pt"); // Print the font name onto the TFT screen

  tft.setFreeFont(FSB24);       // Select Free Serif 24 point font
  tft.println();                // Move cursor down a line
  tft.print("Serif Bold 24pt"); // Print the font name onto the TFT screen

  delay(4000);

  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // Now use drawString() so we can set background colours and the datum
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  tft.fillScreen(TFT_BLACK);

  header("Draw with background using drawString()");

  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  tft.setTextDatum(TC_DATUM); // Centre text on x,y position

  xpos = tft.width() / 2; // Half the screen width
  ypos = 50;

  tft.setFreeFont(FSB9);                               // Select the font
  tft.drawString("Serif Bold 9pt", xpos, ypos, GFXFF); // Draw the text string in the selected GFX free font
  ypos += tft.fontHeight(GFXFF);                       // Get the font height and move ypos down

  tft.setFreeFont(FSB12);
  tft.drawString("Serif Bold 12pt", xpos, ypos, GFXFF);
  ypos += tft.fontHeight(GFXFF);

  tft.setFreeFont(FSB18);
  tft.drawString("Serif Bold 18pt", xpos, ypos, GFXFF);
  ypos += tft.fontHeight(GFXFF);

  tft.setFreeFont(FSB24);
  tft.drawString("Serif Bold 24pt", xpos, ypos, GFXFF);
  ypos += tft.fontHeight(GFXFF);

  // Set text padding to 120 pixels wide area to over-write old values on screen
  tft.setTextPadding(120);
  for (int i = 0; i <= 20; i++)
  {
    tft.drawFloat(i / 10.0, 1, xpos, ypos, GFXFF);
    delay(200);
  }

  delay(4000);

  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // Same again but with colours that show bounding boxes
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  tft.fillScreen(TFT_DARKGREY);

  header("Show background filled bounding boxes");

  tft.setTextColor(TFT_YELLOW, TFT_BLACK);

  tft.setTextDatum(TC_DATUM); // Centre text on x,y position

  xpos = tft.width() / 2; // Half the screen width
  ypos = 50;

  tft.setFreeFont(FSB9);                               // Select the font
  tft.drawString("Serif Bold 9pt", xpos, ypos, GFXFF); // Draw the text string in the selected GFX free font
  ypos += tft.fontHeight(GFXFF);                       // Get the font height and move ypos down

  tft.setFreeFont(FSB12);
  tft.drawString("Serif Bold 12pt", xpos, ypos, GFXFF);
  ypos += tft.fontHeight(GFXFF);

  tft.setFreeFont(FSB18);
  tft.drawString("Serif Bold 18pt", xpos, ypos, GFXFF);
  ypos += tft.fontHeight(GFXFF);

  tft.setFreeFont(FSBI24);
  tft.drawString("Serif Bold Italic 24pt", xpos, ypos, GFXFF);
  ypos += tft.fontHeight(GFXFF);

  // Set text padding to 120 pixels wide area to over-write old values on screen
  tft.setTextPadding(120);
  for (int i = 0; i <= 20; i++)
  {
    tft.drawFloat(i / 10.0, 1, xpos, ypos, GFXFF);
    delay(200);
  }

  delay(4000);

  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // Now show setting the 12 datum positions works with free fonts
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  // Numbers, floats and strings can be drawn relative to a datum
  tft.fillScreen(TFT_BLACK);
  header("Draw text relative to a datum");

  tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
  tft.setFreeFont(FSS9);

  tft.setTextDatum(TL_DATUM);
  tft.drawString("[Top left}", 20, 60, GFXFF);
  drawDatum(20, 60);

  tft.setTextDatum(TC_DATUM);
  tft.drawString("[Top centre]", 240, 60, GFXFF);
  drawDatum(240, 60);

  tft.setTextDatum(TR_DATUM);
  tft.drawString("[Top right]", 460, 60, GFXFF);
  drawDatum(460, 60);

  tft.setTextDatum(ML_DATUM);
  tft.drawString("[Middle left]", 20, 140, GFXFF);
  drawDatum(20, 140);

  tft.setTextDatum(MC_DATUM);
  tft.drawString("[Middle centre]", 240, 140, GFXFF);
  drawDatum(240, 140);

  tft.setTextDatum(MR_DATUM);
  tft.drawString("[Middle right]", 460, 140, GFXFF);
  drawDatum(460, 140);

  tft.setTextDatum(BL_DATUM);
  tft.drawString("[Bottom Left]", 20, 220, GFXFF);
  drawDatum(20, 220);

  tft.setTextDatum(BC_DATUM);
  tft.drawString("[Bottom centre]", 240, 220, GFXFF);
  drawDatum(240, 220);

  tft.setTextDatum(BR_DATUM);
  tft.drawString("[Bottom right]", 460, 220, GFXFF);
  drawDatum(460, 220);

  tft.setTextDatum(L_BASELINE);
  tft.drawString("[Left baseline]", 20, 300, GFXFF);
  drawDatum(20, 300);

  tft.setTextDatum(C_BASELINE);
  tft.drawString("[Centre baseline]", 240, 300, GFXFF);
  drawDatum(240, 300);

  tft.setTextDatum(R_BASELINE);
  tft.drawString("[Right baseline]", 460, 300, GFXFF);
  drawDatum(460, 300);

  //while(1);
  delay(8000);
}

// Print the header for a display screen
void header(const char *string)
{
  tft.setTextSize(1);
  tft.setTextColor(TFT_MAGENTA, TFT_BLUE);
  tft.fillRect(0, 0, 480, 30, TFT_BLUE);
  tft.setTextDatum(TC_DATUM);
  tft.drawString(string, 239, 2, 4); // Font 4 for fast drawing with background
}

// Draw a + mark centred on x,y
void drawDatum(int x, int y)
{
  tft.drawLine(x - 5, y, x + 5, y, TFT_GREEN);
  tft.drawLine(x, y - 5, x, y + 5, TFT_GREEN);
}

// There follows a crude way of flagging that this example sketch needs fonts which
// have not been enbabled in the User_Setup.h file inside the TFT_HX8357 library.
//
// These lines produce errors during compile time if settings in User_Setup are not correct
//
// The error will be "does not name a type" but ignore this and read the text between ''
// it will indicate which font or feature needs to be enabled
//
// Either delete all the following lines if you do not want warnings, or change the lines
// to suit your sketch modifications.

#ifndef LOAD_GLCD
//ERROR_Please_enable_LOAD_GLCD_in_User_Setup
#endif

#ifndef LOAD_FONT2
//ERROR_Please_enable_LOAD_FONT2_in_User_Setup!
#endif

#ifndef LOAD_FONT4
//ERROR_Please_enable_LOAD_FONT4_in_User_Setup!
#endif

#ifndef LOAD_FONT6
//ERROR_Please_enable_LOAD_FONT6_in_User_Setup!
#endif

#ifndef LOAD_FONT7
//ERROR_Please_enable_LOAD_FONT7_in_User_Setup!
#endif

#ifndef LOAD_FONT8
//ERROR_Please_enable_LOAD_FONT8_in_User_Setup!
#endif

#ifndef LOAD_GFXFF
ERROR_Please_enable_LOAD_GFXFF_in_User_Setup !
#endif

If you have the implementation of a function before you and you want to know it’s declaration, just copy the content until the starting { and put a ; after it.

void header(const char *string);
void drawDatum(int x, int y);
1 Like

Thank you.

Okay. These are the first appearances of those two:

 header("Draw with background using drawString()");
 drawDatum(20, 60);

void header(const char *string);
void drawDatum(int x, int y);

I figured it was a void, but I had (and still have) no idea what do do between the parentheses.
And drawDatum is clearly an int, but that’s as far as I get.

Is there a cheat sheet somewhere for identifying data types and knowing what to put after the parenthesis?

Don’t try and read the function signature from a call to the function, but go directly to the implementation of it. There are caveats in this. From seing e.g. func(123); the function argument type could be long, int, short, char, unsigned int, unsigned short, unsigned char, float, double (since all can be implicitly converted). And the return type could be anything, it may just not have been used in that specific call, so not necessarily void.

That’s why the right place too look is

The function declaration or implementation is your cheat sheet.

Basic C++ data types are e.g. listed at https://www.tutorialspoint.com/cplusplus/cpp_data_types.htm.

Note that for integers, special suffixes are available, to e.g. make an integer literal of a specific type, like 10LLU makes it a long long unsigned instead of just an int.

Arguments can also be objects instantiated from some class and you have to look into the constructor of those to see how to construct them (or where to obtain them). Same for struct type arguments and their subfields.

Hang on- if it’s in the text, why does it need to be declared?
Aren’t we declaring it at line 243 ???

Anyway, there’s line in the library to uncomment with the product name, and I changed it and flashed it and nothing happens.
Just power- white screen.

Does this look like it should work?
The analog pins are input only, so three pins jump to neighboring pins.
I’m pretty sure I did that correctly.

This is not how C++ works. (This is how the Arduino IDE would work with its automatic forward declarations though).

C++ needs to know the signature of a function before it is being called. The program text is scanned progressively, so if you have

void setup() {
   myfunc();
}

void myfunc() { }

that’s an error, since at the point the call is done, the compiler has not yet seen the function definition (implementation). That’s why we have to put a function declaration (=just letting the compiler know what signature / types the functions involves) as in

 /* let compiler know about the existance of a function 
  * of this name and signature (return type and argument types if existant) 
  */
void myfunc();

void setup() {
   myfunc();
}

void myfunc() { }

Also see difference between declaration and definition and our docs.

For that we would need to see which exact TFT shield you’re using. Do you have a link where you bought it from?

With PlatformIO the library needs to be specially configured per https://github.com/Bodmer/TFT_eSPI/blob/master/Tools/PlatformIO/Configuring%20options.txt for the shield that is connected to the board, otherwise not much will happen.

https://aliexpress.ru/item/1005001585779587.html?spm=a2g0s.9042311.0.0.5d6733ed27fycx&_ga=2.165665023.1734491661.1610838273-836697976.1601761419&_gac=1.194450015.1610838274.Cj0KCQjwy8f6BRC7ARIsAPIXOjg8O30NGvbycG64PcQTH-7qBqMi3QFWlFBXhBM_UKi6-Yb5wtm5RlcaAkTyEALw_wcB

The TFT shield is IL19480

This is the Bodner change. He has a list of //#defined TFT products,

Accroding to the page and the pictures it’s a ILI9486. Said to be compatible with the UTFT library. The LCDWiki also knows about that display.

But eTFT seems to be able to handle this driver chip in its 8-bit parallel (not SPI) mode too, let me just look up some configuration values.

Well that library might have a problem in the way it writes to GPIO pins and how the shield sits on the board…

There are threads about this at https://github.com/Bodmer/TFT_eSPI/issues/167 (and referenced).

According to the board pinout and the LCD pinup in LCDWiki, I came up with the pin-assignment

[env:esp32_2]
platform = espressif32
board = esp32dev 
framework = arduino
lib_deps = 
    bodmer/TFT_eSPI @ ^2.3.58
build_flags = 
  -DUSER_SETUP_LOADED=1
  -DESP32_PARALLEL=1
  -DTFT_PARALLEL_8_BIT=1
  -DILI9486_DRIVER=1
  -DTFT_WIDTH=320
  -DTFT_HEIGHT=480
  -DTFT_RST=4
  -DTFT_CS=15
  -DTFT_RS=33
  -DTFT_WR=32
  -DTFT_RD=39
  -DTFT_D0=12
  -DTFT_D1=13
  -DTFT_D2=26
  -DTFT_D3=25
  -DTFT_D4=17
  -DTFT_D5=16
  -DTFT_D6=27
  -DTFT_D7=14
  -DLOAD_GLCD=1
  -DSMOOTH_FONT

please doubel check that.

However, the library has a problem in the specific ESP32 case and pin numbers beyond and equal to 32, because it tries to create then a longer-than-32-bit bitmask for a 32bit value, when it should be using another register.

Also there’s an actual compilation error in the library when using a certain pin number.

And by design the WR pin and D0…D7 have to be accessible in the same GPIO register, which is not the case with this display in board, so it fails (https://github.com/Bodmer/TFT_eSPI/issues/940). So this library doesn’t seem suitable for it.

I’ll have another look at this tomorrow, someone’s gotta have a library for an 8-bit parallel ILI9486 display that works on an ESP32.

…Actually when I look a second time at the pinmaping I read the analog side pins probably and that library should be usable, even if not modified.

Still, can you sanity check the pinmapping described in https://github.com/maxgerhardt/pio-wemos-d1-r32-ili9486-display and the PlatformIO project enclosed in it?

I think all the pins are correct. I went through them before I wired the analog pins to the neighbors. The digital pins should work as-is.
I have a few more of these R32 units coming in a few weeks to use the analog pins in environmental sensor pods. So I can destroy this one. Rather not. I like the R32.

I absolutely love your .cpp file. I wish every example simply showed how to execute, display, etc. I spend too much time trying to figure out what the horrible names mean, give up, and quit looking at the src files because the author is a poopyhead for failing to use language.

But yours doesn’t work either. I just tore apart my wiring, and it was right. I get nothing on the display.

The earlier 0 was a 6, I just didn’t look at my note carefully.

I’ve only gotten the TFT to work with the Mega side of the RobotDyn Mega 8266. I think it was the MCUFriend library.

Thanks for reminding me of UTFT.

There’s another, Ug… ?

Hm sadly the firmware / library doesn’t output much to help to get to the bottom of this. Everything must work right in order for this to work, one error and no output.

But, I do have that display by tomorrow and I can just wire up my ESP32 with the same pinmapping and firmware and see why this doesn’t work.

The https://github.com/prenticedavid/MCUFRIEND_kbv looks very Uno/Mega specific to me with the direct register access, I don’t think that’s compatible with the ESP32. UTFT might have a better chance though. I’ll have a look soon anyways.

If you are using the UNO style ESP32 with an UNO style TFT shield and have performed the wiring change here. Then the correct pin mapping can be found in the Setup14 file, reproduced here for convenience:

#define TFT_CS   33  // Chip select control pin
#define TFT_DC   15  // Data Command control pin - must use a pin in the range 0-31
#define TFT_RST  32  // Reset pin

#define TFT_WR    4  // Write strobe control pin - must use a pin in the range 0-31
#define TFT_RD    2

#define TFT_D0   12  // Must use pins in the range 0-31 for the data bus
#define TFT_D1   13  // so a single register write sets/clears all bits
#define TFT_D2   26
#define TFT_D3   25
#define TFT_D4   17
#define TFT_D5   16
#define TFT_D6   27
#define TFT_D7   14
2 Likes

This almost seems like the right file, but the seller page states it has an ILI9486 instead of the

so I kept that in the config. I’ve corrected the DC/RS error too in the repo https://github.com/maxgerhardt/pio-wemos-d1-r32-ili9486-display. So @Monsterthews can give it another try? I’ll also try it when I have my display…

That makes perfect sense, since it was a Mega chip. I didn’t use the 8266 for the MCUFriend library.
But the Mega did the TFT successfully.
Unfortunately, I can’t squirt the ESP Now into it.
I don’t have any modules, just the 32 and 8266 development boards.

Good morning!
I get this error:

“No instance of overloaded function “TFT_eSPI::setTextColor” matches he argument list – argument types are (int, int) – object type is: TFT_eSPI C/C++(304) [19,7]”