Introduction: Arduino Analogue 'ring' Meter on Colour TFT Display

Picture of Arduino Analogue 'ring' Meter on Colour TFT Display

Yet another Arduino project for the display of sensor readings etc.

The example sketch included in the instructable includes the meter drawing function to use in your own projects, the function is not in a library so could be adapted for use with other graphics libraries. The meter drawing function has been "parameterised" so the meter size, position, range, units and colour scheme can be easily configured to suit your own needs.

Part of the inspiration for the development of the graphic was to have a similar style to the forthcoming Adafruit IO "Internet of Things" website.

The display is a 2.2" 320 x 240 pixel TFT colour display with the ILI9341 driver chip, this is driven by an Arduino UNO.

Step 1: The Meter Graphics

Picture of The Meter Graphics

The value displayed is shown as a bar graph that can be segmented or continuous. Larger values are shown as more segments being coloured in, thus the display gives an instant visual indication of a reading at a glance without having to read the numbers. The numerical value is shown in the center of the ring, a bit like the Google Nest display.

The colour of the ring segments can be set to change as the value increases, so this means a display showing temperatures can be set change from blue to red as the temperature increases. Another display for say a battery level could change from red for a low value, through yellow to green for a high value.

The meter position and size can be set as desired to make a meter arrangement that suits your taste. The sizes are set independently so more important information can be shown with a bigger graphic, or the display could cycle though several meters.

The unlit segments are dark grey (these segments look brighter in the images as I had to adjust the web cam settings to try to capture the display colours.)

The displays are best for values that change slowly with time such as temperature and humidity etc.

Step 2: Hardware Configuration

The hardware setup is common to some of my other Instructables, it consists of the UNO, the 2.2" TFT display based on the ILI9341 driver chip and a set of libraries that are enhanced versions of the Adafruit GFX and ILI9341 libraries.

The libraries attached have been enhanced to give a much faster performance on an UNO using direct port access, other boards could be used by commenting out a #define and changing the the SPI pins.

The UNO is connected to the ILI9241 2.2" TFT display like this:

    • 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.

    I have included a couple of short (!) videos (rather poor quality...) showing the graphics speed using an UNO and hardware SPI. (These have had the long delay() intervals between each test screen removed from the sketch!)

    One video is the UTFT Demo running on a Mega board with a 16 bit parallel interface to the display. It is faster mostly because the 10,000 pixel plot test at the end has been changed so 30,000 16 bit random numbers do not need to be produced at the same time as plotting 10,000 pixels (generating 30,000 16 bit random values takes nearly 3 seconds so the UNO can really drive the display faster than it appears during that part of the test!)

    The "Sine wave" animation is limited mainly by the floating point maths involved and could be speeded up dramatically by using a simple Sine lookup table, that test would then be over in the blink of an eye!

    Step 3: The Meter Drawing Function

    Picture of The Meter Drawing Function

    Here is the function prototype:

    int ringMeter(value, vmin, vmax, x, y, r, "Units", scheme)

    The ringMeter function returns the x coordinate of the right hand side of the meter to aid placement of the next meter.

    value is the value to be displayed and plotted, integer values up to 4 digits are accommodated

    vmin is the minimum value to be plotted

    vmax is the maximum value to be plotted, thus vmin and vmax set the full meter range

    x and y are the coordinates of the top left corner of an imaginary box that contains the meter

    r in the outer radius of the ring in pixels, the minimum is about 52 before the text intrudes on the ring

    "Units" is the text string such as "Volts", "C" etc.

    scheme sets the colour scheme, there are some # define statements in the example that enumerate the settings available, others could be added:

    • #define RED2RED 0
    • #define GREEN2GREEN 1
    • #define BLUE2BLUE 2
    • #define BLUE2RED 3
    • #define GREEN2RED 4
    • #define RED2GREEN 5

    These different schemes set the colour change as the value grows from vmin to vmax, so for example in the following the colour scheme is change from Blue to Red as the value increases:

    ringMeter(reading,-10,50, xpos,ypos,radius,"degC",BLUE2RED);

    In this case a temperature reading is being plotted in the range -10 to +50 degrees C, as the value increases the segments turn from blue (cold!) to red (hot!) as shown in the picture.

    Step 4: Libraries and Sketch

    The ring meter sketch and the two libraries needed are in the attached zip file.

    Some fonts have been disabled in the "Load_fonts.h" file to save space in the compiled sketch. Fonts 2,4 and 6 are enabled.

    The "Adafruit_ILI9341_AS" library as provided here is optimised for the UNO and ATmega 328p microcontroller, so it is best to start with that device.

    To use with others such as the Mega the SPI pins in the sketch will need to be changed and also the #define F_AS_T line will need to be commented out in the "Adafruit_ILI9341_FAST.h" file found inside the "Adafruit_ILI9341_AS" library. When the line is commented out the ATmega328 specific code will not be used so the display updates will be 50% slower.

    Eventually I will add speed enhancing code for the Mega as that is likely to be the upgrade path for projects that use large font files!

    The libraries and sketch were really developed for my own use and hence may have a few rough edges... but it works for me! If you have problems then report them below and I will try to help... given time!

    Warning: This version of the "Adafruit_GFX_AS" has NOT been tested with the other display libraries (S6D02A1 and ST7735) in my other instructables. So please keep a copy of your old library in case this one has an incompatibility! I will be adding compatible hardware drivers to this instructable at some point...

    Lastly, there is a comment at line 121 in the sketch describing how to turn a continuous ring into a segmented one.


    Bodmer (author)2015-04-04

    Following on from FabioB3's comment, I have run the Adafruit "graphicstest" sketch under the original Adafruit_GFX library and my enhanced version. The results are quite interesting:

    The speed has been increased to an average of 2.3 times faster. This is an equivalent boost to running a 16MHz UNO at 36MHz!

    Of particular note is the "line", triangle outline and circle outline drawing speed boost. This is because the Bresenham algorithm has been enhanced to take advantage of the way the display hardware has to be driven. The line drawing speed increase is the equivalent of running an UNO at 88MHz.

    See attached table of results.

    Mery YC (author)Bodmer2015-10-12

    Hi, Bodmer

    Congratulations again for your projects. The truth is that they are something that I always had in my mind. I wanted to ask for your help again, I'm interested in displaying data in the wattmeter display through input "A0", because in your sketch, the indication is simulated by a sinusoidal signal. It's posible?

    BODMER thank you very much, I hope your response as you have always done, congratulations !!!!

    Bodmer (author)Mery YC2015-10-13

    Try code like this:

    reading = analogRead(A0);

    Then change the calling function to, for example:

    ringMeter(reading, 0, 1023, xpos, ypos, radius, "W", GREEN2RED);

    Mery YC (author)Bodmer2016-09-02

    Hi, Bodmer, All Good?

    Can you help me again? I am trying one of the examples to make a voltmeter with of your ring put and it would need to visualize a precision value in the center of the display (the information her provides a converter ADC 24Bits "LTC2400") I have the code to monitor the readings of the LTC2400 but only it does it across ARDUINO's serial monitor, but it wanted to visualize it in the own display. Can you help me?

    Mery YC (author)Bodmer2015-10-14


    Punyviking (author)2015-03-18

    This is just what I needed! Looking forward to try it out as soon as you have fixed the problems!
    Do you know if it works with the 1.8 inch display to?

    Bodmer (author)Punyviking2015-03-18

    Working now!

    The 1.8" drivers probably will not work with the Adafruit_GFX_AS library version attached to this instructable, but...

    The sketch uses standard library function calls so should work with the drivers and Adafruit_GFX_AS library from my instructable here:

    Let me know is it works. I will be updating this instructable with updated drivers, which display do you use?


    medwar65 (author)Bodmer2017-09-13

    This is an awesome library! Do you know how I could adapt it to use with an Adafruit Feather M0?

    LukeC45 (author)2017-07-28

    hi bodmer

    love your work, im try merge with my energy monitoring system reads solar, batterys, logs to sd card with rtc and dht22

    but just doing test with with dht22 sensor and with 5 gauges im getting black triangles flashing on screen, just below half way all the away across

    insanoff (author)2017-06-12

    Worked from first try. Thank you for sharing your knowledge! I can now easily learn create gauges by modifying it.
    My setup:
    Arduino Pro Mini
    2.4" 240x320 TFT display

    KarthickR24 (author)2017-06-06


    I am using standalone Atmega328p-AU (SMD, 32 pin,-MLF) with the tft LCD 2.2" display ( At first, I tried your program on UNO board and it works fine. But, my own board not using the hardware SPI to interface with display because hardware SPI is busy with other processes. Therefore I use following digital pins to interface with LCD and tried to invoke custom library, however, I failed several times and that is why I am here..

    My pin connections are following

    #define sclk 9 // equivalent to UNO SMD version pin map

    #define miso 8

    #define mosi 7

    #define cs 6

    #define dc 4

    #define rst 3

    Adafruit_ILI9341_AS tft = Adafruit_ILI9341_AS(cs, dc, mosi, sclk, rst, miso); // Invoke custom library


    undefined reference to `Adafruit_ILI9341_AS::Adafruit_ILI9341_AS(signed char, signed char, signed char, signed char, signed char, signed char)'

    collect2.exe: error: ld returned 1 exit status

    Please help me to find where I am wrong or How to modify the library to make it work.

    Thanks in advance for your efforts!

    preemax made it! (author)2016-09-02

    i made it ,

    lcd 3.95 - mega2560

    KazafY (author)2015-07-23

    This is a great project that suit perfectly what I intended to do! However, the problem is that my display is not using the SPI connection. But the one with 8 data lines + 4 lines for the touchscreen...

    I have tried to modify the original library from Adafruit by implementing the functions from yours but no luck... any idea on how to get it works?

    Bodmer (author)KazafY2015-07-24

    Can you provide a link to the display details, I may have a library version that supports that display.

    KazafY (author)Bodmer2015-07-24

    I appreciate your reply :) The display is exactly the same the one from this post:

    I think it is similar to the old version of adafruit TFT display. Also the library which I was using was modified from adafruit and forced it to use ILI9341 driver.

    Thank you again !

    (For the display pinout, you can find it here:

    Bodmer (author)KazafY2015-07-26

    Try the libraries attached. I can't promise it will work though! These displays often have different drivers fitted to those advertised.

    TimC125 (author)Bodmer2016-05-25

    What do I do with these libraries? After I unzip them and add to the libraries folder I delete the original include GFX and ILI19341 lines in the Ring sketch and compile but I get errors. I can load and run the examples from the libraries though. Thanks a lot for the help.

    TimC125 made it! (author)TimC1252016-05-25

    Never mind. I got it working. Thanks for the great instructable. Attached is the updated sketch that works with the cheap eBay/Amazon 2.8 TFT shields.

    KazafY (author)Bodmer2015-07-26

    Thank your very much! It works like a charm! I have just run the ring meter program and it works properly. Also, the graphtest runs a little bit faster than the original libraries. (The UTFT demo has taken 11782ms to complete the sequence) Now lets see if I can make a speed meter for my bicycle :P

    Bodmer (author)KazafY2015-07-26

    That was lucky ;-)

    GerardoM1 (author)2016-03-17

    Hello, I bought this TFT:

    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!



    Bodmer (author)GerardoM12016-04-09

    Try my library here:

    ih82lose made it! (author)2016-02-24

    Thank you for posting this project. I am excited about getting to use the display to view battery voltages on a pack containing three 12V batteries. I have been able to set it up to display the voltages using a voltage divider circuit for each battery, but I was hoping to get some help in getting the displayed value set to a float. Ideally, I would like xx.xx resolution in the voltage readings. I have attached the sketch. I am new to this, so any help would be greatly appreciated.

    Bodmer (author)ih82lose2016-03-14


    I added plotting floats for Mery YC, see Mery_YC.ino example attached to my reply below. You will need to use the library here.

    Mery YC (author)2015-12-07

    Hi BODMER,

    I want to thank you for sharing your knowledge with others. can you help me ? I need to show the numerical values within the rings to two decimal places "x.xx" for example. We appreciate it greatly.Best Regards.

    Bodmer (author)Mery YC2015-12-08

    Locate this line:

    dtostrf(value, len, 0, buf);

    This is a C function converts a number to a string. Change the 0 to 2 as in this line:

    dtostrf(value, len, 2, buf);

    This will then put 2 decimal places in the string. More information on the dtostrf() can be found with a Google search.

    Mery YC (author)Bodmer2015-12-09

    Hi, BODMER,

    Thank you very much for the quick answer. I made the modification that you have shown me in the sketch but always indicate the two digits "00" and do not vary. What can be?

    Bodmer (author)Mery YC2015-12-09

    That's because the function to draw the ring meter accepts an integer value. You will need to modify it to accept a float type, or scale the value turning it into a float type within the function...

    Mery YC (author)Bodmer2015-12-10

    Hi, BODMER, thanks for your response. You can help? I do not understand programming.Thanks a lot..

    Bodmer (author)Mery YC2015-12-10

    OK, what are you trying to display?

    For example, are you getting an ADC reading and scaling it to a value that will have 2 decimal palces? If so what is the scale factor?

    Mery YC (author)Bodmer2015-12-14

    Hi BODMER, voltage need to show two decimal places. The scale will be up 35Vd.c (0Vdc to 35Vd.c). We will use the analog input A0. If you need more information, please do not hesitate to ask. Thanks a lot BODMER.

    Mery YC (author)Mery YC2015-12-15

    The resolution may be 0,01 but is possible 0,05, BODMER. Thanks

    Bodmer (author)Mery YC2015-12-15

    OK, in the main loop call the function with a line like:

    ringMeter(reading, 0, 1023, xpos, ypos, radius, "V", BLUE2BLUE);

    Where the reading is the analogue input value, this will be in the range 0 - 1023.

    In the ringMeter(...) function you need to modify some lines at the end to convert the value to a floating point number like this, where the lines I have changed are in bold text.

    float voltage = value/29.2286; // Convert to a float number in range 0- 35
    // Print value, if the meter is large then use big font 6, othewise use 4
    if (r > 84) {
    tft.setTextPadding(5*27 + 15); // Allow for 3 digits each 27 pixels wide
    tft.drawFloat(voltage, 2, x, y, 6); // Value in middle
    else {
    tft.setTextPadding(5*14 + 7); // Allow for 3 digits each 14 pixels wide
    tft.drawFloat(voltage, 2, x, y, 4); // Value in middle
    Mery YC (author)Bodmer2015-12-16

    Hi BODMER, when I modify the SKETCH with this changes, It indicates "'class Adafruit_ILI9341_AS' has no member named 'setTextDatum' when it is verified.

    THANKS A LOT ;-).

    Mery YC (author)Mery YC2015-12-16

    I can send you my sketch in some form so you can see. So you can see what I want to do. You think?. Thank you.

    Bodmer (author)Mery YC2015-12-16

    Sure, I think you can send it via a personal message, or post it here by using the "Add images" button and uploading the sketch file.

    Mery YC made it! (author)Bodmer2015-12-17

    Hi, BODMER,this is my sketch. It is a Electronic Dummy Load project.Thanks a lot for your support ;-)

    Bodmer (author)Mery YC2015-12-21


    Updated sketch is attached. This must be used with the library here. Use the Download Zip button on that web page. Save it in your library folder and edit name to TFT_ILI934

    Inside that library folder modify the User_Setup.h file to comment out all fonts except 1, 2, 4. The pins are already setup correctly.

    This new library has extra functions to center the text and numbers and to blank out old values. These new functions are used in the updated sketch.

    Mery YC (author)Bodmer2015-12-22

    Hi, BODMER, as always so attentive and eager to help others. I want to give thanks once again as you've always helped me what you have requested. Thanks for sharing your knowledge and time spent with us all. I would like to contribute in any way to your work time and so I would ask you to tell me, that way I can contribute or help. HAPPY 2016 in the company of your family !!!

    Bodmer (author)Mery YC2015-12-23

    Glad to help, good luck with your project.

    Mery YC made it! (author)Bodmer2015-12-17

    Hi, BODMER,this is my sketch. It is a Electronic Dummy Load project.Thanks a lot for your support ;-)

    Mery YC (author)Mery YC2015-12-17

    forgive me for many sends.... :-(

    Mery YC (author)Bodmer2015-12-17

    Hi BODMER, this is my code "Electronic Dummy Load" project. Thanks a lot for your support.

    Mery YC (author)Bodmer2015-12-17

    Hi BODMER, this is my code "Electronic Dummy Load" project. Thanks a lot for your support.

    Bodmer (author)Mery YC2015-12-16

    Ah, yes. I am using a later version of the library with a new function, sorry!

    Incidentally you might like to try that library. You can find it here.

    Mery YC (author)Bodmer2015-12-17

    Thanks a lot BODMER

    RobertoV1 (author)2015-11-24

    How you made working parallel display with mega 2560?

    RobertoV1 (author)2015-11-08

    Thank you a lot!

    for (int i=0; i <= 255; i++){



    This finally made my display (1.4" tft, il9341) work!

    MikeD15 (author)2015-10-05

    Would this work with a ILI9163C (128x128) 1.44" Display? If so, how would I go about modifying it to do so? Great work by the way.

    Bodmer (author)MikeD152015-10-06

    The ILI9163C will not work with this code, the library would not configure the display properly. It may be possible to adapt the library but I do not have a display with that driver chip, so unfortunately I cannot help you.

    About This Instructable




    More by Bodmer:Arduino - TFT display of icons and images from FLASH memoryArduino - TFT display of bitmap images from an SD CardArduino analogue 'ring' meter on colour TFT display
    Add instructable to: