{"id":164489,"date":"2025-02-25T14:02:28","date_gmt":"2025-02-25T14:02:28","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=164489"},"modified":"2025-06-02T09:15:47","modified_gmt":"2025-06-02T09:15:47","slug":"esp32-cyd-lvgl-line-chart","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-cyd-lvgl-line-chart\/","title":{"rendered":"ESP32 CYD with LVGL: Display Temperature on Line Chart (BME280)"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to display temperature from the BME280 sensor on an ESP32 Cheap Yellow Display (CYD) using LVGL (Light Versatile Graphics Library). You\u2019ll learn how to draw a line chart to display data from a sensor. The ESP32 will be programmed using Arduino IDE.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?resize=1024%2C576&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD with LVGL: Display Temperature on Line Chart (BME280)\" class=\"wp-image-164591\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclblue\"><strong>New to the ESP32 Cheap Yellow Display?<\/strong> Start here: <a href=\"https:\/\/randomnerdtutorials.com\/cheap-yellow-display-esp32-2432s028r\/\">Getting Started with ESP32 Cheap Yellow Display Board \u2013 CYD (ESP32-2432S028R)<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>In this project, we\u2019ll draw a line chart with the temperature from the BME280 sensor on the ESP32 CYD screen. Here&#8217;s the main features:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The chart displays a maximum of 20 data points;<\/li>\n\n\n\n<li>When a new point is added to the screen, the oldest data point is deleted;<\/li>\n\n\n\n<li>The vertical axis range will adjust automatically depending on the current values plotted on the chart;<\/li>\n\n\n\n<li>You can touch next to the data points to check the precise value of a point\u2014it will draw a label with its value next to it.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"452\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-Project-Overview-Line-Chart-BME280.png?resize=750%2C452&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD Project Overview Line Chart BME280\" class=\"wp-image-164499\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-Project-Overview-Line-Chart-BME280.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-Project-Overview-Line-Chart-BME280.png?resize=300%2C181&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding, make sure you follow the next prerequisites.<strong> You must follow all steps, otherwise, your project will not work.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) Parts Required and Wiring the Circuit<\/h3>\n\n\n\n<p>For this project, you need the following parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/cyd-cheap-yellow-display-esp32-2432s028r\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32-2432S028R \u2013 2.8 inch 240\u00d7320 Smart Display TFT with Touchscreen<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/bme280-sensor-module\/\" target=\"_blank\" rel=\"noopener\" title=\"\">BME280 Sensor<\/a><\/li>\n<\/ul>\n\n\n\n<p>We\u2019ll use I2C communication protocol to get data from the BME280 sensor. On the ESP32 CYD board there is an <a href=\"https:\/\/randomnerdtutorials.com\/esp32-cheap-yellow-display-cyd-pinout-esp32-2432s028r\/\">extended IO socket<\/a> that allows you to connect external peripherals. We\u2019ll connect the sensor to the CN1 connector.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-CYD-Cheap-Yellow-Display-Board-JST-Connector-Connecting-BME280-Sensor.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD Cheap Yellow Display Board JST Connector Connecting BME280 Sensor\" class=\"wp-image-162195\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-CYD-Cheap-Yellow-Display-Board-JST-Connector-Connecting-BME280-Sensor.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-CYD-Cheap-Yellow-Display-Board-JST-Connector-Connecting-BME280-Sensor.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Your board should have come with a little JST connector to access those GPIOs.<\/p>\n\n\n\n<p>We&#8217;ll connect SDA to GPIO 27, and SCL to GPIO 22.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-CYD-Cheap-Yellow-Display-Board-JST-Connector.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD Cheap Yellow Display Board JST Connector\" class=\"wp-image-162194\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-CYD-Cheap-Yellow-Display-Board-JST-Connector.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/ESP32-CYD-Cheap-Yellow-Display-Board-JST-Connector.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>If you\u2019re not familiar with the BME280 sensor, we recommend that you read our getting started guide: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\">ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)<\/a><\/p>\n\n\n\n<p>The CYD board should have a built-in LDR (light-dependent resistor) next to the screen and connected to GPIO 34.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"423\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/ESP32-Cheap-Yellow-Display-LDR.jpg?resize=750%2C423&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Cheap Yellow Display LDR (Light Dependent ResistorESP32-Cheap-Yellow-)\" class=\"wp-image-159209\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/ESP32-Cheap-Yellow-Display-LDR.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/ESP32-Cheap-Yellow-Display-LDR.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">2) Install ESP32 Boards in Arduino IDE<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"204\" height=\"204\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-2.jpg?resize=204%2C204&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Logo\" class=\"wp-image-159109\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-2.jpg?w=204&amp;quality=100&amp;strip=all&amp;ssl=1 204w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/06\/arduino-ide-2.jpg?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 204px) 100vw, 204px\" \/><\/figure><\/div>\n\n\n<p>We&#8217;ll program the ESP32 using Arduino IDE. Make sure you have the ESP32 boards installed. Follow the next tutorial:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-esp32-arduino-ide-2-0\/\" title=\"\">Installing ESP32 Board in Arduino IDE 2 (Windows, Mac OS X, Linux)<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3) Get familiar with the ESP32 Cheap Yellow Display<\/h3>\n\n\n\n<p>The&nbsp;<a href=\"https:\/\/makeradvisor.com\/tools\/cyd-cheap-yellow-display-esp32-2432s028r\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32-2432S028R<\/a>&nbsp;development board has become known in the maker community as the \u201c<em>Cheap Yellow Display<\/em>\u201d or CYD for short. This development board, whose main chip is an ESP32-WROOM-32 module, comes with a 2.8-inch TFT touchscreen LCD, a microSD card interface, an RGB LED, and all the required circuitry to program and apply power to the board.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"421\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Cheap-Yellow-Display-CYD-Board-ESP32-2432S028R-front.jpg?resize=750%2C421&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Cheap Yellow Display CYD Board ESP32-2432S028R front\" class=\"wp-image-149592\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Cheap-Yellow-Display-CYD-Board-ESP32-2432S028R-front.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Cheap-Yellow-Display-CYD-Board-ESP32-2432S028R-front.jpg?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>If this is your first time using the ESP32 Cheap Yellow Display, make sure to follow our getting started guide:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-cheap-yellow-display-esp32-2432s028r\/\">Getting Started with ESP32 Cheap Yellow Display Board and LVGL<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4) Install TFT and LVGL Libraries<\/h3>\n\n\n\n<p><a href=\"https:\/\/docs.lvgl.io\/master\/\" target=\"_blank\" rel=\"noreferrer noopener\">LVGL<\/a>&nbsp;(Light and Versatile Graphics Library) is a free and open-source graphics library that provides a wide range of easy-to-use graphical elements for your microcontroller projects that require a graphical user interface (GUI).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"622\" height=\"194\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-new-logo.png?resize=622%2C194&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"LVGL new logo\" class=\"wp-image-161339\" style=\"width:340px;height:auto\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-new-logo.png?w=622&amp;quality=100&amp;strip=all&amp;ssl=1 622w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/08\/LVGL-new-logo.png?resize=300%2C94&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 622px) 100vw, 622px\" \/><\/figure><\/div>\n\n\n<p>Follow the next tutorial to install and configure the required libraries to use LVGL for the ESP32 Cheap Yellow Display using Arduino IDE.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-cheap-yellow-display-esp32-2432s028r\/\" title=\"\"><strong>Get started with LVGL using the ESP32 Cheap Yellow Display Board (ESP32-2432S028R)<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5) Install BME280 Libraries<\/h3>\n\n\n\n<p>For this project, we&#8217;ll use the Adafruit BME280 library to get data from the BME280. In the Arduino IDE, go to <strong>Sketch <\/strong>&gt; <strong>Include Library<\/strong> &gt; <strong>Manage Libraries<\/strong>. Search for<strong> Adafruit BME280<\/strong> Library on the search box and install the library. Also, install any dependencies that are currently not installed (usually the Adafruit Bus IO and the Adafruit Unified Sensor libraries).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"290\" height=\"305\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/Installing-Adafruit-BME280-Sensor-Library-Arduino-IDE.png?resize=290%2C305&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Installing Adafruit BME280 Sensor Library Arduino IDE\" class=\"wp-image-162191\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/Installing-Adafruit-BME280-Sensor-Library-Arduino-IDE.png?w=290&amp;quality=100&amp;strip=all&amp;ssl=1 290w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/09\/Installing-Adafruit-BME280-Sensor-Library-Arduino-IDE.png?resize=285%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 285w\" sizes=\"(max-width: 290px) 100vw, 290px\" \/><\/figure><\/div>\n\n\n<p class=\"rntbox rntclgreen\">Learn more about the CYD Pinout: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-cheap-yellow-display-cyd-pinout-esp32-2432s028r\/\">ESP32 Cheap Yellow Display (CYD) Pinout (ESP32-2432S028R)<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Displaying Temperature Line Chart on ESP32 CYD using LVGL &#8211; Arduino Code<\/h2>\n\n\n\n<p>The following code will create the chart with values from the BME280 sensor.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*  Rui Santos &amp; Sara Santos - Random Nerd Tutorials - https:\/\/RandomNerdTutorials.com\/esp32-cyd-lvgl-line-chart\/  |  https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl-line-chart\/\n    THIS EXAMPLE WAS TESTED WITH THE FOLLOWING HARDWARE:\n    1) ESP32-2432S028R 2.8 inch 240\u00d7320 also known as the Cheap Yellow Display (CYD): https:\/\/makeradvisor.com\/tools\/cyd-cheap-yellow-display-esp32-2432s028r\/\n      SET UP INSTRUCTIONS: https:\/\/RandomNerdTutorials.com\/cyd-lvgl\/\n    2) REGULAR ESP32 Dev Board + 2.8 inch 240x320 TFT Display: https:\/\/makeradvisor.com\/tools\/2-8-inch-ili9341-tft-240x320\/ and https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\n      SET UP INSTRUCTIONS: https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl\/\n    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.\n    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n*\/\n\n\/*  Install the &quot;lvgl&quot; library version 9.X by kisvegabor to interface with the TFT Display - https:\/\/lvgl.io\/\n    *** IMPORTANT: lv_conf.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***\n    *** YOU MUST USE THE lv_conf.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***\n    FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https:\/\/RandomNerdTutorials.com\/cyd-lvgl\/ or https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl\/   *\/\n#include &lt;lvgl.h&gt;\n\n\/*  Install the &quot;TFT_eSPI&quot; library by Bodmer to interface with the TFT Display - https:\/\/github.com\/Bodmer\/TFT_eSPI\n    *** IMPORTANT: User_Setup.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***\n    *** YOU MUST USE THE User_Setup.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***\n    FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https:\/\/RandomNerdTutorials.com\/cyd-lvgl\/ or https:\/\/RandomNerdTutorials.com\/esp32-tft-lvgl\/   *\/\n#include &lt;TFT_eSPI.h&gt;\n\n\/\/ Install the &quot;XPT2046_Touchscreen&quot; library by Paul Stoffregen to use the Touchscreen - https:\/\/github.com\/PaulStoffregen\/XPT2046_Touchscreen - Note: this library doesn't require further configuration\n#include &lt;XPT2046_Touchscreen.h&gt;\n\n\/\/ Install Adafruit Unified Sensor and Adafruit BME280 Library\n#include &lt;Wire.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;\n#define I2C_SDA 27\n#define I2C_SCL 22\nTwoWire I2CBME = TwoWire(0);\nAdafruit_BME280 bme;\n\n\/\/ SET VARIABLE TO 0 FOR TEMPERATURE IN FAHRENHEIT DEGREES\n#define TEMP_CELSIUS 1\n#define BME_NUM_READINGS 20\nfloat bme_last_readings[BME_NUM_READINGS] = {-20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0};\nfloat scale_min_temp;\nfloat scale_max_temp;\n\n\/\/ Touchscreen pins\n#define XPT2046_IRQ 36   \/\/ T_IRQ\n#define XPT2046_MOSI 32  \/\/ T_DIN\n#define XPT2046_MISO 39  \/\/ T_OUT\n#define XPT2046_CLK 25   \/\/ T_CLK\n#define XPT2046_CS 33    \/\/ T_CS\n\nSPIClass touchscreenSPI = SPIClass(VSPI);\nXPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);\n\n#define SCREEN_WIDTH 240\n#define SCREEN_HEIGHT 320\n\n\/\/ Touchscreen coordinates: (x, y) and pressure (z)\nint x, y, z;\n\n#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT \/ 10 * (LV_COLOR_DEPTH \/ 8))\nuint32_t draw_buf[DRAW_BUF_SIZE \/ 4];\n\n\/\/ Generally, you should use &quot;unsigned long&quot; for variables that hold time\nunsigned long previousMillis = 0; \/\/ will store last time the chart was updated\n\/\/ Interval at which the chart will be updated (milliseconds) 10000 milliseconds = 10 seconds\nconst long interval = 10000;\n\n\/\/ If logging is enabled, it will inform the user about what is happening in the library\nvoid log_print(lv_log_level_t level, const char * buf) {\n  LV_UNUSED(level);\n  Serial.println(buf);\n  Serial.flush();\n}\n\n\/\/ Get the Touchscreen data\nvoid touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data) {\n  \/\/ Checks if Touchscreen was touched, and prints X, Y and Pressure (Z)\n  if(touchscreen.tirqTouched() &amp;&amp; touchscreen.touched()) {\n    \/\/ Get Touchscreen points\n    TS_Point p = touchscreen.getPoint();\n\n    \/\/ Advanced Touchscreen calibration, LEARN MORE \u00bb https:\/\/RandomNerdTutorials.com\/touchscreen-calibration\/\n    float alpha_x, beta_x, alpha_y, beta_y, delta_x, delta_y;\n\n    \/\/ REPLACE WITH YOUR OWN CALIBRATION VALUES \u00bb https:\/\/RandomNerdTutorials.com\/touchscreen-calibration\/\n    alpha_x = -0.000;\n    beta_x = 0.090;\n    delta_x = -33.771;\n    alpha_y = 0.066;\n    beta_y = 0.000;\n    delta_y = -14.632;\n\n    x = alpha_y * p.x + beta_y * p.y + delta_y;\n    \/\/ clamp x between 0 and SCREEN_WIDTH - 1\n    x = max(0, x);\n    x = min(SCREEN_WIDTH - 1, x);\n\n    y = alpha_x * p.x + beta_x * p.y + delta_x;\n    \/\/ clamp y between 0 and SCREEN_HEIGHT - 1\n    y = max(0, y);\n    y = min(SCREEN_HEIGHT - 1, y);\n\n    \/\/ Basic Touchscreen calibration points with map function to the correct width and height\n    \/\/x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);\n    \/\/y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);\n\n    z = p.z;\n\n    data-&gt;state = LV_INDEV_STATE_PRESSED;\n\n    \/\/ Set the coordinates\n    data-&gt;point.x = x;\n    data-&gt;point.y = y;\n\n    \/\/ Print Touchscreen info about X, Y and Pressure (Z) on the Serial Monitor\n    Serial.print(&quot;X = &quot;);\n    Serial.print(x);\n    Serial.print(&quot; | Y = &quot;);\n    Serial.print(y);\n    Serial.print(&quot; | Pressure = &quot;);\n    Serial.print(z);\n    Serial.println();\n  }\n  else {\n    data-&gt;state = LV_INDEV_STATE_RELEASED;\n  }\n}\n\n\/\/ Draw a label on that chart with the value of the pressed point\nstatic void chart_draw_label_cb(lv_event_t * e) {\n  lv_event_code_t code = lv_event_get_code(e);\n  lv_obj_t * chart = (lv_obj_t*) lv_event_get_target(e);\n\n  if(code == LV_EVENT_VALUE_CHANGED) {\n    lv_obj_invalidate(chart);\n  }\n  if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {\n    int32_t * s = (int32_t*)lv_event_get_param(e);\n    *s = LV_MAX(*s, 20);\n  }\n  \/\/ Draw the label on the chart based on the pressed point\n  else if(code == LV_EVENT_DRAW_POST_END) {\n    int32_t id = lv_chart_get_pressed_point(chart);\n    if(id == LV_CHART_POINT_NONE) return;\n\n    LV_LOG_USER(&quot;Selected point %d&quot;, (int)id);\n\n    lv_chart_series_t * ser = lv_chart_get_series_next(chart, NULL);\n    while(ser) {\n      lv_point_t p;\n      lv_chart_get_point_pos_by_id(chart, ser, id, &amp;p);\n\n      int32_t * y_array = lv_chart_get_y_array(chart, ser);\n      int32_t value = y_array[id];\n      char buf[16];\n      #if TEMP_CELSIUS\n        const char degree_symbol[] = &quot;\\u00B0C&quot;;\n      #else\n        const char degree_symbol[] = &quot;\\u00B0F&quot;;\n      #endif\n\n      \/\/ Preparing the label text for the selected data point\n      lv_snprintf(buf, sizeof(buf), LV_SYMBOL_DUMMY &quot; %3.2f %s &quot;, float(bme_last_readings[id]), degree_symbol);\n\n      \/\/ Draw the rectangular label that will display the temperature value\n      lv_draw_rect_dsc_t draw_rect_dsc;\n      lv_draw_rect_dsc_init(&amp;draw_rect_dsc);\n      draw_rect_dsc.bg_color = lv_color_black();\n      draw_rect_dsc.bg_opa = LV_OPA_60;\n      draw_rect_dsc.radius = 2;\n      draw_rect_dsc.bg_image_src = buf;\n      draw_rect_dsc.bg_image_recolor = lv_color_white();\n      \/\/ Rectangular label size\n      lv_area_t a;\n      a.x1 = chart-&gt;coords.x1 + p.x - 35;\n      a.x2 = chart-&gt;coords.x1 + p.x + 35;\n      a.y1 = chart-&gt;coords.y1 + p.y - 30;\n      a.y2 = chart-&gt;coords.y1 + p.y - 10;\n      lv_layer_t * layer = lv_event_get_layer(e);\n      lv_draw_rect(layer, &amp;draw_rect_dsc, &amp;a);\n      ser = lv_chart_get_series_next(chart, ser);\n    }\n  }\n  else if(code == LV_EVENT_RELEASED) {\n    lv_obj_invalidate(chart);\n  }\n}\n\n\/\/ Draw chart\nvoid lv_draw_chart(void) {\n  \/\/ Clear screen\n  lv_obj_clean(lv_scr_act());\n\n  \/\/ Create a a text label aligned on top\n  lv_obj_t * label = lv_label_create(lv_screen_active());\n  lv_label_set_text(label, &quot;BME280 Temperature Readings&quot;);\n  lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 10);\n\n  \/\/ Create a container to display the chart and scale\n  lv_obj_t * container_row = lv_obj_create(lv_screen_active());\n  lv_obj_set_size(container_row, SCREEN_HEIGHT-20,  SCREEN_WIDTH-40);\n  lv_obj_align(container_row, LV_ALIGN_BOTTOM_MID, 0, -10);\n  \/\/ Set the container in a flexbox row layout aligned center\n  lv_obj_set_flex_flow(container_row, LV_FLEX_FLOW_ROW);\n  lv_obj_set_flex_align(container_row, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);\n\n  \/\/ Create a chart\n  lv_obj_t * chart = lv_chart_create(container_row);\n  lv_obj_set_size(chart, SCREEN_HEIGHT-90, SCREEN_WIDTH-70);\n  lv_chart_set_point_count(chart, BME_NUM_READINGS);\n  lv_obj_add_event_cb(chart, chart_draw_label_cb, LV_EVENT_ALL, NULL);\n  lv_obj_refresh_ext_draw_size(chart);\n\n  \/\/ Add a data series\n  lv_chart_series_t * chart_series = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_GREEN), LV_CHART_AXIS_PRIMARY_Y);\n\n  for(int i = 0; i &lt; BME_NUM_READINGS; i++) {\n    if(float(bme_last_readings[i]) != -20.0) { \/\/ Ignores default array values\n      \/\/ Set points in the chart and scale them with an *100 multiplier to remove the 2 floating-point numbers\n      chart_series-&gt;y_points[i] = float(bme_last_readings[i]) * 100;\n    }\n  }\n  \/\/ Set the chart range and also scale it with an *100 multiplier to remove the 2 floating-point numbers\n  lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, int(scale_min_temp-1)*100, int(scale_max_temp+1)*100);\n  lv_chart_refresh(chart); \/\/ Required to update the chart with the new values\n\n  \/\/ Create a scale (y axis for the temperature) aligned vertically on the right\n  lv_obj_t * scale = lv_scale_create(container_row);\n  lv_obj_set_size(scale, 15, SCREEN_WIDTH-90);\n  lv_scale_set_mode(scale, LV_SCALE_MODE_VERTICAL_RIGHT);\n  lv_scale_set_label_show(scale, true);\n  \/\/ Set the scale ticks count \n  lv_scale_set_total_tick_count(scale, int(scale_max_temp+2) - int(scale_min_temp-1));\n  if((int(scale_max_temp+2) - int(scale_min_temp-1)) &lt; 10) {\n    lv_scale_set_major_tick_every(scale, 1); \/\/ set y axis to have 1 tick every 1 degree\n  }\n  else {\n    lv_scale_set_major_tick_every(scale, 10); \/\/ set y axis to have 1 tick every 10 degrees\n  }\n  \/\/ Set the scale style and range\n  lv_obj_set_style_length(scale, 5, LV_PART_ITEMS);\n  lv_obj_set_style_length(scale, 10, LV_PART_INDICATOR);\n  lv_scale_set_range(scale, int(scale_min_temp-1), int(scale_max_temp+1));\n}\n\n\/\/ Get the latest BME readings\nvoid get_bme_readings(void) {\n  #if TEMP_CELSIUS\n    float bme_temp = bme.readTemperature();\n  #else\n    float bme_temp = 1.8 * bme.readTemperature() + 32;  \n  #endif\n  \n  \/\/ Reset scale range (chart y axis) variables\n  scale_min_temp = 120.0;\n  scale_max_temp = -20.0;\n\n  \/\/ Shift values to the left of the array and inserts the latest reading at the end\n  for (int i = 0; i &lt; BME_NUM_READINGS; i++) {\n    if(i == (BME_NUM_READINGS-1) &amp;&amp; float(bme_temp) &lt; 120.0) {\n      bme_last_readings[i] = float(bme_temp);  \/\/ Inserts the new reading at the end\n    }\n    else {\n      bme_last_readings[i] = float(bme_last_readings[i + 1]);  \/\/ Shift values to the left of the array\n    }\n    \/\/ Get the min\/max value in the array to set the scale range (chart y axis)\n    if((float(bme_last_readings[i]) &lt; scale_min_temp) &amp;&amp; (float(bme_last_readings[i]) != -20.0 )) {\n      scale_min_temp = bme_last_readings[i];\n    }\n    if((float(bme_last_readings[i]) &gt; scale_max_temp) &amp;&amp; (float(bme_last_readings[i]) != -20.0 )) {\n      scale_max_temp = bme_last_readings[i];\n    }\n  }\n  Serial.print(&quot;Min temp: &quot;);\n  Serial.println(float(scale_min_temp));\n  Serial.print(&quot;Max temp: &quot;);\n  Serial.println(float(scale_max_temp));\n  Serial.print(&quot;BME last reading: &quot;);\n  Serial.println(float(bme_last_readings[BME_NUM_READINGS-1]));\n  lv_draw_chart();\n}\n\nvoid setup() {\n  String LVGL_Arduino = String(&quot;LVGL Library Version: &quot;) + lv_version_major() + &quot;.&quot; + lv_version_minor() + &quot;.&quot; + lv_version_patch();\n  Serial.begin(115200);\n  Serial.println(LVGL_Arduino);\n\n  I2CBME.begin(I2C_SDA, I2C_SCL, 100000);\n  bool status;\n  \/\/ Passing a &amp;Wire2 to set custom I2C ports\n  status = bme.begin(0x76, &amp;I2CBME);\n  if (!status) {\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\n    while (1);\n  }\n  \n  \/\/ Start LVGL\n  lv_init();\n  \/\/ Register print function for debugging\n  lv_log_register_print_cb(log_print);\n\n  \/\/ Start the SPI for the touchscreen and init the touchscreen\n  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);\n  touchscreen.begin(touchscreenSPI);\n  \/\/ Set the Touchscreen rotation in landscape mode\n  \/\/ Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);\n  touchscreen.setRotation(2);\n\n  \/\/ Create a display object\n  lv_display_t * disp;\n  \/\/ Initialize the TFT display using the TFT_eSPI library\n  disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));\n  lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);\n  \n  \/\/ Initialize an LVGL input device object (Touchscreen)\n  lv_indev_t * indev = lv_indev_create();\n  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);\n  \/\/ Set the callback function to read Touchscreen input\n  lv_indev_set_read_cb(indev, touchscreen_read);\n\n  get_bme_readings();\n}\n\nvoid loop() {\n  lv_task_handler();  \/\/ let the GUI do its work\n  lv_tick_inc(5);     \/\/ tell LVGL how much time has passed\n  delay(5);           \/\/ let this time pass\n  \n  unsigned long currentMillis = millis();\n  if (currentMillis - previousMillis &gt;= interval) {\n    \/\/ save the last time that chart was updated\n    previousMillis = currentMillis;\n    get_bme_readings();    \n  }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/ESP32-TFT-Touchscreen\/raw\/main\/examples\/ESP32_LVGL_Line_Chart_BME280\/ESP32_LVGL_Line_Chart_BME280.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Does the Code Work?<\/h2>\n\n\n\n<p>Let\u2019s take a look at how to get temperature from the BME280 sensor and add the current reading to the line chart. Alternatively, you can skip to the <a href=\"#demonstration\" title=\"\">Demonstration <\/a>section.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Including Libraries<\/h3>\n\n\n\n<p>In all your sketches, you need to include the <span class=\"rnthl rntliteral\">lvgl.h<\/span> and the <span class=\"rnthl rntliteral\">TFT_eSPI.h<\/span> libraries to display on the screen.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;lvgl.h&gt;\n#include &lt;TFT_eSPI.h&gt;<\/code><\/pre>\n\n\n\n<p>You need to include the following libraries to interface with the BME280 sensor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;Wire.h&gt;\n#include &lt;Adafruit_Sensor.h&gt;\n#include &lt;Adafruit_BME280.h&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">BME280 I2C Pins<\/h3>\n\n\n\n<p>Set the I2C pins to use the BME280 sensor, create a new I2C bus instance to use those pins, and create an <span class=\"rnthl rntliteral\">Adafruit_BME280<\/span> object called <span class=\"rnthl rntliteral\">bme<\/span> to refer to the sensor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define I2C_SDA 27\n#define I2C_SCL 22\nTwoWire I2CBME = TwoWire(0);\nAdafruit_BME280 bme;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Celsius or Fahrenheit<\/h3>\n\n\n\n<p>Our code is prepared to display the temperature in Celsius or Fahrenheit degrees. To choose your desired unit, you can set the value of the <span class=\"rnthl rntliteral\">TEMP_CELSIUS<\/span> variable. It is set to <span class=\"rnthl rntliteral\">1<\/span> by default to display the temperature in Celsius degrees.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define TEMP_CELSIUS 1 &nbsp; &nbsp;<\/code><\/pre>\n\n\n\n<p>If you want to display in Fahrenheit degrees instead, set it to <span class=\"rnthl rntliteral\">0<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define TEMP_CELSIUS 0<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Number of Readings and Scale Variables<\/h3>\n\n\n\n<p>The data to be displayed on the chart needs to be placed in an array. We\u2019ll display a maximum of 20 readings. These are saved on the <span class=\"rnthl rntliteral\">bme_last_readings<\/span> array.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define BME_NUM_READINGS 20\nfloat bme_last_readings&#091;BME_NUM_READINGS] = {-20.0, -20.0, -20.0, -20.0, -20.0,\n-20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0,\n-20.0, -20.0, -20.0, -20.0};<\/code><\/pre>\n\n\n\n<p>We also create two global variables <span class=\"rnthl rntliteral\">scale_min_temp<\/span> and <span class=\"rnthl rntliteral\">scale_max_temp<\/span> that will be used to adjust the scale range.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>float scale_min_temp;\nfloat scale_max_temp;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Defining the Display Width and Height<\/h3>\n\n\n\n<p>You need to define your display width and height in all your sketches that use LVGL. If you\u2019re using the recommended display, the size is 240&#215;320.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define SCREEN_WIDTH 241\n#define SCREEN_HEIGHT 320<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Creating a Drawing Buffer<\/h3>\n\n\n\n<p>You need to create a buffer to draw on the display as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT \/ 10 * (LV_COLOR_DEPTH \/ 8))\nuint32_t draw_buf&#091;DRAW_BUF_SIZE \/ 4];<\/code><\/pre>\n\n\n\n<p>You should also include this in all LVGL examples.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging Function<\/h3>\n\n\n\n<p>For debugging with the LVGL library, you should use the <span class=\"rnthl rntliteral\">log_print()<\/span> function. It is defined below. Include it in all your sketches before the <span class=\"rnthl rntliteral\">setup()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ If logging is enabled, it will inform the user about what is happening in the library\nvoid log_print(lv_log_level_t level, const char * buf) {\n  LV_UNUSED(level);\n  Serial.println(buf);\n  Serial.flush();\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">setup()<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, include the following lines for debugging. These will print the version of LVGL that you\u2019re using. You must be using version 9.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>String LVGL_Arduino = String(\"LVGL Library Version: \") + lv_version_major() + \".\" + lv_version_minor() + \".\" + lv_version_patch();\nSerial.begin(115200);\nSerial.println(LVGL_Arduino);<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initializing the BME280 sensor<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, start by initializing the BME280 sensor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>I2CBME.begin(I2C_SDA, I2C_SCL, 100000);\nbool status;\n\/\/ Passing a &amp;Wire2 to set custom I2C ports\nstatus = bme.begin(0x76, &amp;I2CBME);\nif (!status) {\n  Serial.println(\"Could not find a valid BME280 sensor, check wiring!\");\n  while (1);\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Initialize the LVGL Library<\/h4>\n\n\n\n<p>Initialize the LVGL Library by calling the <span class=\"rnthl rntliteral\">lv_init()<\/span> function in the <span class=\"rnthl rntliteral\">setup()<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Start LVGL\nlv_init();<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Register Debugging Function<\/h4>\n\n\n\n<p>Register your <span class=\"rnthl rntliteral\">log_print()<\/span> function declared previously as a function associated with debugging LVGL.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Register print function for debugging\nlv_log_register_print_cb(log_print);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Getting BME280 Readings<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">setup()<\/span>, we call the <span class=\"rnthl rntliteral\">get_bme_readings()<\/span> which will get new sensor readings and display them on the chart.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>get_bme_readings();<\/code><\/pre>\n\n\n\n<p>This function is also called every 10 seconds (<span class=\"rnthl rntliteral\">interval<\/span> variable) in the <span class=\"rnthl rntliteral\">loop()<\/span> to add a new data point to the chart.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>unsigned long currentMillis = millis();\nif (currentMillis - previousMillis &gt;= interval) {\n  \/\/ save the last time that chart was updated\n  previousMillis = currentMillis;\n  get_bme_readings();\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">get_bme_readings()<\/span>, we start by getting a new temperature reading and save it on the <span class=\"rnthl rntliteral\">bme_temp<\/span> variable (in Celsius or Fahrenheit degrees).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#if TEMP_CELSIUS\n  float bme_temp = bme.readTemperature();\n#else\n  float bme_temp = 1.8 * bme.readTemperature() + 32;\n#endif<\/code><\/pre>\n\n\n\n<p>Every time we get a new data point, we\u2019ll reset the scale range (y-axis).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Reset scale range (chart y axis) variables\nscale_min_temp = 120.0;\nscale_max_temp = -20.0;<\/code><\/pre>\n\n\n\n<p>We add the new temperature value at the end of the array and shift all data points to the left of the array.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Shift values to the left of the array and inserts the latest reading at the end\nfor (int i = 0; i &lt; BME_NUM_READINGS; i++) {\n  if(i == (BME_NUM_READINGS-1) &amp;&amp; float(bme_temp) &lt; 120.0) {\n    bme_last_readings&#091;i] = float(bme_temp); \/\/Inserts the new reading at the end\n  }\n  else {\n    bme_last_readings&#091;i] = float(bme_last_readings&#091;i+1]);\n    \/\/ Shift values to the left of the array\n  }<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">bme_last_readings<\/span> array now contains the data to be displayed on the chart.<\/p>\n\n\n\n<p>We\u2019ll go through the array and get the maximum and the minimum temperature readings and save them on the <span class=\"rnthl rntliteral\">scale_max_temp<\/span> and <span class=\"rnthl rntliteral\">scale_min_temp<\/span> variables so that we can adjust the y-axis later.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Get the min\/max value in the array to set the scale range (chart y axis)\nif((float(bme_last_readings&#091;i]) &lt; scale_min_temp) &amp;&amp; (float(bme_last_readings&#091;i]) != -20.0 )) {\n  scale_min_temp = bme_last_readings&#091;i];\n}\nif((float(bme_last_readings&#091;i]) &gt; scale_max_temp) &amp;&amp; (float(bme_last_readings&#091;i]) != -20.0 )) {\n  scale_max_temp = bme_last_readings&#091;i];\n}<\/code><\/pre>\n\n\n\n<p>Now that we have our array ready and the maximum and minimum temperature values, we can start drawing the chart. We created a function called <span class=\"rnthl rntliteral\">lv_draw_chart()<\/span> where we added all the instructions<br>to draw the chart.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_draw_chart();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Drawing the Chart<\/h3>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">lv_draw_chart()<\/span> we draw the chart and add all the other widgets to the screen.<\/p>\n\n\n\n<p>We add a text label at the top with the <span class=\"rnthl rntliteral\">BME280 Temperature Readings<\/span> text.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create a a text label aligned on top\nlv_obj_t * label = lv_label_create(lv_screen_active());\nlv_label_set_text(label, \"BME280 Temperature Readings\");\nlv_obj_align(label, LV_ALIGN_TOP_MID, 0, 10);<\/code><\/pre>\n\n\n\n<p>Next, we create a container (<span class=\"rnthl rntliteral\">container_row<\/span>) where we\u2019ll add the chart and the corresponding scale (y-axis) and we set its alignment.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create a container to display the chart and scale\nlv_obj_t * container_row = lv_obj_create(lv_screen_active());\nlv_obj_set_size(container_row, SCREEN_HEIGHT-20, SCREEN_WIDTH-40);\nlv_obj_align(container_row, LV_ALIGN_BOTTOM_MID, 0, -10);\n\/\/ Set the container in a flexbox row layout aligned center\nlv_obj_set_flex_flow(container_row, LV_FLEX_FLOW_ROW);\nlv_obj_set_flex_align(container_row, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);<\/code><\/pre>\n\n\n\n<p>We create an LVGL chart object using the <span class=\"rnthl rntliteral\">lv_chart_create()<\/span> function. We pass as argument where we want to place the chart. In this case, we want to place it inside the <span class=\"rnthl rntliteral\">container_row<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_t * chart = lv_chart_create(container_row);<\/code><\/pre>\n\n\n\n<p>Set the chart size.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_set_size(chart, SCREEN_HEIGHT-90, SCREEN_WIDTH-70);<\/code><\/pre>\n\n\n\n<p>Set the number of points you want to display simultaneously on the chart.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_chart_set_point_count(chart, BME_NUM_READINGS);<\/code><\/pre>\n\n\n\n<p>Add an event to the chart so that it displays the pressed point value\u2014that will be handled inside the <span class=\"rnthl rntliteral\">chart_draw_label_cb()<\/span> callback function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_add_event_cb(chart, chart_draw_label_cb, LV_EVENT_ALL, NULL);<\/code><\/pre>\n\n\n\n<p>After creating the chart, we need to create a data series for the chart using the <span class=\"rnthl rntliteral\">lv_chart_add_series()<\/span>. Pass as argument the chart you\u2019re referring to, the color of the series, and the Y axis.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_chart_series_t * chart_series = lv_chart_add_series(chart,\nlv_palette_main(LV_PALETTE_GREEN), LV_CHART_AXIS_PRIMARY_Y);<\/code><\/pre>\n\n\n\n<p>Afterward, we add all our points in the array to the chart series.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>for(int i = 0; i &lt; BME_NUM_READINGS; i++) {\n  if(float(bme_last_readings&#091;i]) != -20.0) { \/\/ Ignores default array values\n    \/\/ Set points in the chart and scale them with an\n    \/\/ *100 multiplier to remove the 2 floating-point numbers\n   chart_series-&gt;y_points&#091;i] = float(bme_last_readings&#091;i]) * 100;\n  }\n}<\/code><\/pre>\n\n\n\n<p>Set the chart range taking into account the <span class=\"rnthl rntliteral\">scale_max_temp<\/span> and <span class=\"rnthl rntliteral\">scale_min_temp<\/span> values that we got previously.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Set the chart range and also scale it with an\n\/\/ *100 multiplier to remove the 2 floating-point numbers\nlv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, int(scale_min_temp-1)*100,\nint(scale_max_temp+1)*100);<\/code><\/pre>\n\n\n\n<p>Call the <span class=\"rnthl rntliteral\">lv_chart_refresh()<\/span> function to update all values on the chart.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_chart_refresh(chart); \/\/ Required to update the chart with the new values<\/code><\/pre>\n\n\n\n<p>Create a vertical scale for the chart using the <span class=\"rnthl rntliteral\">lv_scale_create()<\/span> function and place it inside the <span class=\"rnthl rntliteral\">container_row<\/span> aligned vertically on the right.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Create a scale (y axis for the temperature) aligned vertically on the right\nlv_obj_t * scale = lv_scale_create(container_row);\nlv_obj_set_size(scale, 15, SCREEN_WIDTH-90);\nlv_scale_set_mode(scale, LV_SCALE_MODE_VERTICAL_RIGHT);\nlv_scale_set_label_show(scale, true);<\/code><\/pre>\n\n\n\n<p>Set the scale smaller divisions.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Set the scale ticks count\nlv_scale_set_total_tick_count(scale,int(scale_max_temp+2)-int(scale_min_temp-1));\nif((int(scale_max_temp+2) - int(scale_min_temp-1)) &lt; 10) {\n  lv_scale_set_major_tick_every(scale, 1); \/\/ set y axis to have 1 tick every 1 degree\n}\nelse {\n  lv_scale_set_major_tick_every(scale, 10);\/\/set y axis to have 1 tick every 10 degrees\n}<\/code><\/pre>\n\n\n\n<p>Set the scale style and range.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Set the scale style and range\nlv_obj_set_style_length(scale, 5, LV_PART_ITEMS);\nlv_obj_set_style_length(scale, 10, LV_PART_INDICATOR);\nlv_scale_set_range(scale, int(scale_min_temp-1), int(scale_max_temp+1));<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Drawing the Chart<\/h3>\n\n\n\n<p>When you press the chart, it will display a label with the values for the pressed data point.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>lv_obj_add_event_cb(chart, chart_draw_label_cb, LV_EVENT_ALL, NULL);<\/code><\/pre>\n\n\n\n<p>All of that is handled on the <span class=\"rnthl rntliteral\">chart_draw_label_cb()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Draw a label on that chart with the value of the pressed point\nstatic void chart_draw_label_cb(lv_event_t * e) {\n  lv_event_code_t code = lv_event_get_code(e);\n  lv_obj_t * chart = (lv_obj_t*) lv_event_get_target(e);\n  if(code == LV_EVENT_VALUE_CHANGED) {\n    lv_obj_invalidate(chart);\n  }\n  if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {\n    int32_t * s = (int32_t*)lv_event_get_param(e);\n    *s = LV_MAX(*s, 20);\n  }\n  \/\/ Draw the label on the chart based on the pressed point\n  else if(code == LV_EVENT_DRAW_POST_END) {\n    int32_t id = lv_chart_get_pressed_point(chart);\n    if(id == LV_CHART_POINT_NONE) return;\n      LV_LOG_USER(\"Selected point %d\", (int)id);\n      lv_chart_series_t * ser = lv_chart_get_series_next(chart, NULL);\n      while(ser) {\n        lv_point_t p;\n        lv_chart_get_point_pos_by_id(chart, ser, id, &amp;p);\n        int32_t * y_array = lv_chart_get_y_array(chart, ser);\n        int32_t value = y_array&#091;id];\n        char buf&#091;16];\n        #if TEMP_CELSIUS\n          const char degree_symbol&#091;] = \"\\u00B0C\";\n        #else\n          const char degree_symbol&#091;] = \"\\u00B0F\";\n        #endif\n        \/\/ Preparing the label text for the selected data point\n        lv_snprintf(buf, sizeof(buf), LV_SYMBOL_DUMMY \" %3.2f %s \", float(bme_last_readings&#091;id]), degree_symbol);\n        \/\/ Draw the rectangular label that will display the temperature value\n        lv_draw_rect_dsc_t draw_rect_dsc;\n        lv_draw_rect_dsc_init(&amp;draw_rect_dsc);\n        draw_rect_dsc.bg_color = lv_color_black();\n        draw_rect_dsc.bg_opa = LV_OPA_60;\n        draw_rect_dsc.radius = 2;\n        draw_rect_dsc.bg_image_src = buf;\n        draw_rect_dsc.bg_image_recolor = lv_color_white();\n        \/\/ Rectangular label size\n        lv_area_t a;\n        a.x1 = chart-&gt;coords.x1 + p.x - 35;\n        a.x2 = chart-&gt;coords.x1 + p.x + 35;\n        a.y1 = chart-&gt;coords.y1 + p.y - 30;\n        a.y2 = chart-&gt;coords.y1 + p.y - 10;\n        lv_layer_t * layer = lv_event_get_layer(e);\n        lv_draw_rect(layer, &amp;draw_rect_dsc, &amp;a);\n        ser = lv_chart_get_series_next(chart, ser);\n      }\n    }\n    else if(code == LV_EVENT_RELEASED) {\n      lv_obj_invalidate(chart);\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"demonstration\">Demonstration<\/h2>\n\n\n\n<p>Upload the code to your board. Go to <strong>Tools <\/strong>&gt; <strong>Board <\/strong>and select <strong>ESP32 <\/strong>&gt; <strong>ESP32 Dev Module<\/strong>. Then, select the right COM port in <strong>Tools <\/strong>&gt; <strong>Port<\/strong>. Finally, click the upload button.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"36\" height=\"39\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2021\/05\/arduino-ide-2-upload-button.png?resize=36%2C39&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Arduino IDE 2 Upload Button\" class=\"wp-image-146269\" style=\"width:36px;height:auto\"\/><\/figure><\/div>\n\n\n<p>After uploading the code, it will display the chart with one point. Wait 10 seconds to get a second point, 10 seconds more for the third point, and so on.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-LVGL-Display-Temperature-Line-Chart-BME280.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD LVGL Display Temperature Line Chart BME280\" class=\"wp-image-164495\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-LVGL-Display-Temperature-Line-Chart-BME280.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-LVGL-Display-Temperature-Line-Chart-BME280.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Wait until you have the chart filled with the 20 data points. A new value is added every 10 seconds\u2014the chart is automatically updated.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-LVGL-Display-Temperature-Line-Chart-BME280-Demonstration.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD LVGL Display Temperature Line Chart BME280 Demonstration\" class=\"wp-image-164496\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-LVGL-Display-Temperature-Line-Chart-BME280-Demonstration.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-LVGL-Display-Temperature-Line-Chart-BME280-Demonstration.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>You can press on a specific data point to check its precise value.<\/p>\n\n\n\n<p>The serial monitor displays the latest temperature reading as well as the minimum and maximum values from the array.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"695\" height=\"371\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-BME280-line-chart-serial-monitor-temperature-demonstration.png?resize=695%2C371&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 CYD BME280 line chart serial monitor temperature demonstration\" class=\"wp-image-164494\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-BME280-line-chart-serial-monitor-temperature-demonstration.png?w=695&amp;quality=100&amp;strip=all&amp;ssl=1 695w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-CYD-BME280-line-chart-serial-monitor-temperature-demonstration.png?resize=300%2C160&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 695px) 100vw, 695px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned to display sensor data on a line chart with the Cheap Yellow display screen using the LVGL library.<\/p>\n\n\n\n<p>We hope you found this tutorial useful. We&#8217;re preparing more guides about this board, so stay tuned. If you would like to learn more about creating graphical user interfaces using the LVGL library with the ESP32, check out our latest eBook:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><a href=\"https:\/\/randomnerdtutorials.com\/learn-lvgl-esp32-ebook\/\">Learn LVGL: Build GUIs for ESP32 Projects (eBook)<\/a><\/strong><\/li>\n<\/ul>\n\n\n\n<p>Other guides you might like reading:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/cheap-yellow-display-esp32-2432s028r\/\">Getting Started with ESP32 Cheap Yellow Display Board \u2013 CYD (ESP32-2432S028R)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/touchscreen-on-off-button-cheap-yellow-display-esp32-2432s028r\/\">ESP32 Touchscreen On\/Off Button \u2013 Cheap Yellow Display (ESP32-2432S028R)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-cheap-yellow-display-cyd-pinout-esp32-2432s028r\/\">ESP32 Cheap Yellow Display (CYD) Pinout (ESP32-2432S028R)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/lvgl-cheap-yellow-display-esp32-2432s028r\/\">LVGL with ESP32 Cheap Yellow Display Board (ESP32-2432S028R)<\/a><\/li>\n<\/ul>\n\n\n\n<p>To learn more about the ESP32, make sure to take a look at our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/smart-home-ebook\/\" title=\"\">SMART HOME with Raspberry Pi, ESP32, and ESP8266 eBook<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\" title=\"\"><strong>Free ESP32 Guides and Tutorials<\/strong><\/a><\/li>\n<\/ul>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to display temperature from the BME280 sensor on an ESP32 Cheap Yellow Display (CYD) using LVGL (Light Versatile Graphics Library). You\u2019ll learn how to &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 CYD with LVGL: Display Temperature on Line Chart (BME280)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-cyd-lvgl-line-chart\/#more-164489\" aria-label=\"Read more about ESP32 CYD with LVGL: Display Temperature on Line Chart (BME280)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":164591,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-164489","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/12\/ESP32-Cheap-Yellow-Display-BME280-Chart.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/164489","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=164489"}],"version-history":[{"count":9,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/164489\/revisions"}],"predecessor-version":[{"id":170714,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/164489\/revisions\/170714"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/164591"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=164489"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=164489"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=164489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}