{"id":1751,"date":"2023-05-28T11:30:48","date_gmt":"2023-05-28T11:30:48","guid":{"rendered":"https:\/\/photobuilds.com\/?p=1751"},"modified":"2023-05-29T12:10:05","modified_gmt":"2023-05-29T12:10:05","slug":"using-the-st7735-tft-display-with-the-arduino-nano","status":"publish","type":"post","link":"https:\/\/photobuilds.com\/index.php\/2023\/05\/28\/using-the-st7735-tft-display-with-the-arduino-nano\/","title":{"rendered":"Using the ST7735 TFT Display with the Arduino Nano"},"content":{"rendered":"\n<p>In earlier Arduino based projects I&#8217;ve used two different monochrome LCD screens, but these were quite limited in their display capabilities. In the drop controller I went with the two line by 16 character LCD Keypad shield. This was very easy to integrate into the build physically, but did lack a little finesse. In the slightly more recent photogate trigger I used the <a href=\"https:\/\/amzn.to\/3OCqszM\" target=\"_blank\" rel=\"noopener\" title=\"\">Nokia 5110 display<\/a>. This has a resolution of 84 by 48 pixels and it can display more lines of text, or even rudimentary monochrome graphics.<\/p>\n\n\n\n<p>For my <a href=\"https:\/\/photobuilds.com\/index.php\/2023\/05\/09\/motorized-macro-rail-part-2\/\" title=\"\">macro rail project<\/a> I decided to up the ante and go for a colour screen, namely the <a href=\"https:\/\/amzn.to\/3OJvo5V\" target=\"_blank\" rel=\"noopener\" title=\"\">1.8&#8243; ST7735 TFT display<\/a>. This can display 160 by 128 pixels with 16-bit \u201cHigh color\u201d and can draw shapes as well as text. It also has an SD card socket on the back, although I&#8217;m not going to use this at present.<\/p>\n\n\n\n<p>The screen has a height of just over 3.5cm and a width of about 3cm. To me this raised the possibility of having four or five PCB mounted pushbutton switches up the side, aligned with text on the screen for menu item selection. I&#8217;m planning to control the macro rail with an <a href=\"https:\/\/amzn.to\/3ozsXZ2\" target=\"_blank\" rel=\"noopener\" title=\"\">Arduino Nano<\/a>, so this time I&#8217;ve done my test setup with a Nano rather than the obligatory Uno.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Started<\/h2>\n\n\n\n<p>In order to control the ST7735 with an Arduino there are a couple of libraries I had to add to the Arduino IDE: Adafruit ST7735 and Adafruit_GFX. These were added to the IDE via <em>Tools>>Manage Libraries&#8230;<\/em> With the libraries installed, a quick IDE restart had me ready to go:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"654\" src=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-1024x654.jpg\" alt=\"ST7735 TFT Display\" class=\"wp-image-1756\" srcset=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-1024x654.jpg 1024w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-300x192.jpg 300w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-768x491.jpg 768w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-1000x639.jpg 1000w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-230x147.jpg 230w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-350x224.jpg 350w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries-480x307.jpg 480w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/ST7735-Libraries.jpg 1263w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Hardware Connection<\/h2>\n\n\n\n<p>The next step was to connect the screen to the Arduino Nano: this only required five wires plus power. However, it&#8217;s worth noting that my test ST7735 is a 3.3 Volt unit. While the Nano can provide 3.3V power, the digital output pins are 5V. To protect the display I used 1K\u03a9 resistors in series with the five Arduino data lines.<\/p>\n\n\n\n<p>To make life very easy, the 7735 uses the SPI (serial peripheral interface) protocol to communicate with the Arduino. With Arduino, SPI can either be implemented in hardware or software. I decided to use the hardware option as it&#8217;s faster than software SPI, but has to use the board&#8217;s hardware SPI pins. For the Nano these are Pin 11 for MOSI and Pin 13 for SCLK. With software SPI it&#8217;s possible to assign your own pins, but unless there&#8217;s a particular need to use D11 and D13 for something else, I&#8217;m not sure I can see any benefit. <\/p>\n\n\n\n<p>The full set of connections from Nano to ST7735 is:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Arduino Nano<\/strong><\/td><td><strong>ST7735 TFT<\/strong><\/td><\/tr><tr><td>3.3V<\/td><td>Vcc<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><tr><td>D11<\/td><td>SDA<\/td><\/tr><tr><td>D13<\/td><td>SCL<\/td><\/tr><tr><td>D5<\/td><td>RES<\/td><\/tr><tr><td>D6<\/td><td>CS<\/td><\/tr><tr><td>D7<\/td><td>DC<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Pretty straightforward stuff: I wired mine up on a small breadboard to get me started quickly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">First Test<\/h2>\n\n\n\n<p>With the display connected to the Nano I needed a sketch to check that the display was actually working. Luckily Adafruit have provided a couple of useful ones that can be accessed in the IDE via <em>File&gt;&gt;Examples&gt;&gt;Adafruit ST7735 and ST7789 Library<\/em>. The best of these was called &#8220;graphicstest&#8221;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"555\" src=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-1024x555.jpg\" alt=\"ST7735 TFT Display\" class=\"wp-image-1759\" srcset=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-1024x555.jpg 1024w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-300x163.jpg 300w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-768x417.jpg 768w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-1536x833.jpg 1536w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-1000x542.jpg 1000w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-230x125.jpg 230w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-350x190.jpg 350w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest-480x260.jpg 480w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/graphicstest.jpg 1912w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>This pretty much does what it says on the tin, once a very minor mod has been made to it. Because I was using D5, D6 and D7 for RES, CS and DC respectively, these had to be reflected in the define statements (highlighted) at the start of the sketch:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"572\" src=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-1024x572.jpg\" alt=\"ST7735 TFT Display\" class=\"wp-image-1760\" srcset=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-1024x572.jpg 1024w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-300x168.jpg 300w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-768x429.jpg 768w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-1000x559.jpg 1000w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-230x129.jpg 230w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-350x196.jpg 350w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines-480x268.jpg 480w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/sketch-defines.jpg 1263w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>With the define statements fixed, I compiled the sketch and uploaded it to the Nano. When the upload was complete the display ran through its range of text and graphical displays, proving that the screen was working and the interface to the Nano was good.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Programming<\/h2>\n\n\n\n<p>One of the great things about the <em>graphicstest<\/em> sketch is that it displays text and various graphics, so gives a quick insight into how to do these yourself. It also gives you bits you can pick out and tweak to help work out how to implement the displays you actually want.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Displaying Text<\/h3>\n\n\n\n<p>Displaying basic text is easy, but requires a few function calls to set things up prior to actually printing the text. First, set the text size using the following function:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#f0f0f0\">void setTextSize(uint8_t size);<\/pre>\n\n\n\n<p>where size is an 8-bit integer. As far as the available text sizes are concerned, text size 1 is small, size 2 quite big and anything higher is, in my view, too big for the screen. Half sizes would have been useful, as between 1 and 2 would probably be ideal for what I was trying to do. However, we can only work with what we have!<\/p>\n\n\n\n<p>I believe it may be possible to do intermediate text sizes with a different ST7735 library, but that&#8217;s another rabbit hole to chase down some other time.<\/p>\n\n\n\n<p>Text colour is set with another call, this time passing an unsigned 16-bit integer:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#f0f0f0\">void setTextColor(uint16_t color);<\/pre>\n\n\n\n<p>Colours can either be pre-defined values like &#8220;ST77XX_GREEN&#8221; or 16-bit hex values such as &#8220;0xEC02&#8221;.<\/p>\n\n\n\n<p>It is possible to just print lines of text to the screen, but to fromat it neatly the position of each string can be set using the following function:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#f0f0f0\">void setCursor(int16_t x0, int16_t y0);<\/pre>\n\n\n\n<p>where x0 and y0 are the coordinates of the top left of the first character, passed as unsigned 16-bit integers. [(0,0) is the top left corner of the screen.]<\/p>\n\n\n\n<p>With the text parameters set up, the actual text is just written <em>tft.print()<\/em> instructions , which work the same as <em>print()<\/em> in serial printing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Displaying Symbols<\/h3>\n\n\n\n<p>The GFX library implements a range of primitives: points, lines, rectangles, triangles, circles and rounded rectangles. For the display I was aiming to implement I only needed a few of these, detailed below.<\/p>\n\n\n\n<p>As the screen area is quite small I decided to make my status symbols a traffic light system. This removes the need to make very small ticks and crosses &#8211; instead just having to use filled circles. Very usefully, filled circles have been implemented in the library and just require four parameters to be passed to the function:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#f0f0f0\">void fillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);<\/pre>\n\n\n\n<p>where the parameters, all passed as unsigned 16-bit integers, are:<\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"font-size:16px\">\n<li>x0 and y0 are the position of the <em>centre<\/em> of the circle,<\/li>\n\n\n\n<li>radius is the radius of the circle in pixels,<\/li>\n\n\n\n<li>color is the circle&#8217;s colour: either pre-defined or a hex value (same as text colours, above).<\/li>\n<\/ul>\n\n\n\n<p>There&#8217;s another library function to draw unfilled circles, which could be useful highlighting list items for selection.  Calling it uses the same parameters as the filled circle:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#f0f0f0\">void drawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);<\/pre>\n\n\n\n<p>Finally, for highlighting text items on the menu there&#8217;s a rounded rectangle:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background\" style=\"background-color:#f0f0f0\">void drawRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);<\/pre>\n\n\n\n<p>This one has a few more parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li style=\"font-size:16px\">x0 and y0 are the coordinates of the <em>top-left<\/em> corner,<\/li>\n\n\n\n<li style=\"font-size:16px\">w and h are the width and height of the rectangle,<\/li>\n\n\n\n<li style=\"font-size:16px\">radius is the radius of the corner rounding in pixels,<\/li>\n\n\n\n<li style=\"font-size:16px\">color is the colour.<\/li>\n<\/ul>\n\n\n\n<p>Again all parameters are passed as unsigned 16-bit integers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test Sketch<\/h2>\n\n\n\n<p>Looking forward to the elements I think I need to produce the UI for the macro rail, I designed a simple display with a heading, a list of menu items on the left and values and status indicators on the right. I added highlighting outlines to one each of the values and  status indicators. I  coded this as a simple static display page, using a subset of the GFX library&#8217;s functionality.<\/p>\n\n\n\n<p>The display I produced is shown here:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"679\" src=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-1024x679.jpg\" alt=\"ST7735 TFT Display\" class=\"wp-image-1804\" srcset=\"https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-1024x679.jpg 1024w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-300x199.jpg 300w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-768x510.jpg 768w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-1536x1019.jpg 1536w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-1000x664.jpg 1000w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-230x153.jpg 230w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-350x232.jpg 350w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1-480x319.jpg 480w, https:\/\/photobuilds.com\/wp-content\/uploads\/2023\/05\/N505084-1.jpg 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>&#8230; and the sketch to create it is listed below:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-background has-small-font-size\" style=\"background-color:#f0f0f0\">#include &lt;Adafruit_GFX.h&gt;    \/\/ Core graphics library\n#include &lt;Adafruit_ST7735.h&gt; \/\/ Hardware-specific library for ST7735\n#include &lt;SPI.h&gt;\n\n#define TFT_CS         6  \/\/ define CS, RST and DC pins\n#define TFT_RST        5 \n#define TFT_DC         7\n\nAdafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);\n\nvoid setup() {\n  Serial.begin(9600);\n  tft.initR(INITR_BLACKTAB);      \/\/ Init ST7735S chip, black tab\n  tft.setTextWrap(false);\n  delay(500);\n  tft.fillScreen(ST77XX_BLACK);   \/\/clear the screen\n}\n\nvoid loop() {\n  \/\/ write the heading\n  tft.setCursor(0, 0);\n  tft.setTextColor(0xE383);\n  tft.setTextSize(2);\n  tft.print(\"Heading\");\n  \/\/ write the menu items\n  tft.setCursor(0, 32);\n  tft.setTextColor(ST77XX_WHITE);\n  tft.setTextSize(1);\n  tft.print(\"Item 1:\");\n  tft.setCursor(0, 57);\n  tft.print(\"Item 2:\");\n  tft.setCursor(0, 82);\n  tft.print(\"Item 3:\");\n  tft.setCursor(0, 107);\n  tft.print(\"Item 4:\");\n  tft.setCursor(0, 132);\n  tft.print(\"Item 5:\");\n  \/\/ write some filled circles\n  tft.fillCircle(118, 35, 5, 0x1F09);   \/\/ green\n  tft.fillCircle(118, 60, 5, 0xED42);   \/\/ orange\n  tft.fillCircle(118, 85, 5, 0xF8E0);   \/\/ red\n  \/\/ write two values as text\n  tft.setCursor(70, 107);\n  tft.print(123.45);\n  tft.setCursor(70, 132);\n  tft.print(567.8);\n  \/\/ write indiviual characters\n  tft.drawChar(110,107,0xE5 ,ST77XX_WHITE, 0, 1);\n  tft.drawChar(116,107,0x6D ,ST77XX_WHITE, 0, 1);  \n  tft.drawChar(116, 132,0x73,ST77XX_WHITE, 0, 1);\n  \/\/ highlight second circle\n  tft.drawCircle(118, 60, 8, ST77XX_YELLOW);\n  \/\/ highlight first value\n  tft.drawRoundRect(67, 104, 58, 13, 4, ST77XX_YELLOW);\n}<\/pre>\n\n\n\n<p><strong><em>Note:<\/em><\/strong> the above is purely a test sketch with a lot of static values and positioning, but it shows what the screen can do. Things will get more complicated code-wise when this gets turned into a properly structured sketch and  integrated into the macro rail. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In earlier Arduino based projects I&#8217;ve used two different monochrome LCD screens, but these were quite limited in their display capabilities. In the drop controller I went with the two [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[128,199,217],"tags":[426,206,300,422,139,141,297,9,427,429,428,212,213,420,418,421,419,416,417],"class_list":["post-1751","post","type-post","status-publish","format-standard","hentry","category-background","category-electronics","category-microcontrollers","tag-adafruit","tag-arduino","tag-arduino-ide","tag-breadboard","tag-color","tag-colour","tag-display","tag-diy","tag-gfx","tag-libraries","tag-library","tag-microcontroller","tag-nano","tag-protocol","tag-screen","tag-serial-peripheral-interface","tag-spi","tag-st7735","tag-tft"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/posts\/1751","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/comments?post=1751"}],"version-history":[{"count":30,"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/posts\/1751\/revisions"}],"predecessor-version":[{"id":1812,"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/posts\/1751\/revisions\/1812"}],"wp:attachment":[{"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/media?parent=1751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/categories?post=1751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/photobuilds.com\/index.php\/wp-json\/wp\/v2\/tags?post=1751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}