t r o n i x s t u f f

fun and learning with electronics

Tutorial: Arduino and TFT LCD

This is chapter twenty-nine of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe.

The first chapter is here, the complete series is detailed herePlease note that the tutorials are not currently compatible with Arduino IDE v1.0. Please continue to use v22 or v23 until further notice. 

Welcome back fellow arduidans!

Today we continue with experimenting with colour LCD units. In this article we will get started with a very clear and sharp unit – the 4D Systems 1.44″ TFT serial interface LCD:

The LCD is an LED-backlit thin-film transistor type, resolution is 128 x 128 pixels, with an RGB colour range of 65536.

As an aside, this is a very powerful piece of hardware. The module not only contains a 1.44″ square TFT LCD, there is also a dedicated graphics processor and a microSD card interface. One can program the display processor in the same manner as another microcontroller platform for incredibly interesting results. For more information, please visit here.

However in the spirit of keeping things simple, this article will focus on driving the LCD directly using our Arduino or compatible boards. There are two firmware versions of this module – the GFX and the SGC. We need to have the SGC firmware, as this allows control via the serial TX/RX pins from our Arduno board. If you have purchased the SGC module, you’re ready to go. Scroll down until you see “And we’re back…”. However if you have the GFX version, please read the following instructions on how to change your LCD’s firmware from GFX to SGC…

Changing the firmware from GFX to SGC

  • At the moment this process only seems available to users of Microsoft Windows. All complaints to 4D Systems.
  • Unfortunately this process may not work with an Arduino Mega board.
  • First of all, remove the ATmega328 from your Arduino board. Please be careful, use a chip puller if possible. We are going to use the board as a simple serial-USB converter;
  • Insert your LCD module into a solderless breadboard;
  • Connect Arduino pin 0 (RX) to display pin 7 (RX); connect Arduino pin 1 (TX) to display pin 8 (TX). [Yes - TX>TX, RX>RX];
  • Connect Arduino 5V to display pin 9; connect Arduino GND to display pin 6; your LCD should display the following:

  • Visit here, download and open the PmmC Loader application; visit here and download the .pmmc file to your local drive;
  • Connect your Arduino board via USB to the computer; then run the PmmC loader application;
  • Select the appropriate COM: port, load in the .pmmc file, then click Load. The firmware update should take less than sixty seconds;
  • When finished, you will be presented with the following on the computer:

… and the following on your LCD:

  • At this point unplug the USB lead from your Arduino board and all leads into the Arduino board;
  • Re-insert the ATmega328 back into your Arduino board;
  • Reconnect the wires from the LCD module to the Arduino, but this time connect Arduino TX to LCD RX; and LCD TX to Arduino RX.
  • Now you have  the serial-interface SGC firmware model LCD.

And we’re back…

To control this LCD, it requires commands to be sent via Serial.write(), and such commands are in the form of hexadecimal numbers. (You see something new every day). You can download the reference book with all the commands: SGC Commands.pdf and bypass the library by directly writing the hexadecimal numbers directly to the module.

However, to get up to speed as fast as possible we can use a library with more of the popular functions included. Kudos and thanks to Oscar Gonzalez for writing a very useful library. Download the library from here and install into your ../Arduino-002x/libraries folder, then re-start the Arduino IDE if you had it running. You may be wondering why the library is named displayshield4d - the LCD manufacturer sells this LCD on an Arduino shield. Although that would be great for experimenting, one would need to purchase another standalone LCD if their project moved forward – myself included. So that’s why we’re using the bare LCD board.

To connect the LCD to our Arduino is very simple:

  • LCD pin 5 to Arduino RST;
  • LCD pin 6 to Arduino GND;
  • LCD pin 7 to Arduino D1;
  • LCD pin 8 to Arduino D0;
  • LCD pin 9 to Arduino 5V.

In the following examples we will demonstrate the various functions available in the library. As this is chapter 29, (when will this stop?) I will no longer explain the more basic functions or ideas that you should know by now, instead relying on comments within the sketch if it feels necessary. It can take a short moment for the LCD controller to process, so always put a short delay between functions.

When uploading a sketch to your Arduino you may need to disconnect the LCD from Arduino D0/D1 as it can interfere with the serial process.

Firstly we will demonstrate text display. Initialising the display requires a few functions:

#include <displayshield4d.h> // include the LCD library
DisplayShield4d  lcd;

The second line creates an instance of lcd to be used with the relevant functions. Next, within void setup():

Serial.begin(115200);  // LCD speed is very high
lcd.Init(); // wake up LCD
lcd.Clear(); // clear the LCD, set background to black

To write text to the LCD, the following function is required:

lcd.setfontmode(OLED_FONT_TRANSPARENT);  // set font background type

This line sets the font transparency. If we use the parameter OLED_FONT_TRANSPARENT the unused pixels in the character area will be transparent and continue to show what they were set to before the text was over-written with. You can also use OLED_FONT_OPAQUE, which blocks the item displayed “behind” the text.

Whenever a function requires a colour parameter, we use:

lcd.RGB(x,y,z);

where x, y and z are numerical values (between 0 and 255) for the red, green and blue components of the required colour. If you need an RGB numerical reference, download this handy chart. Finally, to display some text we use the following:

lcd.drawstringblock(a, b, c, lcd.RGB(255, 255, 255), d, e, "Hello, world");

The parameters required are:

  • a – the x-position of the first character. E.g. if this was a zero, the top-left pixel of the first character would be on the left-most pixel column of the LCD;
  • b – the y-position of the first character. e.g. if both a and b were zero, the text would start from the top-left of the LCD;
  • c – numerical code for the font to use: 1 is for 5×7 pixel characters, 2 for 8×8 and 3 for 8×12;
  • the three values within the lcd.RGB() function determine the colour of the text;
  • d – x-axis resolution multiplier. E.g. if you double this and use the 5×7 font, the characters will be double-width;
  • e – y-axis resolution multiplier.

Now let’s see this in action with the following sketch:

Example 29.1

/*  Example 29.1 - uLCD-144 text demonstration
http://tronixstuff.com/tutorials > chapter 29  CC by-sa-nc  */
#include <displayshield4d.h> // necessary library
DisplayShield4d  lcd; // create an instance of the LCD
void setup()
{
Serial.begin(115200);  // LCD speed is very high
lcd.Init(); // wake up LCD
delay(20);
}
void loop()
{
lcd.Clear(); // clear LCD
delay(20);
lcd.setfontmode(OLED_FONT_TRANSPARENT);  // set font background type
delay(20);
for (int a=0; a<128; a+=8)
{
lcd.drawstringblock(0, a, 2 , lcd.RGB(255, 0, 0), 1, 1, "visit me");
delay(20);
}
delay(2000);
lcd.Clear();
for (int a=0; a<128; a+=16)
{
lcd.drawstringblock(0, a, 0, lcd.RGB(0, 255, 0), 2, 2, "0123456789");
delay(20);
}
delay(2000);
lcd.Clear();
delay(20);
for (int a=0; a<128; a+=32)
{
lcd.drawstringblock(0, a, 0, lcd.RGB(0, 0, 255), 4, 4, "Great");
delay(20);
}
delay(2000);
}

And a short video clip of the example in action:

As you can see the display update speed is much better than the LCD from the previous chapter. Although this example was short, don’t be afraid to try out your own parameters in the example sketch.

Next we will demonstrate the various graphics functions in the library. Creating graphics isn’t rocket science, it just takes some imagination (something I admit to lacking) and following the parameters for each function. Our first is

lcd.putpixel(x,y,lcd.RGB(r,g,b));

which places a pixel on the screen at location x,y of colour described using lcd.RGB(). Next we have

lcd.line(x1,y1,x2,y2,lcd.RGB(r,g,b));

which draws a line from x1, y1 to x2, y2 of colour rgb. One can also create rectangles and so on using

lcd.rectangle(x,y,l,h,z,lcd.RGB(r,g,b));

This will create a rectangle with the top-left point at x,y; width is l pixels, height is h pixels, and a new parameter z. If z is 0, the function will draw a solid shape, if z is 1, it will display only a wire-frame rectangle with a pixel width of one. Circles are created using

lcd.circle(x,y,r,z,lcd.RGB(r,g,b);

where x and y are the coordinates for the centre of the circle, r is the radius, and z is the solid/wireframe parameter. And finally – triangles:

lcd.triangle(x1,y1,x2,y2,x3,y3,z,lcd.RGB(r,g,b));

This will draw a triangle with the corners at the coordinate parameters; z again is the solid/wireframe parameter. However you need to order the corners in an anti-clockwise order. This will become evident in the example sketch below.

Example 29.2

In this example we run through the graphical functions described above. By following through the sketch you should gain an idea of how the graphical functions are used, in order to create your own displays.

/*  Example 29.2 - uLCD-144 graphic library demonstration
http://tronixstuff.com/tutorials > chapter 29  CC by-sa-nc  */
int a,b,c,d,e=0;
#include <displayshield4d.h> // necessary library
DisplayShield4d  lcd; // create an instance of the LCDvoid
setup()
{
randomSeed(analogRead(0));
Serial.begin(115200);  // LCD speed is very high
lcd.Init(); // wake up LCD
delay(50);
}
void loop()
{
lcd.Clear();
delay(50);
for (int z=0; z<2500; z++)
{
a=random(127);
b=random(127);
c=random(255);
d=random(255);
e=random(255);
lcd.putpixel(a,b,lcd.RGB(c,d,e));
delay(50);
}
delay(1000);
lcd.Clear();
delay(50);
for (int z=0; z<64; z++)
{
lcd.line(0,0,127,z*2,lcd.RGB(0,255,0));
delay(50);
}
for (int z=0; z<64; z++)
{
lcd.line(0,0,z*2,127,lcd.RGB(0,0,255));
delay(50);
}
delay(1000);
lcd.Clear();
delay(50);
for (int z=0; z<15; z++)
{
lcd.rectangle(z*10, z*10, 20, 20, 1, lcd.RGB(255,0,0));
delay(250);
lcd.rectangle(z*10, z*10, 20, 20, 0, lcd.RGB(0,0,255));
delay(250);
lcd.rectangle(z*10, z*10, 20, 20, 0, lcd.RGB(0,0,0));
delay(250);
}
delay(1000);
lcd.Clear();
delay(50);
for (int z=0; z<14; z++)
{
lcd.circle(63,63,z*3, 1, lcd.RGB(0,0,255));
delay(250);
lcd.circle(63,63,z*3, 0, lcd.RGB(0,255,0));
delay(250);
lcd.circle(63,63,z*3, 0, lcd.RGB(0,0,0));
delay(250);
}
delay(1000);
lcd.Clear();
delay(50);
for (int z=10; z>-0; --z)
{
lcd.triangle(127,127,64,z*10,0,127,1,lcd.RGB(0,255,0));
delay(250);
lcd.triangle(127,127,64,z*10,0,127,0,lcd.RGB(0,0,255));
delay(250);
lcd.triangle(127,127,64,z*10,0,127,0,lcd.RGB(0,0,0));
delay(250);
}
}

And here is the video of example 29.2 in action … brought to you by Mr Blurrycam:

So there you have it, another useful part and a very nice colour LCD to make use of.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

February 18, 2011 - Posted by | arduino, education, LCD, learning electronics, microcontrollers | , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

24 Comments »

  1. Another great tutorial, can’t wait to get my hands on one of those :)
    Thank you!

    Comment by Primadeluxe | February 18, 2011 | Reply

  2. Hi John.

    Many thanks for the tutorials – fabulous work!
    Wondering if might have a few moments to suggest what I might be doing wrong with your first sketch?
    (btw, I changed the line: lyd.drawstringblock(0, a, 0, lcd.RGB(0, 255, 0), 2, 2, “0123456789″); – as I think ‘lyd’ might be ‘lcd’)
    So I’m running Arduino 0022 (Mac OSX) with an Arduino pro. Your sketch compiles and uploads fine, the connections to the uLCD are triple checked = correct, however, after the initial reset, the 4D Systems splash screen writes fine, but then remains – no ’123456789′ – I’ve looked at the datasheet too, but can’t figure if I’ve missed anything… any suggestions much appreciated

    – keep up the good work mate,
    Rich.

    Comment by Rich Carthew | May 21, 2011 | Reply

    • Hi Rich
      Thanks for picking up the type :)
      Silly question, have you changed the firmware from GFX to SGC? I realise you have a Mac and finding a Windows machine :| is a pain, but it is necessary.
      cheers
      john

      Comment by John Boxall | May 22, 2011 | Reply

      • Hi John,
        Thanks for following up. I bought the module pre-loaded with the SGC firmware, so no worries there. (I also have Win 7 & XP PC’s – lucky me right ;-) So, I tried the whole lot again on an Win XP system and it now works great! As an aside, I’m not sure if it makes a difference, but after successful .pde upload from PC to the Arduino 328, I hit the Aduino’s reset button = voila! cheers, Rich

        Comment by Rich Carthew | June 2, 2011

  3. I have a strange situation. I am trying to find replacement for 1.8″ qcif tft lcds used in mobile phones. Because original supplier went out of business, I can not find exact module in the market. it is interfaced with sc6600L (arm7tdmi board). I have the firmware. Is it possible to find the pinouts of the board from the firmware? Would this information be helpful to find the replacements? I need about 100 of these and I am not very technical. Any help will be appreciated.

    Comment by Bal K Paudyal | May 28, 2011 | Reply

    • If you had the source code for the firmware you might be able to work it out, but it would be somewhat complex. If you just wanted the LCDs try http://www.4dsystems.com.au; otherwise if you were replacing LCDs in mobile phones I would just buy new phones.

      Comment by John Boxall | May 28, 2011 | Reply

  4. Hi John -A follow-up to my earlier June 2 comment: When uploading a sketch, I need to temporarily disconnect either the TX, RX (or both)lines from the uLCD to upload a .pde, then reconnect lines and hit ‘reset’ btn = good. I suspect this may be simple to resolve, but unsure how – is it conflicting serial timing or perhaps port assignment in the library? – little out of my depth on this one!
    Cheers, Rich.

    Comment by Rich Carthew | June 2, 2011 | Reply

    • The serial end of the USB converter on an Arduino is wired to the d0/1, so if something is connected to serial while attempting to upload a sketch sometimes it needs to be disconnected during the upload process.
      Cheers
      John

      Comment by John Boxall | June 2, 2011 | Reply

  5. Aha! Interesting, thanks. So then it seems that I should take precautions when dedicating D0 & D1 pins (like adding a physical bypass switch) to the tx/rx uLCD lines when intending to hardwire an arduino bootloaded AVR into a sculpture if I intend on updating the sketch. Very good to know prior to making the work. Awesome! Cheers, Rich.

    Comment by Rich Carthew | June 2, 2011 | Reply

  6. Hey there !
    I’m sorry if this is the wrong place to ask. I’m looking for an example of plotting a graph of some logged data on a screen. Can you help me or point me somewhere I can find inspiration ?
    In my particular case, I have the 2,8″ tft touch screen from adafruit and I haven’t seen any help in their library (ok, except logging data and then re-calculate the position of each pixel and then draw pixel-by-pixel).
    Cheers !

    Comment by Christophe C. | July 17, 2011 | Reply

    • All the projects I have seen that plot data in such a way do it pixel-by-pixel. Perhaps ask in the adafruit support forum.
      Cheers
      John

      Comment by John Boxall | July 18, 2011 | Reply

  7. Hi John,
    I was just trying to change the firmware from GFX to SGC like you described it, but apparently I can’t get it to load the SGC firmware. I’m running it on a Windows 7, set it all up correctly, even got the green screen about the GFX v2.0. However when I open PmmCLoader, choose the port, browse the file and hit load, it just returns me a “Waiting for device” forever… and I get no progress at all in the status bar. I noticed the RX led blinks on my arduino though. Any idea of what should be the problem?
    Cheers,
    Vini.

    Comment by Vini | September 26, 2011 | Reply

    • Sorry – have to ask – did you remove the ATmega328 from your Arduino first?
      If it still doesn’t work, check your wiring, and try another USB port or another computer if possible.

      Comment by John Boxall | September 27, 2011 | Reply

      • Yes, I did! Tried different USB ports, and even on a Windows Vista too, but still no good… Thanks for the reply, anyways!

        Comment by Vini | September 27, 2011

      • No worries. Wouldn’t hurt to ask 4D Systems – http://www.4dsystems.com.au/contact.php

        Comment by John Boxall | September 27, 2011

      • Hey John, I figured it out, man! I just had to connect LCD Pin 5 to Arduino Reset and it worked! You should add that to your tutorial as well! Another important thing I can point out: it didn’t worked with the uLCD-144SGC-R17.pmmc firmware. Then I tried the new driver uLCD-144rSGC-R17.pmmc(Portrait), and that solved my problem! All good now, thanks a lot! Would you happen to have any example that loads images on a SD card and shows it on the LCD? Cheers!

        Comment by Vini | September 28, 2011

      • Glad to hear you had it working. Afraid I gave away my LCD so cannot experiment with it any more with regards to the image>LCD. Pretty sure you would need to run the LCD in the GFX mode to do so :|
        cheers
        john

        Comment by John Boxall | September 29, 2011

  8. Hello;

    I’m trying to configure with my arduino uno but it dosen’t works, loader says “Waiting for device”. I’ve tried all this:
    - Remove Atmega382
    - Connect Reset cable to display
    - I’ve tried in windows vista and windows XP
    - Change TX and RX cables
    - Transform TX and RX signals to 3.3V

    Never of this works.

    Please, somebody can help me?

    Thanks

    Comment by ilausuch | January 20, 2012 | Reply

    • Sorry to ask, but did you connect Arduino GND to display pin 6? A lot of people seem to forget this bit.

      Comment by John Boxall | January 21, 2012 | Reply

  9. Nice article! I have a small question though:

    I loaded the pmmc and everything but i can’t get the http://tronixstuff.files.wordpress.com/2011/02/aftersgcss.jpg screen! I only get the white screen….

    Do you know how to fix this?

    Comment by Niek | January 21, 2012 | Reply

    • Sorry, not sure about that. As always, double check your wiring and if connected properly perhaps you have a faulty screen. Contact your retailer.

      Comment by John Boxall | January 23, 2012 | Reply

  10. First let me say I am very glad to have found your blog. This is the second post that I have found immensely useful. I am having a problem with the 4D library probably because I am using v1.0.

    However, I am lucky enough to have VS installed on my development machine so I was able to use your example code and the actual library to hash out how to correctly send data to one of these displays. I am using this display to develop with. On another one of yor posts, I am throwing questions at you that will let me translate to a much cheaper display. I just happened to already have this one.

    I have been using it for awhile as well as one of their 2.4″ Touch displays and have gone back and forth between GFX and SGC several but, while successful in their ‘native’ IDE, I have never been successful getting this to work via serial until now.

    A quick couple of pointers to any that come behind me. If you are having trouble changing the PMMC from GFX to Serial, in the past I have had to quickly reset the DTR line manually to get it to program. I didn’t have to do this this time but it has worked in the past.

    Also, since I could not use the library, I got really, really confused about the RGB conversion to that two byte hex number. I eventually found a decent descrption of how this works using 565 conversion. In the process I found a great quick converter that will give you both the HEX and Binary result of your RGB numbers. Since I got stuck I thought I would share for anyone else.

    In the library, it takes the value you enter for Red, Blue, and Green and converts them to 5,6,5 bit numbers respectively. This is done using a basic relationship. as follows:

    255 is to 255 as x is to 31. 31 is the largest number you can have with 5 bits (31 = 11111 Binary). So using basic algebra, this gives the following equation:

    red5bit = (Red * 31)/255

    The exact same math and logic behind the math is used for the Blue value so that:

    blue5bit = (Blue * 31)/255

    For green, a 6 bit number is used. Apparently the human eye is much more accurate when determining various shades of green than any other color so the extra bit is used to accomodate for this. The largest 6 bit number you can have is 63. (63 =111111 Binary) So using the same math as above:

    green6bit = (Green * 63)/255

    This is exactly what the library is doing. I just didn’t understand it at first.

    So once each of those values is determined, they are shifted into the final variable like so:

    color = (red5bit << 11) | (green6bit << 5) | blue5bit

    So now you have a 16bit number representing the RGB values that you need.

    Here is a real world example:

    if my RGB numbers are (231,231,231) I will end up with the following numbers: (28,57,28). Using a converter, I end up with the following binary:

    11100 111001 11100. The spaces are simply to show the 565 bit relationship. So these 3 values are mashed together to form a single 16bit number.

    It is then split apart into two 8bit bytes. This yields E7 and 3C. These are the values that are sent to the dispaly to determine color!

    Yeah!

    Obviously hashing and sending the two bytes is handled automatically in code but this is why it works the way it does.

    One last pointer and I will quit hijacking: If it appears that your display is not doing anything, send it a simple change background and change it to white (42,FF,FF). This is the simplest thing to do and it will tell you quickly if your display is responding correctly. And before you can write text, you must select a fontmode as in transparent or opaque.

    I really hope this is useful info. and I look forward to reading more of your posts!

    Thanks,

    Wade

    Comment by Wade | January 27, 2012 | Reply

  11. Thanks for sharing this tutorial. 4D Systems screens are great.

    I’ve developed a suite of libraries for Goldelox- and Picaso-based screen with serial connection for hardware, software and I2C ports, GUI with button, menu, dialog box —touch required—, graphics.

    Everything, including tutorial, code, examples, is here http://sg.sg/pyXBgx

    Enjoy!

    Comment by Rei Vilo | March 12, 2012 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 2,588 other followers