Arduino Serial UART Scrolling Display Terminal Using a 2.2" TFT

24,842

41

38

Published

Introduction: Arduino Serial UART Scrolling Display Terminal Using a 2.2" TFT

I have been making projects based around a 2.2" TFT display which uses the ILI9341 driver chip, this display can be connected to and controlled by an Arduino UNO. As a bit of background reading you may find my instructable here useful.

During debugging of one of my battery powered Arduino projects I needed to have a portable terminal to look at the debug output being printed to the serial pins. To achieve this I built the small portable display terminal described herein.

The unique part of this project is that the sketch uses the built in hardware scrolling feature of the ILI9341 chip, this takes the processing burden off the Arduino AVR microcontroller and means that the display can keep up with serial text messages at 9600 baud.

The ILI9341 and GFX libraries featured in this instructable has been optimised for speed, some of the speed enhancing features use direct PORT access to the ATmega328 registers so it is important to use an Arduino board based on that processor chip. These speed improvements means that characters in the proportional font 2 can be printed to the screen at more than 1000 characters per second... which is a bit faster than I can read them!

Though the development has been done with a UNO, the final battery powered terminal will be based around the smaller Pro Micro, with a battery pack and 3 AA batteries this will be nice and portable.

Step 1: Connecting It Up

The connections between the display and UNO are not the same as my other instructable, for this project connect as follows:

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

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

Once programmed the Terminal can be connected to another Arduino to monitor the serial output:

  • Set the baud rate on the Arduino to be monitored to 9600 baud (or modify the Terminal sketch to match)
  • Connect the Terminal UNO GND to GND on the Arduino to be monitored
  • Connect the Terminal UNO Rx pin to the Tx pin on the Arduino to be monitored

Output text messages sent using Serial.print from the other Arduino to the Terminal will be displayed. At 9600 baud the Terminal manages to keep up with the data flow.

Step 2: The Sketches and Libraries

The libraries and sketches needed are attached as zip files. The Terminal sketch is included as one of the examples within the Adafruit_ILI9341_AS library.

The Adafruit_GFX_AS library attached contains some significant speed improvements that permit drawing font 2 characters at over 1000 per second, this is needed to keep up with with a full speed 9600 baud rate. This version of the library requires the use of the ATmega328 processor (as used on UNO) since direct PORT access is performed. To use the library with other processors, such as the ATmega2560, the sketch will need to be modified to the correct hardware SPI pins and the following line must be commented out:

#define F_AS_T

within the "Adafruit_ILI9341_FAST.h" header file located in the Adafruit_ILI9341_AS library folder.

No changes are needed when using the ATmega328 based Arduinos providing the pins listed above are used.

A speed demo sketch has been included here, this is the one I use to test the speed improvements, it is an adapted version of a sketch that comes with the Arduino UTFT library.

Step 3: Operating at Higher Baud Rates

In most cases characters don't get lost at 9600 baud but it is a good idea to increase the serial Rx buffer from 64 bytes to 512 or 1024 bytes, especially if higher baud rates are used. The sketch does not use much RAM so even a 1024 byte Rx buffer leaves RAM spare.

To increase the serial buffer space the method described here works well:

http://www.hobbytronics.co.uk/arduino-serial-buff...

The TFT ILI9341 driver scrolls the display almost instantly, but it takes the Arduino about 13 milliseconds (ms) to erase a line on the display during the scroll process. In this time more characters may be arriving, so the buffer helps by storing the serial data until the ATmega processor gets around to taking more bytes out of the buffer.

The line erasure code in the sketch is optimised by storing the length of each line of printed text and then only over-writing that area, this means the worst case where 1 character is printed on every line it does not take 13ms to scroll and erase a line, but more like 1ms.

Step 4: Adapting the Sketch

Using the hardware scrolling feature of the display is not easy to understand, it is one of the more esoteric facilities the ILI9341 driver chip provides. The concepts of circular buffers and how the pixel y coordinate changes as the display scrolls will need to be understood, otherwise changes to the sketch are likely to give seemingly unpredictable results. If you are really keen then read the ILI9341 data sheet!

Just for fun I created a "Matrix" falling characters effect by scrolling the screen! Sketch is attached in case anyone may be interested... :-)

Step 5: The Future...

Any updates or bug fixes to the code will be posted here, so come back and check for updates if you are having a problem.

3 People Made This Project!

Recommendations

  • Oil Contest

    Oil Contest
  • Make it Move Contest

    Make it Move Contest
  • Casting Contest

    Casting Contest
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

38 Comments

This is fantastic work! (this and your optimised libraries ) I haven't seen the scrolling feature of these displays used by anyone else. You mention the circular buffers are hard to use/understand, Is it possible that you could incorporate the functionality into your libraries, abstracted to a nice simple method like tft.Scroll(DIRECTION, DISTANCE); ? This would be incredibly useful. Can you scroll just an area? (Im guessing so, unless you're redrawing the title bar in this project..) if so, a function like scroll(x,y,h,w,direction distance), or one for setting the area, and one for scrolling it, would suit all purposes, and be greatly appreciated by many.

Your idea re RLE compression of fonts(and icons) is VERY exiting. I crave full hi-res font sets than fit comfortably on a 328.

Can't overstate how much I appreciate your work and the quality of your writeup.

1 reply

Thank you for your kind comments. This Instructable is not a particularly popular one so I did not think there was much interest in adding the scrolling capability to a library! The displays are designed for use in portrait orientation so can only be scrolled up/down in that axis. A single area can be defined to scroll, it must span the width of the screen (in portrait mode) but can start and end at any point on the y axis.

The problem is the y coordinates change within the scrolling area so it is easy to get in a pickle when using this feature!

I did consider adding a scroll left,scroll right function to the library so pictures off SD Card can be drawn scrolling on and off screen in a wiping action. Other than a terminal or picture scrolling I haven't thought of an application for this hardware feature!

Thanks again for your comments.

Hi Bodmer!
I'm trying to use an Arduino code that makes use of this library: Adafruit_ILI9341_AS; I
installed it in the correct location but when I compile in Arduino (IDE
1.8.5) it presents the following error: 'class Adafruit_ILI9341_AS' has
no member named 'setTextColor'; I also noticed that this function does not appear in the CPP file of this library. But I can not find another.
The Adafruit_GFX_AS library is also installed.
Thank you if you can help.

3 replies

The setTextColor() function is defined in the Adafruit_GFX_AS.h header and .cpp file so this suggests that the library is not being called in the sketch or is not being found by the Arduino IDE.

Hi Bodmer! All
the "Adafruit_GFX_AS" libraries I have downloaded do not have the
setTextColor() function. Could you provide some that have this
function? Thanks

Are you sure yiu have the v8 version from step 2 of the Instructable loaded as I can see the function exists.

Greetings;
I
have an arduino sketch that calls this library
<Adafruit_ILI9341_AS.h> but, it displays the following error: 'class Adafruit_ILI9341_AS' has no member named 'setTextColor'

error:
'class Adafruit_ILI9341_AS' has no member named 'fillCircle'

error:
'class Adafruit_ILI9341_AS' has no member named 'drawCentreString'

error:
'class Adafruit_ILI9341_AS' has no member named 'drawLine'

I've been looking in the .CPP and .H files and these are not included.
can anybody help me? Thank you

1 reply

Answered above.

Hello,
I try to transform your good job from ILI9341 for ILI9342 (320x240, inverted color, miroring text), but I can not.
Can you help me please ?

Hello, I bought this TFT:

http://www.ebay.it/itm/Schermo-TFT-LCD-320-x-480-3-2-pollici-Arduino-963573-/121868650556?hash=item1c5ff0083c:g:LbkAAOSw5dNWnLH6

I would mount it on an Arduino Mega and recall the images uploaded to SD with a button ... can you help me?

Thank you and congratulations for the job!

regards,

Gerry

Some further experiments with the backlighting led. I'm not sure if this has a dropping resistor on the ILI9341 board and I suspect it may not. I measured the current by measuring the volts across a 1R resistor to the led pin and got a value of 200mV, ie 200mA. The display was also getting quite warm.

My guess is this is a white led with a forward voltage of about 3V and running it from 5V it may have a short life. I tried adding a 220R resistor in series - this would give about 10mA rather than 200mA. Certainly the display is not as bright, but it is running cold now.

100R would give 20mA which may be a better compromise for brightness vs life expectancy.

Your thoughts would be most appreciated.

Cheers, James Moxham

1 reply

Hi, It seems that some of these displays come with resistors built in and others do not.

My display has a circuit on the back to switch power to the LED, I measured the LED current at 50mA, so for your display I suggest a value of 56R would be good.

This is awesome, thank you for sharing. Would it be possible to adapt the program so that it works in landscape mode? I need to display longer lines.

Thank you!

2 replies

Hi, unfortunately the hardware scroll feature only provides vertical scrolling in portrait orientation...

Thanks for the reply. It would have been cool though :-)

I ran into a problem with Adafruit_ILI9341_AS8::pushColors. I'm testing your ILI9341_draw_bitmap_v2.ino file from another instructable. The error from the compiler is:


ILI9341_draw_bitmap_v2.cpp.o: In function `drawRAW(char*, int, int, int, int)':
/Users/xxxx/ILI9341_draw_bitmap_v2.ino:398: undefined reference to `Adafruit_ILI9341_AS8::pushColors(unsigned char*, unsigned char)'
/Users/xxxx/ILI9341_draw_bitmap_v2.ino:405: undefined reference to `Adafruit_ILI9341_AS8::pushColors(unsigned char*, unsigned char)'
collect2: error: ld returned 1 exit status
Error compiling.

In the Adafruit_ILI9341_AS8.cpp file, you have commented out the function

void Adafruit_ILI9341_AS8::pushColors(uint8_t *data, uint8_t len).

The .ino file makes this call:

// Here we are sending a uint16_t array to the function
tft.pushColors(tftbuffer, tft_ptr);

tftbuffer is uint16_t:

uint16_t tftbuffer[BUFF_SIZE];

So there should not be an issue with the commented out public function.

This is with Arduino 1.6.5 and also Arduino 1.0.6, so it's probably not a GCC version issue.

4 replies

Hi, I hacked the library together rather quickly as I bought on of those UNO displays. Unfortunately I never got around to testing some functions like pushColors...

I found the issue. You left off the * from the data in

void Adafruit_ILI9341_AS8::pushColors(uint8_t *data, uint8_t len)

Corrected:

// This is the byte array version for 16 bit raw images.
void Adafruit_ILI9341_AS8::pushColors(uint8_t *data, uint8_t len) {
uint8_t hi, lo;
CS_ACTIVE;
CD_DATA;
while(len--) {
hi = *data++;
lo = *data++;
write8(hi);
write8(lo);
}
CS_IDLE;
}

Ha! It may compile, but it will never work on my "mcufriend 2.8" display. The SD card is wired up completely wrong. I may be able to cut the traces and solder directly to the pins of the SD card slot and the 74vhc245 chip, but it's going to be micro-surgery.

I looked at my mcufriend shield and I can see that the SD Card slot is wired directly to the UNO pins with no 5v<>3.3V level translation. This has to be a design error in the shield... as you say some hacking will be needed.

Alternatively you could just buy a cheap SDCard module interface on eBay and wire that in. (search for "Arduino sdcard module"). These modules have the level translator and a regulator to power the SDcard.