How to Use a Touchscreen with an Arduino
2022-01-05 | By Maker.io Staff
The first part of this three-part series discussed common touchscreen technologies and their typical use-cases. Then, the second part investigated a few readily available and affordable touch display options for makers and hobbyists. This article documents how to get started with one of the recommended Arduino-compatible 2.8” resistive touchscreens from part two.
This is the 2.8” resistive touchscreen I use throughout this article.
Connecting a Touchscreen to an Arduino
The TFT display I use contains a resistive overlay, which allows users to control an Arduino-based project with touch inputs. The display controller that comes with the touchscreen supports a few different communication methods. However, I’ll only outline two of them as I find these to be the most useful. The first method uses eight parallel communication lines to transmit pixel data from the Arduino to the display. I recommend using this method in multimedia applications where the Arduino needs to transfer a lot of pixel data.
Connect the Arduino as shown in the schematic to use the display in parallel mode. Note that the Arduino library this article uses requires you to wire eight communication lines exactly as shown. I omitted the touch-input lines in the schematic to keep it looking cleaner.
The second method involves using SPI to communicate with the display controller. Doing so saves a few digital I/O lines with the tradeoff of being slower than the parallel communication method. To enable the display’s SPI mode, you have to close these three solder pad jumpers on the bottom side of the board:
Use some solder to bridge the three highlighted jumpers on the underside of the TFT control board. Doing so connects the IM1, IM2, and IM3 lines to +3.3V.
Once you’ve done that, connect the display to the Arduino as shown in the following schematic diagram:
You can save a few connections when using the SPI method. This schematic diagram also shows how to connect the resistive touch overlay to the Arduino (X-, Y-, X+, Y+ pins).
Note that I used the SPI method to send data from the Arduino to the display. Either way, in addition to the pixel data lines, you’ll further need to employ two additional digital I/O lines and two more analog pins of the Arduino if you want to add resistive touch detection to your project. In addition, this touchscreen module comes with a built-in micro SD card reader I won’t discuss further in this article.
This image shows the complete test setup with the Arduino connected to the TFT display using the SPI method.
Sending Pixel Data to the TFT Display
You have to install two libraries before you can send image data to the TFT display. First, use the Arduino IDE’s built-in library manager to download the Adafruit ILI9341 library. This package handles low-level communication between the Arduino and the display controller IC. Then, download the Adafruit_GFX library. The second library contains helpful code for drawing graphics primitives such as simple shapes and text. I recommend you read this article if you don’t know how to use the library manager in the Arduino IDE.
Use the library manager to install the Adafruit ILI9341 and Adafruit_GFX packages.
Next, I used the following code snippet to test the display:
/* imports, defines, and variable declarations omitted */ void setup() { Serial.begin(9600); tft.begin(); screenRedrawNecessary = true; } void loop() { /* Touch input detection omitted. See below */ if(screenRedrawNecessary) { resetAndClearScreen(); drawIntroText(); drawTouchButton(b1[0], b1[1], b1[2], b1[3], "Previous"); drawTouchButton(b2[0], b2[1], b2[2], b2[3], "Next"); screenRedrawNecessary = false; } } void drawIntroText(void) { tft.setCursor(15, 15); tft.setTextColor(font_colors[active_colors]); tft.setTextSize(2); tft.println("Hello, World!"); tft.setCursor(15, 55); tft.println("Use the buttons below"); tft.setCursor(15, 75); tft.println("to change the background"); tft.setCursor(15, 95); tft.println("color!"); } void drawTouchButton(unsigned x, unsigned y, unsigned width, unsigned height, String text) { int x_text_pos = x + width / 2 - (text.length() / 2) * 11; int y_text_pos = y + height / 2 - 8; tft.drawRect(x, y, width, height, font_colors[active_colors]); tft.setTextSize(2); tft.setTextColor(font_colors[active_colors]); tft.setCursor(x_text_pos, y_text_pos); tft.print(text); }
This short test program first initializes the TFT display in the setup()-function. Then, I defined a few helper methods. The resetAndClearScreen()-method resets the display’s rotation and erases all previously drawn pixels. The next function is drawIntroText(). It prints a short status message in the top left corner of the display. Lastly, drawTouchButton() creates a rectangle at the specified position with the given width and height. Then, the method places a string at the center of the previously drawn rectangle. As the name suggests, I’ll later use these rectangles to detect user inputs. The loop()-method refreshes the screen twice a second. But because there’s no interactivity built into the program yet, users can’t change what the screen displays at this point.
Interpreting Touch Input
To use the resistive touch capabilities of this display, download the Adafruit_TouchScreen library using the Arduino IDE’s built-in library manager. The example code from above prints a few lines of text and then draws two touch buttons. Next, we’ll have to detect when a user presses one of the buttons. If that happens, the Arduino should refresh the screen and draw all the components using different colors. Therefore, I added the following method to detect whether a user touched one of the buttons:
/* Intro code omitted */ void setup() { /* Code omitted. Same as above. */ } void loop() { // Determine whether the user touched the display TSPoint p = ts.getPoint(); if (p.z > PRESSURE_THRESHOLD && !screenRedrawNecessary) { // NOTE: The touchscreen controller does NOT use the // screen coordinates! It uses its own coordinate system if(touchedWithin(p, 165, 100, 320, 450)) { active_colors -= 1; screenRedrawNecessary = true; } else if(touchedWithin(p, 175, 500, 330, 830)) { active_colors += 1; screenRedrawNecessary = true; } if(active_colors < 0) active_colors = 2; if(active_colors >= 3) active_colors = 0; } /* Draw functionality. See above */ } bool touchedWithin(TSPoint touch, unsigned x, unsigned y, unsigned w, unsigned h) { return (touch.x > x) && (touch.x < (w)) && (touch.y > y) && (touch.y < (h)); } /* Draw functions omitted. See above */
The touchedWithin()-function is easy to understand. The first parameter represents the coordinates of the detected input. Then, the helper method checks whether these x and y coordinates are within the button’s dimensions.
Before making the previously discussed calls to the various draw-functions, the loop() method also checks whether the user touched the resistive screen. The TSPoint class contains a z-value we can use to determine how hard a user pressed down on the screen. This z-value is also perfect for preventing the Arduino from detecting unwanted inputs. If the z-value is greater than a fixed threshold value, the Arduino detects a touch input. The code then calls the touchedWithin()-function to determine whether the user pressed one of the buttons.
Download the Code Snippets
You can download the example code here.
Summary
A closeup of the 2.8” resistive touch display.
Arduino-compatible touchscreens allow you to quickly add a touchscreen to your existing or new DIY projects. Simple-to-use libraries let you get the display up and running in practically no time. The screen I used offers a few ways for devices to send pixel data to it. A parallel interface allows you to achieve higher screen refresh rates, which might be essential in multimedia applications. The parallel interface is also perfect for MCUs with a large number of I/O pins. The SPI method, on the other hand, is a bit slower compared to parallel communication. It, however, allows you to cut down on the number of required I/O pins, which is the preferred option in most Arduino projects.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum