set a font in arduino ide for tft display quotation
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:
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.
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)
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.
TFT_ILI9341 library updated on 1st July 2015 to version 12, this latest version is attached here to step 8:Minor bug when rendering letter "T" in font 4 without background fixed
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.
This example demonstrates how to draw text on the Arduino GLCD screen when connected to an Arduino. The Arduino reads the value of an analog sensor attached to pin A0, and writes the value to the LCD screen, updating every quarter second.
Connect the screen to the breadboard. The headers on the side of the screen with the small blue tab and arrow should be the ones that attach to the board. Pay attention to the orientation of the screen, in these images, it is upside down.
Connect the BL and +5V pins to power, and GND to ground. Connect CS-LD to pin 10, DC to pin 9, RESET to pin 8, MOSI to pin 11, and SCK to pin 13. If you"re using a Leonardo, you"ll be using different pins. see the getting started page for more details.
Define the pins you"re going to use for controlling the screen, and create an instance of the TFT library named TFTscreen. You"ll reference that object whenever you"re working with the screen.
In setup(), initialize the screen and clear the background. Set the color for the font with stroke(), and write any static text to the screen. In this case, you"ll write "Sensor Value :". This will stay at the top of the screen and not change as long as the sketch runs. Before entering the loop(), set the text size so you can really see the sensor values stand out.
In loop(), read the value from the potentiometer and store it in a string. Convert the string content to a char array, storing it in the global array you declared int he beginning of your program.
Set the text color (this would be a good place to change the color of the text depending on the value from the potentiometer), and print it to the screen below the static text.
I am using a 3.5: TFT LCD display with an Arduino Uno and the library from the manufacturer, the KeDei TFT library. The library came with a bitmap font table that is huge for the small amount of memory of an Arduino Uno so I"ve been looking for alternatives.
What I am running into is that there doesn"t seem to be a standard representation and some of the bitmap font tables I"ve found work fine and others display as strange doodles and marks or they display upside down or they display with letters flipped. After writing a simple application to display some of the characters, I finally realized that different bitmaps use different character orientations.
What are the rules or standards or expected representations for the bit data for bitmap fonts? Why do there seem to be several different text character orientations used with bitmap fonts?
Are these due to different target devices such as a Windows display driver or a Linux display driver versus a bare metal Arduino TFT LCD display driver?
What is the criteria used to determine a particular bitmap font representation as a series of unsigned char values? Are different types of raster devices such as a TFT LCD display and its controller have a different sequence of bits when drawing on the display surface by setting pixel colors?
Is there some method other than the approach I"m using to determine what transformation is needed? I currently plug the bitmap font table into a test program and print out a set of characters to see how it looks and then fine tune the transformation by testing with the Arduino and the TFT LCD screen.
I"m not fully conversant with the standard descriptions of bitmap fonts however I think of this as being an 8x16 bitmap font in which each character is 8 pixels wide and 16 pixels in height or an 8x16 bitmap font.
With the size of this table and the small amount of memory on the Arduino Uno, I started hunting for other bitmap fonts that would be legible while also taking up less memory. See reducing memory required for KeDei TFT library used with 3.5" TFT display with Arduino
What I hoped to find was something around a 6x6 bitmap font so that the definition of the bitmap font table would change from const unsigned char font_table_16_col[96][16] = { to const unsigned char font_table_16_col[96][6] = { which would free up a significant amount of memory. And experiments with cutting the table down by removing lower case letters showed that helped as well.
Finding alternative bitmap fonts has been more difficult than I thought, envisioning someone with the motherlode of bitmap fonts in a GitHub repository somewhere, easily found with a search or two.
What I have run into is that while I have found several different examples of bitmap fonts not all seem to be compatible with my specific 3.5" TFT LCD display.
For instance here are representations of four different bitmap fonts showing the bits of the bitmaps for two characters, the exclamation point (!) and the double quote ("). The 5x8 seems to be rotated to the clockwise by 90 degrees. The 8x8 and the 16x8 seem to be oriented correctly and the 13x8 seems to be upside down.
The bitmap font representations in the image above, showing the differences in text character orientation, were generated by a simple Windows GUI and displayed with a dash (-) representing a bit value of zero and an asterisk (*) representing a bit value of 1. This is the output of a Microsoft Windows GUI application whose WM_PAINT message handler which draws the displayed image is as follows:
I have modified the code that displays text using the bitmap fonts so that for a particular bit map the character drawing logic will perform several different kinds of translations between the bitmap font representation as a series of hexadecimal digits and how the series of digits are used to determine which pixels to turn on and which to turn off.
The code for drawing a single line of a character is as follows. The outline of this function is to provide to the LCD controller a rectangle specifying the region of the display to be modified followed by a series of two 8 bit writes to set the two byte RGB565 color value of each of the pixels in the region.
static bool TFTLCD::draw_glyph(unsigned short x0, unsigned short y0, TftColor fg_color, TftColor bg_color, unsigned char bitMap, unsigned char bmWidth, unsigned char flags)
and the source code that uses the above function for drawing a complete characters is as follows. This code uses the drawGlyph() function to draw a series of slices of the text character from top to bottom. When a bitmap transformation is done depends on the bitmap representation.
TFTLCD::draw_glyph(Font::now_x, Font::now_y, Font::font_color, Font::txt_backcolor, Font::font_table.table[char_i_x + char_m], Font::font_table.nCols, glyphFlags);
TFTLCD::draw_glyph(Font::now_x, Font::now_y, Font::font_color, Font::txt_backcolor, Font::font_table.table[char_i_x + char_m], Font::font_table.nCols, glyphFlags);
TFTLCD::draw_glyph(Font::now_x, Font::now_y, Font::font_color, Font::txt_backcolor, Font::font_table.table[char_i_x + char_m], Font::font_table.nCols, glyphFlags);
TFTLCD::draw_glyph(Font::now_x, Font::now_y, Font::font_color, Font::txt_backcolor, Font::font_table.table[char_i_x + char_m], Font::font_table.nCols, glyphFlags);
TFTLCD::draw_glyph(Font::now_x, Font::now_y, Font::font_color, Font::txt_backcolor, Font::font_table.table[char_i_x + char_m], Font::font_table.nCols, glyphFlags);
TFTLCD::draw_glyph(Font::now_x, Font::now_y, Font::font_color, Font::txt_backcolor, Font::font_table.table[char_i_x + char_m], Font::font_table.nCols, glyphFlags);
There are a number of font specifications including rasterized bitmap type fonts. These specifications do not necessarily describe the glyph bitmaps used in application such as the KeDei TFT library but rather provide a device independent description of a bitmap font format.
Oracle in Solarix X Window System Developer"s Guide, Chapter 4 Font Support at https://docs.oracle.com/cd/E19253-01/816-0279/6m6pd1cvk/index.html has a table listing several different bitmap font formats and has this to say:
Hi guys, over the past few tutorials, we have been discussing TFT displays, how to connect and use them in Arduino projects, especially the 1.8″ Colored TFT display. In a similar way, we will look at how to use the 1.44″ TFT Display (ILI9163C) with the Arduino.
The ILI9163C based 1.44″ colored TFT Display, is a SPI protocol based display with a resolution of 128 x 128 pixels. It’s capable of displaying up to 262,000 different colors. The module can be said to be a sibling to the 1.8″ TFT display, except for the fact that it is much faster and has a better, overall cost to performance ratio when compared with the 1.8″ TFT display. Some of the features of the display are listed below;
TheTFT Display, as earlier stated, communicates with the microcontroller over SPI, thus to use it, we need to connect it to the SPI pins of the Arduino as shown in the schematics below.
Please note that the version of the display used for this tutorial is not available on fritzing which is the software used for the schematics, so follow the pin connection list below to further understand how each pin of the TFT display should be connected to the Arduino.
When connecting the display, ensure that has a voltage regulator (shown in the image below) before connecting it directly to the 5v logic level of the Arduino. This is because the display could be destroyed if the version of the display you have does not have the regulator.
In order to allow the Arduino to work with the display, we need two Arduino libraries; the sumotoy TFT ILI9163C Arduino library which can be downloaded from this link and the popular Adafruit GFX Arduino library which we have used extensively in several tutorials. Download these libraries and install them in the Arduino IDE.
For today’s tutorial, we will be using the bigtest example which is one of the example codes that comes with the sumotoy ILI9163C Arduino library to show how to use the TFT display.
The example can be opened by going to File–>Examples–>TFT_ILI9163c–>bigtest as shown in the image below. It should be noted that this will only be available after the sumotoy library has been installed.
Next, we define some of the colors that will be used along with the corresponding hex values. If you’ve gone through any of our previous tutorials where we used the Adafruit GFX library, you would have noticed that this code contains a lot from the GFX library and it should be easier for you to follow.
Next, an object of the ILI9163c library named “display” was created with CS and DC parameter as inputs but due to the kind of display being used, we need to include the pin of the Arduino to which the A0 pin of the TFT display is connected which is D8.
With this done, we move to the void setup() function. Under this function, we issue the commands that initialize the display then create a time variable updated by millis, after which we issue a command to clear the screen and display some random text on it.
Some of the functions which perform actions ranging from displaying fastlines, drawing rectangles etc are then called with a delay after each function so the text or graphics stays long enough on the screen to be visible.
Up next is the void loop function. The void loop function also calls some of the same functions called under the void setup() function to display circles, rectangles etc including the testline function which is essentially used to test the screen.
With the libraries installed, open an instance of the Arduino IDE, open the examples as described initially, don’t forget to make the A0 pin (D8) correction to the code then upload to the Arduino board. You should see different kind of text and graphics being displayed on the screen. I captured the screen in action and its shown in the image below.
That’s it for this tutorial guys, what interesting thing are you going to build with this display? Let’s get the conversation started. Feel free to reach me via the comment section if you have any questions about the tutorial.
This project is created byDIYODE Magazineand is originally published onDIYODE Magazinewhere they also did an informative review on Seeed Studio"s Wio Terminal. I personally love this project and decided to share it here on Hackster. Please do note the following documentation is written byDIYODE Magazine Team.
For our first project, we’re using both the inbuilt LCD screen and WiFi module to get text data of famous quotes. Since we’re all nerds at DIYODE, we’ve of course chosen to choose famous programming quotes. The center button of the Wio Terminal will be used to load a new quote and display it on the screen.
WiFi is involved here because we’re using a simple Web API to gather data and display it live. Since it’s connecting to WiFi, we could connect it with virtually any other web interface and make it work.
If you’re new to programming, this code may appear daunting, but it’s really just our Wio Terminal pretending to be a computer sending a web request and reading the response. An API is just an ‘application programming interface’ and is a fancy way of saying it’ll be the source of our data.
After installing the required WiFi libraries, we can open a new Arduino sketch and pop in the following initialization code. Unless your WiFi network so happens to be named “YOUR_WIFI_NAME” and has the password “YOUR_WIFI_PASSWORD”, you’ll want to change them to your home network details!
There isn’t a ton of libraries we need to import here. We’re using the Arduino JSON, rpcWiFi and HTTPClient libraries to handle the internet connection and data, and the TFT_eSPI library to handle the screen on the Wio Terminal.
The ‘wasPressed’ variable will be used during the main loop to ensure we only display one new quote when the button is pressed, and not to continue looking for quotes when the button is held. This is typically referred to as state detection, and we’ll talk about this shortly.void setup() {
Our setup code is verbose but should be fairly self-explanatory as we read through it. We’re starting the TFT screen and setting its rotation, background settings and a placeholder text while we wait for a connection to the WiFi.
To make the WiFi and networking features work, you’ll need to reflash the WiFi firmware on the Wio Terminal. The official Seeed guide can be found here:https://wiki.seeedstudio.com/Wio-Terminal-Wi-Fi/
It’s not as difficult as it sounds, and it only took us 10 minutes. If you’re wondering why the WiFi isn’t working on your Wio Terminal, there’s a good chance that this will fix the problem.
Also notice that there is a considerable number of calls to the Serial command, which essentially allows us to debug and inspect the functionality of the Wio Terminal by opening the Serial Monitor (Shortcut – Ctrl+Shift+M).void loop() {
This is where the real heavy lifting happens! In our loop function, we’re using that ‘wasPressed’ variable mentioned before to respond only when the button is pressed, and not continuously held.
The getQuoteResponse() function is where the request actually happens, which consists of opening our URL (feel free to visit the URL shown, it will show a random programming quote in your browser), and loading it from a JSON format. We won’t go into JSON formats and the specifics of it in this project, but essentially its a field and value-based system where attributes are given names. Our response usually comes in this format:{"id":"5a6ce86f2af929789500e824","author":"Ken Thompson","en":"One of my most productive days was throwing away 1,000 lines of code."}
In this case, if we refer to the field “author”, it’s value is “Ken Thompson”. That’s why in our code, we can refer to fields to get their values.int len = 23;
Finally, we can actually draw the quote text on the Wio Terminal’s screen! This isn’t that tricky, except for that weird for loop with the numbers in it. The purpose of this is to provide some basic text wrapping.
Text wrapping is the process of bringing text fields down to the next line on the screen if it’s too long – which is often the case with quotes. The LCD library does have this function built-in, but it wasn’t cooperating for us, so we wrote it ourselves!
Essentially, we’re taking ‘chunks’ out of the text with the substring function and writing each to one line of the Wio Terminal’s LCD screen. The ‘len’ variable describes the number of characters on each line. If the function is confusing, just change some values and observe the effects!
We’re all done! Now just hit the upload button, ensuring that the Wio Terminal is switched on. After a couple of seconds of letting it connect to our WiFi…
…and boom! It’s all working. Inspiring programming quotes at the press of a button. Obviously, this isn’t the most practical program ever – but it’s a good starting program to experiment with the Wio Terminal and to demonstrate its capabilities with precisely zero external wiring required.
Why, we updated them slightly to allow us to include them in several of the display drivers that we setup to handle these fonts, like the st7735/90 ILI9488, RA8875/76...
We also converted it to be a newer Arduino library (moved things to SRC directory), plus set it up to generate an archive. Why this is nice is that when you build with it, it will only include those files (fonts) that your code actually references, otherwise it will try to link in all of the font files in that directory.
In part 1 of this two part series I presented the hardware design and build for the Nokia 6300 TFT that shows how we can connect it directly to the external memory interface of the Arduino Mega and that by doing so we achieve the fastest possible interface between the TFT and the Arduino MCU.
Now the driver software has been updated to support the 2.4″ Nokia N82 LCD that I have reverse engineered. Everything that you can do on the 6300 screen, you can now also do on the N82.
A TFT with the fastest transfer times possible on an Arduino deserves a software library to do it justice, and that’s what I hope to provide here. The software library provides the following functionality:
The library is implemented as a set of C++ templates. This design decision was taken to maximise the performance of the library as much as possible by isolating the choices that you make at design-time, such as the colour depth and orientation of the LCD and making those compile-time template parameters. This means that entire swathes of code simply do not get compiled making your program as fast and as small as it can be.
Note that the code for the design-time decision regarding the LCD orientation is there at runtime even though it’s completely redundant. Contrast this with the template library which might have two function specialisations that look like this:
When the code is compiled the template specialisation for the orientation that you are not using simply never happens and the optimiser is presented with a trivial function that returns a constant. This is certain to be inlined by the optimiser meaning that the entire function call never happens at all! This design pattern is prevalent throughout my entire library.
Anyway, you can forget the theory and there’s no need to be nervous about the sometimes obscure syntax that comes with templates because I take care of all that and expose only a very small number of simple types that you interact with.
All of these examples are based around the popular and easy to use Arduino prototyping IDE. Advanced users will find that the library works just as well outside the IDE. My own development environment consists of avr-gcc 4.7.0, Eclipse Indigo and avr-libc 1.8.0 so compatibility with the most advanced toolchain to date is assured.
Download the library zip file from my downloads page and unzip it into your Arduino libraries directory. For me, that directory is C:\Program Files (x86)\arduino-1.0.1\libraries. Adjust that pathname to reflect where you installed the Arduino IDE on your computer.
When you’re finished you should have a new xmemtft directory in the Arduino libraries directory. All of the demos presented below can be accessed under the Arduino File -> Examples -> xmemtft menu.
All you need to do is uncomment the typedef line that corresponds to how you want to use the TFT in your project. Select a colour depth and orientation and you’re good to go. The class constructor for the panel object will take care of powering up the device and sending the initialisation sequence.
The entire library is contained within a namespace called lcd. For code-clarity all these examples will import lcd into the global namespace with a using namespace lcd statement. Advanced users will know the reasons why they don’t want to do this in a real project.
In the above example we show how to initialise the TFT and switch on the backlight. When the TFT is being initialised it contains random data. This is ugly for the user to see so we begin by ensuring that the backlight is off which makes the data on the panel invisible. We then initialise the TFT, clear down the display to a solid colour (black in this case) and then fade up the backlight smoothly.
This is the line that creates the backlight and initialises it to zero brightness (off). The brightness is expressed as a percentage in the range 0..100. You must connect PWM pin #2 to the EN pin on the board. You can change both the PWM pin number and the default starting brightness percentage by changing how you declare and construct the Backlight class. See the source code for details.
Note the use of the ColourNames namespace. Take a look at ColourNames.h to see the full set of available names. The names correspond to the X11 colours.
Rectangles can be drawn as an outline in the foreground colour or filled with either the background or foreground colour. Here’s an example that shows all of that.
To keep the code samples concise and focused on the example I’m going to show only the loop() function. You can take the above example code that demonstrates the backlight initialisation and just paste in the code for loop().
Unfortunately TFTs photograph and film very badly indeed. I’ll try my best but the images and videos on this page are not representative of the actual picture quality that your eye perceives. Bands and pattern effects seen in the photographs are not present on the actual screen and the colours are a lot more vivid – the rectangle that appears cyan in the picture below is actually a deep solid blue.
See how easy it is to draw on to the display? The graphics library remembers two colours, a foreground and a background colour. Most operations will use the foreground colour but some, such as clearRectangle will use the background colour.
The Rectangle object is used to define the co-ordinates of the rectangle on the display. For clarity I’ve shown explicit initialisation of the members but there are constructors that allow you to initialise the members in various different ways.
The graphics library contains a linear gradient fill algorithm of my own design. This can be used to fill a rectangle with a gradient calculated from a starting and ending colour and a horizontal or vertical direction.
It’s unfortunate that I have to pass the direction as a boolean to the doGradientFills function but there is a bug in the Arduino IDE that prevents an enum value being passed to a function in your sketch.
Ideally I would have liked to have provided the gradient fill functions as template specialisations for horizontal and vertical but due to a limitation in the C++ standard around specialisation of template members of template classes I can’t do it without some ugly hacking.
Perhaps of interest here is the type name used for holding colour variables. TftPanel::TColour. It actually resolves down to uint32_t which you can use instead if you like. The type name is for portability if and when I use this library to control other TFTs.
Freely useable in non-commercial applications as long as credits to Po-Han Lin and link to http://www.edepot.com is provided in source code and can been seen in compiled executable. Commercial applications please inquire about licensing the algorithms.
An ellipse is defined by the position of the center of the shape and the two X and Y radii. A circle is just a special case of an ellipse so this is the method you should use to draw or fill circles.
The graphics library supports fixed-width and proportional bitmap fonts (the former being merely a special case of the latter). TrueType Fonts can be downloaded from the bitmap fonts section of DaFont and converted to a C++ header file that you can include in your code.
Let’s start with an example that shows a text string being repeatedly displayed at various positions on the screen. I’ll show the whole sketch this time because there are additions to the includes and to the initialisation.
We need to add an include for each font header file that you want to use. Uncomment one of the #include lines and put it at the top of your sketch with the other #include directives.
In the setup() function we construct the font class that we’re going to use. The obscure looking name of the class is auto-generated by the font conversion utility and can be found by looking in the header file.
This demonstration uses the stream operator << to control text output. These operators are much more convenient than calling the writeString and measureString member functions directly because you can chain together multiple operations in one line.
The stream operators can take a font object to change the font that will be used next, a point object to change where the next output will be and of course a string, character, integer or floating point number to write. The current output location is automatically updated in the X direction so you can write out multiple strings and have them tacked on end-to-end.
The default precision for floating point numbers (double’s) is 5 decimal places. If you want to override that you can do so like this example where I show PI to 3 decimal places:
There is a double-to-string conversion in the arduino standard libraries but this version is 17% faster at the expense of 40 bytes of SRAM for an internal lookup table. For the curious, the implementation is a port of this open source library.
Only the pixel/bitmap fonts are compatible. The vector fonts require a sophisticated anti-aliasing engine to make them look as great as they do, and typically they include special algorithms that help them to maintain their looks at small font sizes.
Find a font you like and obtain the .ttf file for it. Save this to somewhere permanent on your system because the font conversion utility saves a reference to the pathname so it can read the font back later on.
Select the characters you want to include when you save it. Don’t include characters you don’t use – in an embedded system that’s just a waste of memory. I have included Select all 7-bit and Select all alphanumeric buttons to help you select the most common characters.
If the characters are not centered in their boxes or the boxes are not wide enough then adjust the Extra Lines and Offset parameters until it looks right.
If the characters are tight up against the edges of their boxes (like in the screenshot above) then add on a pixel or two of Character spacing so that the characters will appear spaced apart on screen. There is no preview for this option.
Select the Arduino target button and click Save. The adjustments that you have made are saved in an XML file and the font source code in a header file. For example, enter MyFont as the name to save and you will get MyFont.h and MyFont.xml on disk.
If, in the future you need to make adjustments to the saved font then use the Load option and browse for the XML file that you saved in the above instructions.
The graphics library supports bitmap graphics compiled into SRAM or flash, compressed or uncompressed. A utility is provided to convert almost any popular format to an internal format that you can include directly into your project.
Bitmaps have to be converted from the efficient file storage format such as PNG, JPEG etc. to an internal format for optimised for transferring quickly from memory to the display. A Windows command-line utility is provided for this purpose, called bm2rgbi.exe. You can find it in the xmemtft/utility/bm2rgbi sub-directory of your Arduino libraries folder. The syntax is as follows:
Uncompressed bitmaps are good for small icons and are the fastest to display. Even simple animation is possible with these and I will demonstrate that in this example code. The drawback is the amount of flash memory required to store the bitmap.
The pixels are stored in flash and we need to know where they are and how much memory they occupy. These two extern references will resolve to those values. We’ll see later how we get the pixels compiled into your program.
Before we can display a bitmap we need to set up a structure that tells the library about it. The structure needs to receive the pixel width and height and the external references that we declared before. The GET_FAR_ADDRESS macro is a very useful hack that allows us to reference 24-bit addresses in flash. It’s required because AVR pointers are normally 16-bits wide and without this we would never be able to reference data above 64K in flash… kind of pointless when we’ve got 128K or 256K to play with.
This is where we draw the bitmap. The method takes a Point structure telling it where to display the bitmap and a reference to the bitmap structure itself that we prepared above.
Now we need to explain how we include that .bin converted bitmap in your compiled program. There are a couple of ways to do this and I’ve selected a method that means you don’t have to hardcode the start address and it should work with any size of bitmap limited only by your flash memory size, and it doesn’t matter if it ends up above the 64K memory boundary.
In the Arduino IDE I include this hack in a separate tab. What it’s doing is using the GNU assembler .incbin directive to include arbitrary binary into your program. Two symbols are declared (GlobePixels and GlobePixelsSize) and made global so that the C++ code can see them. Wrapping it all in a function that will never be called (_asmStub) ensures that it ends up in flash with your code. Don’t ever call this function because the MCU will try to execute your binary picture as program code!
Large bitmaps cost memory. An uncompressed QVGA bitmap would occupy 320 x 240 x 3 = 230400 bytes. Far too much for our little MCU. Thankfully we support compression of bitmaps using the tiny liblzg codec. The level of compression is almost identical to PNG – that’s very good indeed and easily suitable for full-screen bitmaps.
There is a cost to using the LZG compression. The authors claim that the algorithm does not require any memory during decompression but this is only true if it’s set up to decompress to RAM because the algorithm needs random access to a preceding ‘window’ of bytes from the decompressed stream, the size of which is determined by the level of compression that was selected.
I have taken steps to limit the size of the compression window to 2Kb and implemented it as a ring buffer in the decompressor. Therefore the algorithm requires 2Kb of stack space to run which is de-allocated when it’s completed.
In this next example we will really showcase how our little Arduino can play with the big boys by simulating a media player interface complete with a live 16 channel ‘graphic equaliser’ that displays the amplitudes of the frequency ranges in an input signal calculated in real-time by the Fast Fourier Transform (FFT).
Most of the example code is dedicated to the program logic. I’ve highlighted the lines where we use bitmaps. A compressed bitmap is used for the media player interface because without compression it would be about 190Kb. With LZG compression it’s a mere 32Kb.
As before, the raw bitmaps are included into the program code using some inline assembler like this example. Adjust the filenames of the .bin files to match your system.
The author of picojpeg has gone to great lengths to limit SRAM memory use but it will still cost you about 2.5Kb to call the JPEG decoder. The original version of the library would take that 2.5Kb as global variables which meant that you pay the memory cost for the lifetime of your program, even when you’re not actually decoding a JPEG.
I have modified picojpeg so that all but about 200 bytes of that memory comes off the stack and is only consumed whilst a JPEG is being decoded. Another key limitation is that progressive JPEGs are not supported.
We can display JPEG images that are compiled into flash memory. My sample images take up about 15Kb each at full-screen (240×320) and 70% quality. Here’s an abbreviated sample that shows the technique:
drawJpeg is the key function. It takes a point location on the screen of where to draw the jpeg and a reference to the data-source object that tells the drawing function where the jpeg data is, and how much of it there is.
As in all the previous bitmap examples the pixel data is included directly into flash using a little assembly language file. You can see the entire demo code in the driver zip file.
I have included driver support for displaying JPEG images streamed over the serial port from a connected computer. This frees your application from the memory limitations of the Arduino Mega and opens up the possibility of creating applications such as digital photo frames to showcase your portfolio to unsuspecting family and friends.
Serial support is a little more involved than flash support because we have to marshal the data between the two ends of the wire, ensuring that both ends stay in sync with each other. Here’s a sample application in its entirety:
The key points are that you first initialise the serial link with the desired board rate, then you must initialise a JpegSerialDataSource with the serial object, the size of the data that you are going to transmit, and the size of each chunk of data to receive before sending back a ‘you may continue’ flow-control byte to the sender.
This last number, the chunk size, is important. The Arduino Mega library can, by default, receive 63 bytes before its internal buffer overflows. Therefore the ideal chunk size is 63, and that’s what we’ll use.
How you get the jpeg data size is up to you. In my demo I choose to transmit the size as a 32-bit number ahead of the data itself and you can see in readJpegSize that I just receive those bytes directly on to a uint32_t and return it.
Now for the other end. I created a small C# command line utility to do the work of sending the jpeg over the serial port. In my demo code I use the Arduino’s built in USB connection, the same one you use to flash your programs.
The serial port support is not limited to actual serial ports. It should work with any peripheral that has a driver that derives from the Arduino Stream class.
Let’s see a video of the serial jpeg link in action. Naturally this mode of operation is not as fast as when the data is compiled into flash because the little Arduino has to devote some time to receiving data over the wire.
The Nokia 6300 supports hardware scrolling. Well, they call it hardware scrolling but no pixel moving takes place. It’s actually simulated scrolling by offsetting the rows by a user-defined amount.
For example, a scroll amount of 1 means that row zero is actually output one row down and so on until you get to the last row that is wrapped around and will appear at the top where row zero usually is.
Hardware scrolling is officially supported in portrait mode but the current batch of screens that I’ve tested also support it in landscape mode where the scroll direction comes out as horizontal.
The TFT supports a sleep mode in which the display and much of the controller circuitry is powered down, reducing the current usage to a few microamps. The backlight should also be switched off in sleep mode since it’s the biggest current drain.
I have provided a high level class that builds on the primitives provided by the graphics library to implement a character terminal that you can use to output strings to.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aenean nec arcu ac lorem pulvinar pretium. Etiam at ultricies est.nn
Nunc nisl justo, ullamcorper vitae laoreet sit amet, tristique id est. Nulla imperdiet, massa et tincidunt ultricies, quam magna blandit nulla, vel aliquam tellus ipsum nec erat.nn
Suspendisse dignissim consectetur iaculis. Morbi vel felis quis nibh placerat porttitor eu dignissim mauris. Nunc posuere tincidunt felis elementum molestie.nn
Maecenas eget justo nunc. Aliquam erat volutpat. Ut pulvinar, massa id adipiscing blandit, ligula purus rhoncus ante, sed scelerisque tortor magna gravida libero.nn
Curabitur eget neque nec ante porttitor ornare. Morbi congue fermentum pellentesque. Suspendisse nisi tellus, suscipit sed congue ac, accumsan ac quam.nn
Nullam ullamcorper purus vitae diam vestibulum ultrices. Nullam vel libero ut justo imperdiet lobortis. Nullam sed lorem vitae nulla mattis faucibus.nn
Here is where we declare the implementation of the terminal that we will use. It must match the orientation and colour depth of the TFT class. The font that you use must be fixed width.
Here the demo simulates a percentage counter from 0 to 100. This is intended to show how the clearLine() method can be used to repeatedly show a changing status line.
This part of the demo ‘types’ out some paragraphs from the lorem ipsum text that will be familiar to designers the world over. When the text hits the bottom of the screen it will be hardware-scrolled to make room for the next line.
Temporarily sold out! Some more boards are supposedly on the way to me so if you’re interested then please use my contact page to let me know and I’ll drop you a no-obligation email when they’re ready.
I have noted that not all boards obtained on ebay are the same. To my surprise there are slight differences in the behaviour, nothing radical but enough for me to justify a new release of the software driver to deal with this ‘type B’ model. I will refer to the original model as ‘type A’.
The hardware scrolling offset is reversed. Type ‘A’ boards scroll up one line with an offset of 319. These type ‘B’ boards will scroll up one line with an offset of 1.
Type ‘B’ boards support the faster 64K driver. Type ‘A’ boards do not. The raw fill rate for the 64K colour mode is 1.32 megapixels/second. It is 1.06 megapixels/second for the 262K and 16M modes on both boards.
The new line of 3.5” TFT displays with IPS technology is now available! Three touchscreen options are available: capacitive, resistive, or without a touchscreen.
I noticed that the TomThumb.h font included in the Adafruit GFX library has characters that have different widths, which is a problem for me because I"m doing text processing that requires characters to have the same dimensions (width and height). I also noticed that the TomThumb.h font misses some characters (such as ") and so on. I need a way to create/edit fonts for the Adafruit GFX (where I"m using the Adafruit_ST7735 on a 1.8" TFT Display). I"ve looked around the internet but I couldn"t find anything decent.
In this Arduino touch screen tutorial we will learn how to use TFT LCD Touch Screen with Arduino. You can watch the following video or read the written tutorial below.
For this tutorial I composed three examples. The first example is distance measurement using ultrasonic sensor. The output from the sensor, or the distance is printed on the screen and using the touch screen we can select the units, either centimeters or inches.
The next example is controlling an RGB LED using these three RGB sliders. For example if we start to slide the blue slider, the LED will light up in blue and increase the light as we would go to the maximum value. So the sliders can move from 0 to 255 and with their combination we can set any color to the RGB LED, but just keep in mind that the LED cannot represent the colors that much accurate.
The third example is a game. Actually it’s a replica of the popular Flappy Bird game for smartphones. We can play the game using the push button or even using the touch screen itself.
As an example I am using a 3.2” TFT Touch Screen in a combination with a TFT LCD Arduino Mega Shield. We need a shield because the TFT Touch screen works at 3.3V and the Arduino Mega outputs are 5 V. For the first example I have the HC-SR04 ultrasonic sensor, then for the second example an RGB LED with three resistors and a push button for the game example. Also I had to make a custom made pin header like this, by soldering pin headers and bend on of them so I could insert them in between the Arduino Board and the TFT Shield.
Here’s the circuit schematic. We will use the GND pin, the digital pins from 8 to 13, as well as the pin number 14. As the 5V pins are already used by the TFT Screen I will use the pin number 13 as VCC, by setting it right away high in the setup section of code.
As the code is a bit longer and for better understanding I will post the source code of the program in sections with description for each section. And at the end of this article I will post the complete source code.
I will use the UTFT and URTouch libraries made by Henning Karlsen. Here I would like to say thanks to him for the incredible work he has done. The libraries enable really easy use of the TFT Screens, and they work with many different TFT screens sizes, shields and controllers. You can download these libraries from his website, RinkyDinkElectronics.com and also find a lot of demo examples and detailed documentation of how to use them.
After we include the libraries we need to create UTFT and URTouch objects. The parameters of these objects depends on the model of the TFT Screen and Shield and these details can be also found in the documentation of the libraries.
Next we need to define the fonts that are coming with the libraries and also define some variables needed for the program. In the setup section we need to initiate the screen and the touch, define the pin modes for the connected sensor, the led and the button, and initially call the drawHomeSreen() custom function, which will draw the home screen of the program.
So now I will explain how we can make the home screen of the program. With the setBackColor() function we need to set the background color of the text, black one in our case. Then we need to set the color to white, set the big font and using the print() function, we will print the string “Arduino TFT Tutorial” at the center of the screen and 10 pixels down the Y – Axis of the screen. Next we will set the color to red and draw the red line below the text. After that we need to set the color back to white, and print the two other strings, “by HowToMechatronics.com” using the small font and “Select Example” using the big font.
Next is the distance sensor button. First we need to set the color and then using the fillRoundRect() function we will draw the rounded rectangle. Then we will set the color back to white and using the drawRoundRect() function we will draw another rounded rectangle on top of the previous one, but this one will be without a fill so the overall appearance of the button looks like it has a frame. On top of the button we will print the text using the big font and the same background color as the fill of the button. The same procedure goes for the two other buttons.
Now we need to make the buttons functional so that when we press them they would send us to the appropriate example. In the setup section we set the character ‘0’ to the currentPage variable, which will indicate that we are at the home screen. So if that’s true, and if we press on the screen this if statement would become true and using these lines here we will get the X and Y coordinates where the screen has been pressed. If that’s the area that covers the first button we will call the drawDistanceSensor() custom function which will activate the distance sensor example. Also we will set the character ‘1’ to the variable currentPage which will indicate that we are at the first example. The drawFrame() custom function is used for highlighting the button when it’s pressed. The same procedure goes for the two other buttons.
drawDistanceSensor(); // It is called only once, because in the next iteration of the loop, this above if statement will be false so this funtion won"t be called. This function will draw the graphics of the first example.
getDistance(); // Gets distance from the sensor and this function is repeatedly called while we are at the first example in order to print the lasest results from the distance sensor
So the drawDistanceSensor() custom function needs to be called only once when the button is pressed in order to draw all the graphics of this example in similar way as we described for the home screen. However, the getDistance() custom function needs to be called repeatedly in order to print the latest results of the distance measured by the sensor.
Here’s that function which uses the ultrasonic sensor to calculate the distance and print the values with SevenSegNum font in green color, either in centimeters or inches. If you need more details how the ultrasonic sensor works you can check my particular tutorialfor that. Back in the loop section we can see what happens when we press the select unit buttons as well as the back button.
Ok next is the RGB LED Control example. If we press the second button, the drawLedControl() custom function will be called only once for drawing the graphic of that example and the setLedColor() custom function will be repeatedly called. In this function we use the touch screen to set the values of the 3 sliders from 0 to 255. With the if statements we confine the area of each slider and get the X value of the slider. So the values of the X coordinate of each slider are from 38 to 310 pixels and we need to map these values into values from 0 to 255 which will be used as a PWM signal for lighting up the LED. If you need more details how the RGB LED works you can check my particular tutorialfor that. The rest of the code in this custom function is for drawing the sliders. Back in the loop section we only have the back button which also turns off the LED when pressed.
In order the code to work and compile you will have to include an addition “.c” file in the same directory with the Arduino sketch. This file is for the third game example and it’s a bitmap of the bird. For more details how this part of the code work you can check my particular tutorial. Here you can download that file:
drawDistanceSensor(); // It is called only once, because in the next iteration of the loop, this above if statement will be false so this funtion won"t be called. This function will draw the graphics of the first example.
getDistance(); // Gets distance from the sensor and this function is repeatedly called while we are at the first example in order to print the lasest results from the distance sensor
When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.
An excellent new compatible library is available which can render TrueType fonts on a TFT screen (or into a sprite). This has been developed by takkaO and is available here. I have been reluctant to support yet another font format but this is an amazing library which is very easy to use. It provides access to compact font files, with fully scaleable anti-aliased glyphs. Left, middle and right justified text can also be printed to the screen. I have added TFT_eSPI specific examples to the OpenFontRender library and tested on RP2040 and ESP32 processors, however the ESP8266 does not have sufficient RAM. Here is a demo screen where a single 12kbyte font file binary was used to render fully anti-aliased glyphs of gradually increasing size on a 320x480 TFT screen:
For ESP32 ONLY, the TFT configuration (user setup) can now be included inside an Arduino IDE sketch providing the instructions in the example Generic->Sketch_with_tft_setup are followed. See ReadMe tab in that sketch for the instructions. If the setup is not in the sketch then the library settings will be used. This means that "per project" configurations are possible without modifying the library setup files. Please note that ALL the other examples in the library will use the library settings unless they are adapted and the "tft_setup.h" header file included. Note: there are issues with this approach, #2007 proposes an alternative method.
Support has been added in v2.4.70 for the RP2040 with 16 bit parallel displays. This has been tested and the screen update performance is very good (4ms to clear 320 x 480 screen with HC8357C). The use of the RP2040 PIO makes it easy to change the write cycle timing for different displays. DMA with 16 bit transfers is also supported.
Support for the ESP32-S2, ESP32-S3 and ESP32-C3 has been added (DMA not supported at the moment). Tested with v2.0.3 RC1 of the ESP32 board package. Example setups:
Smooth fonts can now be rendered direct to the TFT with very little flicker for quickly changing values. This is achieved by a line-by-line and block-by-block update of the glyph area without drawing pixels twice. This is a "breaking" change for some sketches because a new true/false parameter is needed to render the background. The default is false if the parameter is missing, Examples:
New anti-aliased graphics functions to draw lines, wedge shaped lines, circles and rounded rectangles. Examples are included. Examples have also been added to display PNG compressed images (note: requires ~40kbytes RAM).
Frank Boesing has created an extension library for TFT_eSPI that allows a large range of ready-built fonts to be used. Frank"s library (adapted to permit rendering in sprites as well as TFT) can be downloaded here. More than 3300 additional Fonts are available here. The TFT_eSPI_ext library contains examples that demonstrate the use of the fonts.
Users of PowerPoint experienced with running macros may be interested in the pptm sketch generator here, this converts graphics and tables drawn in PowerPoint slides into an Arduino sketch that renders the graphics on a 480x320 TFT. This is based on VB macros created by Kris Kasprzak here.
The RP2040 8 bit parallel interface uses the PIO. The PIO now manages the "setWindow" and "block fill" actions, releasing the processor for other tasks when areas of the screen are being filled with a colour. The PIO can optionally be used for SPI interface displays if #define RP2040_PIO_SPI is put in the setup file. Touch screens and pixel read operations are not supported when the PIO interface is used.
The use of PIO for SPI allows the RP2040 to be over-clocked (up to 250MHz works on my boards) in Earle"s board package whilst still maintaining high SPI clock rates.
DMA can now be used with the Raspberry Pi Pico (RP2040) when used with both 8 bit parallel and 16 bit colour SPI displays. See "Bouncy_Circles" sketch.
The library now supports the Raspberry Pi Pico with both the official Arduino board package and the one provided by Earle Philhower. The setup file "Setup60_RP2040_ILI9341.h" has been used for tests with an ILI9341 display. At the moment only SPI interface displays have been tested. SPI port 0 is the default but SPI port 1 can be specifed in the setup file if those SPI pins are used.
The library now provides a "viewport" capability. See "Viewport_Demo" and "Viewport_graphicstest" examples. When a viewport is defined graphics will only appear within that window. The coordinate datum by default moves to the top left corner of the viewport, but can optionally remain at top left corner of TFT. The GUIslice library will make use of this feature to speed up the rendering of GUI objects (see #769).
An Arduino IDE compatible graphics and fonts library for 32 bit processors. The library is targeted at 32 bit processors, it has been performance optimised for RP2040, STM32, ESP8266 and ESP32 types, other processors may be used but will use the slower generic Arduino interface calls. The library can be loaded using the Arduino IDE"s Library Manager. Direct Memory Access (DMA) can be used with the ESP32, RP2040 and STM32 processors with SPI interface displays to improve rendering performance. DMA with a parallel interface (8 and 16 bit parallel) is only supported with the RP2040.
For other processors only SPI interface displays are supported and the slower Arduino SPI library functions are used by the library. Higher clock speed processors such as used for the Teensy 3.x and 4.x boards will still provide a very good performance with the generic Arduino SPI functions.
"Four wire" SPI and 8 bit parallel interfaces are supported. Due to lack of GPIO pins the 8 bit parallel interface is NOT supported on the ESP8266. 8 bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with the STM32 Nucleo 64/144 range or the UNO format ESP32 (see below for ESP32).
The library supports some TFT displays designed for the Raspberry Pi (RPi) that are based on a ILI9486 or ST7796 driver chip with a 480 x 320 pixel screen. The ILI9486 RPi display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. Note that due to design variations between these displays not all RPi displays will work with this library, so purchasing a RPi display of these types solely for use with this library is NOT recommended.
A "good" RPi display is the MHS-4.0 inch Display-B type ST7796 which provides good performance. This has a dedicated controller and can be clocked at up to 80MHz with the ESP32 (125MHz with overclocked RP2040, 55MHz with STM32 and 40MHz with ESP8266). The MHS-3.5 inch RPi ILI9486 based display is also supported, however the MHS ILI9341 based display of the same type does NOT work with this library.
Some displays permit the internal TFT screen RAM to be read, a few of the examples use this feature. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation.
The library supports Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is relatively immature and thus only one example has been provided.
The library includes a "Sprite" class, this enables flicker free updates of complex graphics. Direct writes to the TFT with graphics functions are still available, so existing sketches do not need to be changed.
A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16 bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16 bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datasheet implies so a 16 bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8 bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts.
One or more sprites can be created, a sprite can be any pixel width and height, limited only by available RAM. The RAM needed for a 16 bit colour depth Sprite is (2 x width x height) bytes, for a Sprite with 8 bit colour depth the RAM needed is (width x height) bytes. Sprites can be created and deleted dynamically as needed in the sketch, this means RAM can be freed up after the Sprite has been plotted on the screen, more RAM intensive WiFi based code can then be run and normal graphics operations still work.
Drawing graphics into a sprite is very fast, for those familiar with the Adafruit "graphicstest" example, this whole test completes in 18ms in a 160x128 sprite. Examples of sprite use can be found in the "examples/Sprite" folder.
If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind.
The "Animated_dial" example shows how dials can be created using a rotated Sprite for the needle. To run this example the TFT interface must support reading from the screen RAM (not all do). The dial rim and scale is a jpeg image, created using a paint program.
The XPT2046 touch screen controller is supported for SPI based displays only. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. This support will eventually be deprecated when a suitable touch screen library is available.
The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses. Only one SPI device can be connected to the FLASH pins and the chips select for the TFT must be on pin D3 (GPIO0).
The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-aliased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen.
The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for the different processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions.
Configuration of the library font selections, pins used to interface with the TFT and other features is made by editing the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file. Fonts and features can easily be enabled/disabled by commenting out lines.
Anti-aliased (smooth) font files in "vlw" format are generated by the free Processing IDE using a sketch included in the library Tools folder. This sketch with the Processing IDE can be used to generate font files from your computer"s font set or any TrueType (.ttf) font, the font file can include any combination of 16 bit Unicode characters. This means Greek, Japanese and any other UCS-2 glyphs can be used. Character arrays and Strings in UTF-8 format are supported.
The .vlw files must be uploaded to the processors FLASH filing system (SPIFFS, LittleFS or SD card) for use. Alternatively the .vlw files can be converted to C arrays (see "Smooth Font -> FLASH_Array" examples) and sto