arduino tft display animation code for sale
ILI9341 based TFT Touchscreen Display Shields are very popular low cost Display Shields for Arduino. Visuino has had support for them for quite a while, but I never had chance to write a Tutorial on how to use them. Recently however few people asked questions about using displays with Visuino, so I decided to make a tutorial.
In this Tutorial, I will show you how easy it is, to connect the Shield to Arduino, and program it with Visuino to animate a Bitmap to move around on the Display.
In the "Shields" dialog expand the "Displays" category, and select the "TFT Color Touch Screen Display ILI9341 Shield", then click on the "+" button to add it (Picture 2)
Next we need to add Graphics elements to render text and bitmap. First we will add graphics element to draw the shadow of the text:In the Object Inspector, click on the "..." button next to the value of the "Elements" property of the "TFT Display" Element (Picture 1)
In the File Open Dialog, select the bitmap to draw, and click on the "Open" button (Picture 4). If the file is too big it may not be able to fit in the Arduino memory. If you get out of memory error during the compilation, you may need to select a smaller bitmap
Connect the "Out" output pin of the SineIntegerGenerator1component to the "X" input pin of the "Shields.TFT Sisplay.Elements.Draw Bitmap1" element of the Arduino component (Picture 4)
Connect the "Out" output pin of the SineIntegerGenerator2component to the "Y" input pin of the "Shields.TFT Display.Elements.Draw Bitmap1" element of the Arduino component (Picture 5)
Connect the "Pin[ 1 ]" output pin of the "Clock" input pin of the "Shields.TFT Display.Elements.Draw Bitmap1" element of the Arduino component (Picture 6)
Pictures 2, 3, 4 and 5 and the Video show the connected and powered up project. You will see the Bitmap moving around the ILI9341 based TFT Touchscreen Display Shield as seen on the Video.
I decided I wanted to make a version 2 proton pack. But I also wanted it to have a small screen displaying basic animations. I tried loads of different TFT screens, and all of them were FAR to slow to make an animation.
Well thanks to the ILI9341 and the accompanying library by Marek Buriak, I was finally able to get raw 565 images to load at just over 4fps. Which was sufficient for very basic animations.
In this guide we’re going to show you how you can use the 1.8 TFT display with the Arduino. You’ll learn how to wire the display, write text, draw shapes and display images on the screen.
The 1.8 TFT is a colorful display with 128 x 160 color pixels. The display can load images from an SD card – it has an SD card slot at the back. The following figure shows the screen front and back view.
This module uses SPI communication – see the wiring below . To control the display we’ll use the TFT library, which is already included with Arduino IDE 1.0.5 and later.
The TFT display communicates with the Arduino via SPI communication, so you need to include the SPI library on your code. We also use the TFT library to write and draw on the display.
In which “Hello, World!” is the text you want to display and the (x, y) coordinate is the location where you want to start display text on the screen.
The 1.8 TFT display can load images from the SD card. To read from the SD card you use the SD library, already included in the Arduino IDE software. Follow the next steps to display an image on the display:
Note: some people find issues with this display when trying to read from the SD card. We don’t know why that happens. In fact, we tested a couple of times and it worked well, and then, when we were about to record to show you the final result, the display didn’t recognized the SD card anymore – we’re not sure if it’s a problem with the SD card holder that doesn’t establish a proper connection with the SD card. However, we are sure these instructions work, because we’ve tested them.
In this guide we’ve shown you how to use the 1.8 TFT display with the Arduino: display text, draw shapes and display images. You can easily add a nice visual interface to your projects using this display.
Whatever you are currently celebrating, Christmas, Hanukkah, Jul, Samhain, Festivus, or any other end-of-the-civil-year festivities, I wish you a good time! This December 25th edition of the Nextion Sunday Blog won"t be loaded with complex mathematical theory or hyper-efficient but difficult to understand code snippets. It"s about news and information. Please read below...After two theory-loaded blog posts about handling data array-like in strings (Strings, arrays, and the less known sp(lit)str(ing) function and Strings & arrays - continued) which you are highly recommended to read before continuing here, if you haven"t already, it"s big time to see how things work in practice! We"ll use a string variable as a lookup lookup table containing data of one single wave period and add this repeatedly to a waveform component until it"s full.A few weeks ago, I wrote this article about using a text variable as an array, either an array of strings or an array of numbers, using the covx conversion function in addition for the latter, to extract single elements with the help of the spstr function. It"s a convenient and almost a "one fits all" solution for most use cases and many of the demo projects or the sample code attached to the Nextion Sunday Blog articles made use of it, sometimes even without mentioning it explicitly since it"s almost self-explaining. Then, I got a message from a reader, writing: "... Why then didn"t you use it for the combined sine / cosine lookup table in the flicker free turbo gauge project?"105 editions of the Nextion Sunday blog in a little over two years - time to look back and forth at the same time. Was all the stuff I wrote about interesting for my readers? Is it possible at all to satisfy everybody - hobbyists, makers, and professionals - at the same time? Are people (re-)using the many many HMI demo projects and code snippets? Is anybody interested in the explanation of all the underlying basics like the algorithms for calculating square roots and trigonometric functions with Nextion"s purely integer based language? Are optimized code snippets which allow to save a few milliseconds here and there helpful to other developers?Looking through the different Nextion user groups on social networks, the Nextion user forum and a few not so official but Nextion related forums can be surprising. Sometimes, Nextion newbies ask questions or have issues although the required function is well (in a condensed manner for the experienced developer, I admit) documented on the Nextion Instruction Set page, accessible through the menu of this website. On top of that, there is for sure one of my more than 100 Sunday blog articles which deals not only with that function, but goes often even beyond the usual usage of it. Apparently, I should sometimes move away from always trying to push the limits and listen to the "back to the roots!" calls by my potential readers...Do you remember the (almost) full screen sized flicker free and ultra rapid gauge we designed in June? And this without using the built-in Gauge component? If not, it"s time to read this article first, to understand today"s improvements. The June 2022 version does its job perfectly, the needle movement is quick and smooth, and other components can be added close to the outer circle without flickering since there is no background which needs constantly to be redrawn. But there was a minor and only esthetic weak point: The needle was a 1px thin line, sometimes difficult to see. Thus, already a short time after publishing, some readers contacted me and asked if there were a way to make the needle thicker, at least 2 pixels.
In this tutorial, I will show you how easy it is to connect the shield to the Arduino and program it using visualino to make the bitmap move on the display.
As shown in picturesTo to start programming the Arduino, insert the TFT shield into the top of the Arduino Uno, you need to install the Arduino IDE from here: Make sure to install 1. 6.
Displaying a custom image or graphic on a LCD display is a very useful task as displays are now a premium way of providing feedback to users on any project. With this functionality, we can build projects that display our own logo, or display images that help users better understand a particular task the project is performing, providing an all-round improved User Experience (UX) for your Arduino or ESP8266 based project. Today’s tutorial will focus on how you can display graphics on most Arduino compatible displays.
The procedure described in this tutorial works with all color displays supported by Adafruit’s GFX library and also works for displays supported by the TFTLCD library from Adafruit with little modification. Some of the displays on which this procedure works include:
While these are the displays we have, and on which this tutorial was tested, we are confident it will work perfectly fine with most of the other Arduino compatible displays.
For each of the displays mentioned above, we have covered in past how to program and connect them to Arduino. You should check those tutorials, as they will give you the necessary background knowledge on how each of these displays works.
For this tutorial, we will use the 2.8″ ILI9325 TFT Display which offers a resolution of 320 x 340 pixels and we will display a bitmap image of a car.
As usual, each of the components listed above can be bought from the links attached to them. While having all of the displays listed above may be useful, you can use just one of them for this tutorial.
To demonstrate how things work, we will use the 2.8″ TFT Display. The 2.8″ TFT display comes as a shield which plugs directly into the Arduino UNO as shown in the image below.
Not all Arduino displays are available as shields, so when working with any of them, connect the display as you would when displaying text (we recommend following the detailed tutorial for the display type you use of the above list). This means no special connection is required to display graphics.
Before an image is displayed on any of the Arduino screens, it needs to be converted to a C compatible hex file and that can only happen when the image is in bitmap form. Thus, our first task is to create a bitmap version of the graphics to be displayed or convert the existing image to a bitmap file. There are several tools that can be used for creation/conversion of bitmap images including, Corel Draw and Paint.net, but for this tutorial, we will use the Paint.net.
The resolution of the graphics created should be smaller than the resolution of your display to ensure the graphics fit properly on the display. For this example, the resolution of the display is 320 x 340, thus the resolution of the graphics was set to195 x 146 pixels.
Your graphics could also include some text. Just ensure the background is black and the fill color is white if you plan to change the color within your Arduino code.
With the graphics done, save both files as .bmp with 24bits color.It is important to keep in mind that large bitmaps use up a lot of memory and may prevent your code from running properly so always keep the bitmaps as small as possible.
Image2Code is an easy-to-use, small Java utility to convert images into a byte array that can be used as a bitmap on displays that are compatible with the Adafruit-GFX or Adafruit TFTLCD (with little modification) library.
Paste the bit array in the graphics.c file and save. Since we have two graphics (the car and the text), You can paste their data array in the same file. check the graphics.c file attached to the zip file, under the download section to understand how to do this. Don’t forget to declare the data type as “const unsigned char“, add PROGEM in front of it and include the avr/pgmspace.h header file as shown in the image below. This instructs the code to store the graphics data in the program memory of the Arduino.
With this done, we are now ready to write the code. Do note that this procedure is the same for all kind of displays and all kind of graphics. Convert the graphics to a bitmap file and use the Img2code utility to convert it into a hex file which can then be used in your Arduino code.
To reduce the amount of code, and stress involved in displaying the graphics, we will use two wonderful libraries; The GFX library and the TFTLCD library from Adafruit.
The GFX library, among several other useful functions, has a function called drawBitmap(), which enables the display of a monochrome bitmap image on the display. This function allows the upload of monochrome only (single color) graphics, but this can be overcome by changing the color of the bitmap using some code.
The Adafruit libraries do not support all of the displays but there are several modifications of the libraries on the internet for more displays. If you are unable to find a modified version of the library suitable for your the display, all you need do is copy the code of the drawBitmap() function from the GFX library and paste it in the Arduino sketch for your project such that it becomes a user-defined function.
The first two are thex and y coordinates of a point on the screen where we want the image to be displayed. The next argument is the array in which the bitmap is loaded in our code, in this case, it will be the name of the car and the text array located in the graphics.c file. The next two arguments are the width and height of the bitmap in pixels, in other words, the resolution of the image. The last argument is the color of the bitmap, we can use any color we like. The bitmap data must be located in program memory since Arduino has a limited amount of RAM memory available.
As usual, we start writing the sketch by including the libraries required. For this procedure, we will use the TFTLCD library alone, since we are assuming you are using a display that is not supported by the GFX library.
Next, we specify the name of the graphics to be displayed; car and title. At this stage, you should have added the bit array for these two bitmaps in the graphics.c file and the file should be placed in the same folder as the Arduino sketch.
With that done, we proceed to the void loop function, under the loop function, we call the drawbitmap() function to display the car and the text bitmap using different colors.
The last section of the code is the drawBitmap function itself, as earlier mentioned, to use the drawbitmap() function with the Adafruit TFTLCD library, we need to copy the function’s code and paste into the Arduino sketch.
Plug in your screen as shown above. If you are using any other display, connect it as shown in the corresponding linked tutorial. With the schematics in place, connect the Arduino board to your PC and upload the code. Don’t forget the graphics file needs to be in the same folder as the Arduino sketch.
That’s it for this tutorial guys. The procedure is the same for all kinds of Arduino compatible displays. If you get stuck while trying to replicate this using any other display, feel free to reach out to me via the comment sections below.
We have used Liquid Crystal Displays in the DroneBot Workshop many times before, but the one we are working with today has a bit of a twist – it’s a circle! Perfect for creating electronic gauges and special effects.
LCD, or Liquid Crystal Displays, are great choices for many applications. They aren’t that power-hungry, they are available in monochrome or full-color models, and they are available in all shapes and sizes.
Today we will see how to use this display with both an Arduino and an ESP32. We will also use a pair of them to make some rather spooky animated eyeballs!
There are also some additional connections to the display. One of them, DC, sets the display into either Data or Command mode. Another, BL, is a control for the display’s backlight.
The above illustration shows the connections to the display. The Waveshare display can be used with either 3.3 or 5-volt logic, the power supply voltage should match the logic level (although you CAN use a 5-volt supply with 3.3-volt logic).
Another difference is simply with the labeling on the display. There are two pins, one labeled SDA and the other labeled SCL. At a glance, you would assume that this is an I2C device, but it isn’t, it’s SPI just like the Waveshare device.
This display can be used for the experiments we will be doing with the ESP32, as that is a 3.3-volt logic microcontroller. You would need to use a voltage level converter if you wanted to use one of these with an Arduino Uno.
The Arduino Uno is arguably the most common microcontroller on the planet, certainly for experiments it is. However, it is also quite old and compared to more modern devices its 16-MHz clock is pretty slow.
The Waveshare device comes with a cable for use with the display. Unfortunately, it only has female ends, which would be excellent for a Raspberry Pi (which is also supported) but not too handy for an Arduino Uno. I used short breadboard jumper wires to convert the ends into male ones suitable for the Arduino.
Once you have everything hooked up, you can start coding for the display. There are a few ways to do this, one of them is to grab the sample code thatWaveshare provides on their Wiki.
The Waveshare Wiki does provide some information about the display and a bit of sample code for a few common controllers. It’s a reasonable support page, unfortunately, it is the only support that Waveshare provides(I would have liked to see more examples and a tutorial, but I guess I’m spoiled by Adafruit and Sparkfun LOL).
Open the Arduino folder. Inside you’ll find quite a few folders, one for each display size that Waveshare supports. As I’m using the 1.28-inch model, I selected theLCD_1inch28folder.
Once you do that, you can open your Arduino IDE and then navigate to that folder. Inside the folder, there is a sketch file namedLCD_1inch28.inowhich you will want to open.
When you open the sketch, you’ll be greeted by an error message in your Arduino IDE. The error is that two of the files included in the sketch contain unrecognized characters. The IDE offers the suggestion of fixing these with the “Fix Encoder & Reload” function (in the Tools menu), but that won’t work.
The code is pretty basic, I’m not repeating all of it here, as it consists of several files. But we can gather quite a bit of knowledge from the main file, as shown here.
You can see from the code that after loading some libraries we initialize the display, set its backlight level (you can use PWM on the BL pin to set the level), and paint a new image. We then proceed to draw lines and strings onto the display.
After uploading the code, you will see the display show a fake “clock”. It’s a static display, but it does illustrate how you can use this with the Waveshare code.
This library is an extension of the Adafruit GFX library, which itself is one of the most popular display libraries around. Because of this, there isextensive documentation for this libraryavailable from Adafruit. This makes the library an excellent choice for those who want to write their own applications.
As with the Waveshare sample, this file just prints shapes and text to the display. It is quite an easy sketch to understand, especially with the Adafruit documentation.
The sketch finishes by printing some bizarre text on the display. The text is an excerpt from The Hitchhiker’s Guide to the Galaxy by Douglas Adams, and it’s a sample of Vogon poetry, which is considered to be the third-worst in the Galaxy!
Here is the hookup for the ESP32 and the GC9A01 display. As with most ESP32 hookup diagrams, it is important to use the correct GPIO numbers instead of physical pins. The diagram shows the WROVER, so if you are using a different module you’ll need to consult its documentation to ensure that you hook it up properly.
The TFT_eSPI library is ideal for this, and several other, displays. You can install it through your Arduino IDE Library Manager, just search for “TFT_eSPI”.
There is a lot of demo code included with the library. Some of it is intended for other display sizes, but there are a few that you can use with your circular display.
To test out the display, you can use theColour_Test sketch, found inside the Test and Diagnostic menu item inside the library samples. While this sketch was not made for this display, it is a good way to confirm that you have everything hooked up and configured properly.
A great demo code sample is theAnimated_dialsketch, which is found inside theSpritesmenu item. This demonstration code will produce a “dial” indicator on the display, along with some simulated “data” (really just a random number generator).
In order to run this sketch, you’ll need to install another library. Install theTjpeg_DecoderLibrary from Library Manager. Once you do, the sketch will compile, and you can upload it to your ESP32.
One of my favorite sketches is the Animated Eyes sketch, which displays a pair of very convincing eyeballs that move. Although it will work on a single display, it is more effective if you use two.
The first thing we need to do is to hook up a second display. To do this, you connect every wire in parallel with the first display, except for the CS (chip select) line.
The Animated Eyes sketch can be found within the sample files for the TFT_eSPI library, under the “generic” folder. Assuming that you have wired up the second GC9A01 display, you’ll want to use theAnimated_Eyes_2sketch.
The GC9A01 LCD module is a 1.28-inch round display that is useful for instrumentation and other similar projects. Today we will learn how to use this display with an Arduino Uno and an ESP32.
Stop-motion animation is the reverse process of freezing motion: such an animation is produced by displaying successive picture frames at high speed. Here we bring back to life Muybridges’ Sallie Gardner with the aid of a microcontroller connected to a suitable display. Several displays were tested with the ‘Sallie Gardner’ sketch running on an Arduino Uno, Nano or a Wemos D1 mini with an ESP8266 microprocessor chip.
Arduinos are designed to microprocess: they receive data, calculate, and communicate. Output through a display is limited since Arduinos lack a graphical processor. All the hard work in a common Arduino (Uno, Nano) is performed by a single 8-bit processor (ATmega 328) that has limited memory: 1kB EEPROM, 2kB SRAM (‘dynamic memory’) and 32kB flash memory (‘program memory’).
Programs are loaded in program memory while variables are created and during runtime stored in dynamic memory. Users have to live with the dynamic and program memory constraints offered by a common Arduino, or they can switch to an Arduino ‘Mega’ with an ATmega2560 microprocessor (256 kB flash and 8kB SRAM). One jump higher on the ladder is the family of ESP8266 based microboards, e.g., the Wemos D1 mini: 4 MB of SRAM and 50 kB of flash memory.
The challenge in the current project was to achieve fluent stop-motion animation featuring Sallie Gardner, using a humble Arduino Nano, and to see how well the animation performs with several displays. For this purpose I had available a 128*64 pixel LCD display with ST7920 controller, a 128*64 hybrid OLED display with SSD1306 controller, a 130*130 SSD TFT screen with 1283A controller, a 240*240 pixel TFT display powered by a SSD1283A chip, and several larger Arduino compatible TFT displays driven by ILI controllers
Our LCD display limits images to 128×64 pixels. The original ‘The Horse in Motion’ picture is an eight-bit gray scale jpg file from which we have to cut out frames to produce the animation bitmaps. Each cut-out frame produces a file with a size of 19 kB. Eleven of these files take 198 kB which is far beyond the amount of memory available in program space of an Arduino Nano. One solution for this is to load the files one after another from sd card, but the time consumed by this process would produce a slide show rather than the illusion of motion. A better solution is to load image frames from a separate .cpp file that needs to reside in the same directory as the sketch. The third approach, used in this paper, is to include the images in the sketch. One way or another, we need to reduce the image frames for our stop-motion animation to dimensions of 128×64 pixels or less to fit the screen.
The combination all these considerations leads to the need to cut Muybridge’s ‘The Horse in Motion’ photograph down to eleven 1-bit frames each 128 pixels wide and 64 pixels high. Smaller frames are allowed; an advantage of smaller frames is faster loading in the LCD and, for that matter, a smoother animation.
9. Scale the entire stack such that animation frame bitmaps, when exported, satisfy the conditions for LCD display: maximum width 128 pixels, maximum height 64 pixels. In the case of Sallie Gardner the scaling was conducted such that exported animation frame images measured 96×64 pixels, that is: height is here the limiting factor for the Sallie Gardner animation frames.
An intermediate, monitoring step is to check with an animated GIF creating program whether all export actions have been executed correctly and indeed have produced the 1-bit monochrome bitmaps that we need for the animation. I use Fiji (ImageJ) for this purpose. Fiji is a wonderful, free, open source cross platform imaging suite built on a Java platform (https://imagej.net/Fiji). One can also check with an animated GIF how fluid the movements in the Arduino animation will be. Small corrections can at this point be made in the vector file to get the very best out of the animation.
While Arduinos can work with bitmap files loaded from sd card, the loading and processing from sd card is is not fast enough to support animation. The monochrome images that we have produced need to be embedded in the sketch in 8-bit hexadecimal code (so-called ‘c-array’), or as ‘extern’ in the sketch folder
Conversion from bitmap to hexadecimal code is done with the program lcd-image-converter (freely available at https://sourceforge.net/projects/lcd-image-converter/). There exist also on line conversion tools.
The image section contains commented-out lines with dots and colored blocks that provide a visual impression of the 1-bit image. Notice that there are 64 lines with each 96 dots or blocks, in other words a representation of what is going to be displayed on screen.
The bottom section is the most valuable part of the file: the hex array code. Pixels are coded in groups of eight; because the image will be 96 pixels wide there are 96 : 8 = 12 columns of bytes. The number of rows is 64 or equal to the height of the image.
The c-array starts with a variable: static const uint8_t, followed by the image’s file name and size (between the brackets). File size of each c-array is 768 bytes which will result in an animation that has 11×768 bytes = 8,448 bytes. With an Arduino Uno or Nano these c-arrays must be placed in program memory because the dynamic memory can hold only 2 kB of information.
figure 5. C-array file opened with an ascii editor (gedit). Frame 0. Left column: the entire c-array file listed. C-array files are composed as follows: top section: array information (commented), middle section: visual output (commented). All you need is in fact to copy-paste the bottom section: hex code array (pink) into the Arduino sketch.
If an array is defined in a sketch it will by default be compiled by the Arduino IDE to run in dynamic memory. As shown above, each frame of our animation requires 768 bytes. All the c-arrays must be placed in in program memory as constant unsigned chars. To achieve this the library
The stop-motion was initially developed on a 128*64 LCD, just out of curiosity to know in the first place whether it was possible to create an animation on technology so limited in graphic display. The library available to work with the 128*64LCD is
The complete sketch for the 128*64 ST7920 LCD wired to an Arduino Nano is supplied at the end of this document. You will find also versions of the sketch compatible with different display / microprocessor combinations. All these sketches contain the hexadecimal c-array description for each frame. I have added for each frame in a series of commented lines of empty and black characters a visual impression of how the frame looks like.
From the beginning it was evident that frame nr. 11 of “The Horse in Motion” would not contribute to a fluent animation. I assumed that each of the other frames would smoothly transfer to the next and that each animation cycle of frames would smoothly overflow into the next. However, the prototype sketch running on an Arduino Nano that powers a 128*64 LCD with ST7920 controller (figure 6), hiccuped at the point where it cycles from the last frame to the first. The cause appeared to be frame nr. 0 that seems to be atypical. Maybe this frame has been included by Muybridge to produce an appealing 4×3 photomontage. Who knows. Anyway, after frame nr 0 was excluded a very smoothly running animation remained. At this point I decided to include only frames 1 through 10 in the final animation. After completion of the prototyping work the ‘production’ sketch was adapted to run on a variety of combinations of microprocessor boards and displays at hand. A selection of the tested displays is shown in figure 6 while the table below provides the essentials of the tested devices.
Running the animation on the 128*64 LCD requires reference to the
The 130*130 TFT display has a SSD1283A controller that needs the
Equestrian performance on the 130*130 TFT display connected to a Wemos D1 Mini did not produce faster animation than with a Nano as engine. In sketches written for the Wemos D1 Mini one is free to use the PROGMEM instruction. This microprocessor board has plenty SRAM available for the animation job. If PROGMEM was left out and all frame arrays were loaded as variables in dynamic memory instead of program memory, one might expect a faster animation. This however did not materialize: the speed of the animation did not change.
On the TFT display with more pixels (240*240-ST7789) the results were disappointing. Screen updates between every frame that sweep the entire screen instead of the 128×64 pixel ‘Sallie Gardner’ were markedly visible. On the 2.4, 2.8, 3.5 and 3.95 inch 240×320 and 320×480 pixel TFT displays (shields) with ILI controllers, including the 3.95 inch 320×480 ILI6814 screen, animation speed was grandiose, thanks to the support of David Prentice’s
figure 6. Animation played on several displays in combination with either Arduino Uno or Nano, or with a Wemos D1 Mini. While all these images measure 96 pixels in width and 64 pixels in height the size of their appearance is different because of pixel dimensions in these displays. The speed of the animation differs sharply between displays depending on the ‘efficiency’ of the library included in the sketch. The head of the jockey on the OLED is yellow because this display is of the hybrid, blue-yellow type.
The 128*64 LCD is a relatively big display with in proportion big LCD pixels. The OLED, 130*130 TFT and 240*240 TFT are devices with one-inch diagonal screens where the 240*240 TFT stands out with minuscule pixels that provide extreme sharpness. Sallie Gardner will certainly win a horse race on 320*480 TFT screens with my sketches compared with the LCD, OLED and small TFTs. The secret here is that on the TFT displays running under the
Searching the internet for other Muybridge horse animations for the Arduino I encountered in the Arduino forum a sketch for the Adafruit 128*64 OLED created in 2016 by Greg Stievenart and featuring ‘Annie G’, another galloping race horse, from Muybridge’s book “Animal Locomotion” (1887), plate 626; Muybridge has published hundreds of montage pictures of all kinds of animals and humans in motion; Sallie Gardner was only the premiere of his gigantic oevre. See https://forum.arduino.cc/index.php?topic=375985.0. Greg uses the method wherein the c-arrays are separate, external files. This works fine.
Most of the work to produce an animation is invested in the preparation of the frames. The limitations as far as Arduinos concerned are display size, c-array size, available memory in the microprocessor board, number and size of the frames, display controller speed and, finally, the efficiency of the library that contains the graphical and bitmap functions that govern printing each c-array to the display. Quite a handful of constraints! This makes it the more challenging and simultaneously more fun to continue working with small microprocessor boards. An animation is a chain of events in which the slowest link determines the outcome, that is a smooth and elegant animation.
I optimize other people"s code for a living. This library is a good example of the kind of work I do for my commercial clients; it contains many unique and clever optimizations that allows it to perform better than anything else available. I"m happy to contribute optimized libraries to the open source community in addition to working on commercial projects. Whatever platform you"re using, I can make significant improvements to your native code. Please contact me so that I can show you how.
I started working with image and video files around 1989 and soon turned my interest into a Document Imaging product based on my own imaging library. Over the years I added support for more and more formats until I had supported all of the standard ones, including DICOM. I sold my Document Imaging business in 1997, but still found uses for my imaging code in other projects such as retro gaming. I recently went looking to see if there was a good GIF player for Arduino and only found Adafruit"s library. Unfortunately it only runs on their ATSAMD51 boards. I thought it would be possible to use my old code to create a universal GIF player that could run on any MCU/SoC with at least 24K of RAM, so I started modifying my old GIF code for this purpose. The focus of this project is speed and to use as little RAM as possible, so there are some limitations.
To save memory, the code limits the maximum image width to 320 pixels. This is just a constant defined in AnimatedGIF.h, so you can set it larger if you like. Animated GIF images have a lot of options to save space when encoding the changes from frame to frame. Many of the tools which generate animated GIFs don"t make use of every option and that"s helpful because the frame disposal options are not supported in the library code. They can be implemented in your drawing callback if you want. The reason they"re not provided with this code is because one of the image disposal options requires you to keep an entire copy of the previous frame and this would prevent it from working on low memory MCUs. If would also require dynamic memory allocation which is another area I avoided with this code.
My work is always focused on code optimization, so this project is no different. I"ve profiled this code and optimized it for 32-bit CPUs. I discovered while testing it that seeking on micro SD cards (on Arduino) is very very slow. I had to use a little extra RAM to buffer incoming data to avoid seeking. The code does need to seek, but it"s done very rarely. I also wrote code to buffer and de-chunk some of the incoming LZW data to avoid checking for chunk boundaries in the inner decode loop. There are a number of clever optimizations that should allow this to run faster than any existing GIF solutions on Arduino boards. The speed gained from my decoder will be lost if it takes too long to display the pixels. For this reason, the GIFDRAW callback passes an RGB565 palette in the byte order of your choosing and the example sketches uses functions to write entire lines of pixels to the SPI TFT displays in a single shot. If you implement your own GIFDRAW callback and have to pass 1 pixel at a time to whatever display device you"re using, this will cause a major slowdown in the display of the frames.
The chart above shows the total time to decode an 8-frame sequence included in the test_images folder. The decoding speed of your particular image depends on the complexity (how much compressed data) and if/how transparent pixels are used. Small runs of transparent pixels will interfere with the performance of displaying the image on an SPI LCD. This particular image doesn"t use transparency, so the time is purely for decoding the data.
You"ll notice that the images provided in the test_images folder have been turned into C code. Each byte is now in the form 0xAB so that it can be compiled into your program and stored in FLASH memory alongside your other code. You can use a command I wrote called image_to_c (https://github.com/bitbank2/image_to_c) to convert a binary file into this type of text. If you use another tool, make sure to add a const modifier in front of the GIF data array to ensure that it gets written to FLASH and not RAM by your build environment.
One of the reasons that this is apparently the first universal GIF library for Arduino is because the lack of available RAM and myriad display options would make it difficult to support all MCUs and displays properly. I decided that to solve this issue, I would isolate the GIF decoding from the display and file I/O with callback functions. This allows the core code to run on any system, but you need to help it a little. At a minimum, your code must provide a function to draw (or store) each scan line of image. If you"re playing a GIF file from memory, this is the only function you need to provide. In the examples folder there are multiple sketches to show how this is done on various display libraries. For reading from SD cards, 4 other functions must be provided: open, close, read, seek. There is an example for implementing these in the examples folder as well.
If you"re using the ESP32 or ESP8266 and playing GIF images stored in RAM, you"ll need to provide the 4 file callback functions or modify the existing ones because RAM and FLASH are in different address spaces (Harvard architecture). The code assumes the source of the GIF data is in FLASH and uses memcpy_P() instead of memcpy() to access it.
When you use a tile to index to a custom character RAM location everything works in the same way except that it is RAM and can be changed. Any changes to the custom character RAM are effectively immediate changes to whats displayed.
Because the screen has no (graphical) pixel memory itself, any *previous* state of a custom character memory is not displayed, only the current state of custom character memory can be displayed.