button with lcd display free sample

In this tutorial, I’ll explain how to set up an LCD on an Arduino and show you all the different ways you can program it. I’ll show you how to print text, scroll text, make custom characters, blink text, and position text. They’re great for any project that outputs data, and they can make your project a lot more interesting and interactive.
The display I’m using is a 16×2 LCD display that I bought for about $5. You may be wondering why it’s called a 16×2 LCD. The part 16×2 means that the LCD has 2 lines, and can display 16 characters per line. Therefore, a 16×2 LCD screen can display up to 32 characters at once. It is possible to display more than 32 characters with scrolling though.
The code in this article is written for LCD’s that use the standard Hitachi HD44780 driver. If your LCD has 16 pins, then it probably has the Hitachi HD44780 driver. These displays can be wired in either 4 bit mode or 8 bit mode. Wiring the LCD in 4 bit mode is usually preferred since it uses four less wires than 8 bit mode. In practice, there isn’t a noticeable difference in performance between the two modes. In this tutorial, I’ll connect the LCD in 4 bit mode.
Here’s a diagram of the pins on the LCD I’m using. The connections from each pin to the Arduino will be the same, but your pins might be arranged differently on the LCD. Be sure to check the datasheet or look for labels on your particular LCD:
Also, you might need to solder a 16 pin header to your LCD before connecting it to a breadboard. Follow the diagram below to wire the LCD to your Arduino:
All of the code below uses the LiquidCrystal library that comes pre-installed with the Arduino IDE. A library is a set of functions that can be easily added to a program in an abbreviated format.
In order to use a library, it needs be included in the program. Line 1 in the code below does this with the command #include
There are 19 different functions in the LiquidCrystal library available for us to use. These functions do things like change the position of the text, move text across the screen, or make the display turn on or off. What follows is a short description of each function, and how to use it in a program.
TheLiquidCrystal() function sets the pins the Arduino uses to connect to the LCD. You can use any of the Arduino’s digital pins to control the LCD. Just put the Arduino pin numbers inside the parentheses in this order:
This function sets the dimensions of the LCD. It needs to be placed before any other LiquidCrystal function in the void setup() section of the program. The number of rows and columns are specified as lcd.begin(columns, rows). For a 16×2 LCD, you would use lcd.begin(16, 2), and for a 20×4 LCD you would use lcd.begin(20, 4).
This function clears any text or data already displayed on the LCD. If you use lcd.clear() with lcd.print() and the delay() function in the void loop() section, you can make a simple blinking text program:
This function places the cursor in the upper left hand corner of the screen, and prints any subsequent text from that position. For example, this code replaces the first three letters of “hello world!” with X’s:
Similar, but more useful than lcd.home() is lcd.setCursor(). This function places the cursor (and any printed text) at any position on the screen. It can be used in the void setup() or void loop() section of your program.
The cursor position is defined with lcd.setCursor(column, row). The column and row coordinates start from zero (0-15 and 0-1 respectively). For example, using lcd.setCursor(2, 1) in the void setup() section of the “hello, world!” program above prints “hello, world!” to the lower line and shifts it to the right two spaces:
You can use this function to write different types of data to the LCD, for example the reading from a temperature sensor, or the coordinates from a GPS module. You can also use it to print custom characters that you create yourself (more on this below). Use lcd.write() in the void setup() or void loop() section of your program.
The function lcd.noCursor() turns the cursor off. lcd.cursor() and lcd.noCursor() can be used together in the void loop() section to make a blinking cursor similar to what you see in many text input fields:
Cursors can be placed anywhere on the screen with the lcd.setCursor() function. This code places a blinking cursor directly below the exclamation point in “hello, world!”:
This function creates a block style cursor that blinks on and off at approximately 500 milliseconds per cycle. Use it in the void loop() section. The function lcd.noBlink() disables the blinking block cursor.
This function turns on any text or cursors that have been printed to the LCD screen. The function lcd.noDisplay() turns off any text or cursors printed to the LCD, without clearing it from the LCD’s memory.
This function takes anything printed to the LCD and moves it to the left. It should be used in the void loop() section with a delay command following it. The function will move the text 40 spaces to the left before it loops back to the first character. This code moves the “hello, world!” text to the left, at a rate of one second per character:
This function takes a string of text and scrolls it from right to left in increments of the character count of the string. For example, if you have a string of text that is 3 characters long, it will shift the text 3 spaces to the left with each step:
Like the lcd.scrollDisplay() functions, the text can be up to 40 characters in length before repeating. At first glance, this function seems less useful than the lcd.scrollDisplay() functions, but it can be very useful for creating animations with custom characters.
lcd.noAutoscroll() turns the lcd.autoscroll() function off. Use this function before or after lcd.autoscroll() in the void loop() section to create sequences of scrolling text or animations.
This function sets the direction that text is printed to the screen. The default mode is from left to right using the command lcd.leftToRight(), but you may find some cases where it’s useful to output text in the reverse direction:
This code prints the “hello, world!” text as “!dlrow ,olleh”. Unless you specify the placement of the cursor with lcd.setCursor(), the text will print from the (0, 1) position and only the first character of the string will be visible.
This command allows you to create your own custom characters. Each character of a 16×2 LCD has a 5 pixel width and an 8 pixel height. Up to 8 different custom characters can be defined in a single program. To design your own characters, you’ll need to make a binary matrix of your custom character from an LCD character generator or map it yourself. This code creates a degree symbol (°):
If you found this article useful, subscribe via email to get notified when we publish of new posts! And as always, if you are having trouble with anything, just leave a comment and I’ll try to help you out.

You may have used an electronic device with a small Liquid Crystal Display (LCD) which has a textual hierarchical menu system for setting device configuration parameters. If you have tried writing menu code for your Arduino projects, you will recognise the challenge in developing a generic menu system for an open prototyping platform. This is because there are many input and display devices available, and a generic menu system must be independent of whichever input and display devices you wish to use. With our Arduino menu library, this independence is achieved by having the menu manager code use callback methods for handling user input and rendering the menu display.
To keep things simple, all coding examples have been targeted to work with an R3 Arduino Uno/Leonardo/Mega2560, and an LCD keypad shield similar to one illustrated above. There are numerous manufacturers of LCD keypad shields that have the same or similar pin connections, and you must ensure that the sample menu code uses the pin connections that are right for your shield. If the keypad buttons of your shield give different analog readings, you’ll need to make changes to file LcdKeypad.h. Bear in mind that the analog readings are not always consistent, which can lead to the occasional misreporting of a button press. Once you become familiar with the menu library, adapting it for use with other input and display devices should be straight-forward.
With numerous menu libraries readily available, why use this Arduino menu library? We think it is easier to use thanks to our online code generator, and has better memory efficiency with its use of PROGMEM. Watch the short video clip below and see for yourself.
You can use the downloaded sample Arduino project as a starting point for your own coding requirements. You will need to write your own code in the body of method processMenuCommand(byte cmdId) to determine what must be done when a menu item is selected. The cmdId parameter is the Id you associate with a menu item in your menu Xml file. Callback method getNavAction() handles user input, and callback method refreshMenuDisplay(byte refreshMode) renders the menu. To work with other input and display devices you’ll need to re-write the code in these methods. Some LCD keypad shields are not suited for hardware PWM backlight control, and as such the coding example uses a soft PWM alternative.
The Select button on the LCD shield starts/stops a timer, with a long press resetting the timer. A long press of Up enters the menu. Up/Down/Right buttons are for navigating the menu, and Select for choosing a menu item. When an item is selected, Up/Down are used for changing values. When the Reset menu item is displayed, a long press of Select loads default configuration values. Digital pin 2 is used for activating a beeper for the alarm. Examining the source should give you good insight for using the menu system in your own projects. If you find this Arduino menu library guide useful, please share it.
All our hackatronics projects are free for personal use, and there are many more in the pipeline. If you find our projects helpful or useful, please consider making a small donation to our hackatronics fund using the donate buttons on our web pages. Thank you.

After all variables are defined we take care about the setup function which will only run once at the start of the microcontroller. First we define the baud rate to 9600 which means that we can see values in the serial monitor with a data rate of 9600 bits per second. The baud rate defined in the setup function and in the serial monitor has so be synchronous.
Then we initialize the 4 buttons with their pins and we enable the internal pull-up resistor so that we do not need an additional resistor for our circuit.
For the setup function we want to write a short text to the displays. First we clear the complete display and set the cursor in the second line on digit number 4. Here we print the first part of the text. Then we place the cursor in the next line and because the second part of the test is longer we set the cursor to the 3 digit number and print the second part of the text. The text is shown 5 seconds and after that time the display is cleared.
Now we enter the whole loop function which is of course processed over and over. The first 4 lines of the loop function are to read the current state of the buttons. If a button is pressed, the variable buttonState is LOW and we react in the following with the reaction depending on what button was pressed and then run the printScreen function which will be explained in the following section of this menu tutorial.
First we discuss the buttonStateLeft and buttonStateRight statement. We enter the first if query if the button is pressed and clear the screen to display the new screen without the old information. For the left button we decrease the pointer to show the screen before but when the pointer is already on the first screen (currentScreen == 0) we want to display the last screen to get a never ending rotation which you know from your mobile phone. For the right button we want to display the next screen. That is why we increase the variable currentScreen. If we reach the last screen we show the first screen also to get the functionality of a never ending loop in screens.
Now we want to discuss what happen if we push the button up or down. We first clear the screen too and then either increase or decrease the value of the current screen. The corresponding array which we defined earlier stores the changes values. For each screen we can therefore change the value.
The printScreen function has a lot of rows but is pretty easy and straight forward. First we check if we are in the last screen number 3. If so we want to display every number and unit line per line. Therefore we set the cursor in the first line and print the number name, number and unit. We do this line by line by changing the cursor.
If we are not in the last screen we want to display the title “MENU TOTORIAL” in the first line and use the last two lines to display the number name, number and unit.
I know that such tutorials can be a little bit dry but in the following video you see the button menu in action. You see me flipping through all screens and changing the values. Every time a value is changes is is also be stored and not overwritten from the initial values.

The 16x2 LCD And Keypad Shield is very simple to use because it"s fully compatible with the Arduino "LiquidCrystal" library. You can initialise the LCD and display messages on it with just a few lines of code, but it also gives you the flexibility to do more advanced projects such as display menu items and select them using the buttons.
The LCD & Keypad Shield requires a good 5V power supply to ensure the backlight fully illuminates and the display contrast is high, and if you power your Arduino from USB with the LCD Shield attached you may experience a voltage drop over the USB cable. If you have trouble with display contrast or backlight brightness, try attaching a power supply of around 7 to 9Vdc to the 2.1mm DC jack on the Arduino. A typical symptom in an undervoltage situation is that one line of the LCD will show pale rectangles in place of the characters, and the other line will show nothing at all. The Arduino may even continue running normally because it"s quite happy at just 4V or so, but the LCD & Keypad Shield won"t function.
All the hard work of interfacing with the LCD Shield is handled by the LiquidCrystal library, which is included as part of the official Arduino distribution. You can check whether you have it installed by starting up the IDE and looking under Files -> Examples -> LiquidCrystal. If it exists, you"re good to go.
The LCD Shield includes 5 buttons designed for use as navigational or control input. The buttons are arranged in a handy pattern and referred to as UP, DOWN, LEFT, RIGHT, and SELECT, but of course it"s totally up to your sketch to decide what to do when any particular button is pressed.
All the buttons are connected to a single analog input, A0, using a chain of resistors that causes a different reference voltage to be applied to A0 depending on which button is pressed. This section of the shield schematic shows the input buttons and associated resistors:
As you can see, if no button is being pressed the voltage on A0 will be pulled all the way up to 5V by the 2K resistor called R6. In that situation none of the other resistors have any effect at all, and the analog reading on A0 will be hard on the upper limit of 1023. Therefore if you perform an analogRead() call on A0 and it returns 1023 (or any value above about 1000) you know that no buttons are being pressed.
Now consider what happens if the "DOWN" button is pressed. Now A0 is being presented with a voltage that is divided between the 2K resistor that is trying to pull it up to 5V, and the 330R and 620R resistors in series (totaling 950R) that are trying to pull it down to 0V. The voltage presented to A0 in that case is about 1.61V, which means if you perform an analogRead() on A0 it will return a value of about 329. So if you read a value of about 329 from A0 you know the "DOWN" button is being pressed.
This is a neat way to provide a whole set of input buttons while only using up one of the I/O pins on your Arduino, leaving more pins free for use in your project.
The extensive example below combines a number of techniques to demonstrate how to show messages on the LCD, read from the buttons, and change the display message depending on which buttons are pressed.

All I had to do here was add in the three digitalRead() calls, and make sure I accounted for the fact that if all buttons were low, we should reset the timer (lastDebounceTime = currentTime) and set all previous states to low. I also store millis() in currentTime.
There are three sections. Yes, I could have moved them into their own functions, but for sake of simplicity I kept the three main button algorithms in here.if((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)){
This first one handles when menuButtonPressedis HIGH, or when the menu button is pressed. It also checks to make sure the previous state was LOW, so that the button had to be released before it was pressed again, which stops the program from constantly firing the same event over and over again.
It then checks that if the menu is not active, it activates it. It will print the first option selected (which is the first item in the menuOptions array by default. If you press the button a second or third (etc) time, you"ll get the next option in the list. Something I could fix is that when it gets to the end, it cycles back to the beginning. This could read the length of the array and make cycling back easier if you changed the number of options, but this was simple for now.
The last little section (//Prints the menu) obviously prints the menu, but it also sets the previous state to HIGH so the same function won"t loop (see my note above about checking if the button was previously LOW).// menuSelect is pressed, provide logic
if((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)){
This bit of code handles the menuSelectPressed button in the same way, except this time we just fire the ToggleOptionSelected() function. As I said before, you could change this function so it does more, but that"s all I need it to do.
This function handles the menuSave button, which just exits the menu. This is where you could have a cancel or save option, maybe do some cleaning up or save to the EEPROM. I just print "Menu exited" and set the button state to HIGH so it doesn"t loop.if(menuMode && menuNeedsPrint){
// We have printed the menu, so unless something

In this Arduino touch screen tutorial we will learn how to use TFT LCD Touch Screen with Arduino. You can watch the following video or read the written tutorial below.
The next example is controlling an RGB LED using these three RGB sliders. For example if we start to slide the blue slider, the LED will light up in blue and increase the light as we would go to the maximum value. So the sliders can move from 0 to 255 and with their combination we can set any color to the RGB LED, but just keep in mind that the LED cannot represent the colors that much accurate.
The third example is a game. Actually it’s a replica of the popular Flappy Bird game for smartphones. We can play the game using the push button or even using the touch screen itself.
As an example I am using a 3.2” TFT Touch Screen in a combination with a TFT LCD Arduino Mega Shield. We need a shield because the TFT Touch screen works at 3.3V and the Arduino Mega outputs are 5 V. For the first example I have the HC-SR04 ultrasonic sensor, then for the second example an RGB LED with three resistors and a push button for the game example. Also I had to make a custom made pin header like this, by soldering pin headers and bend on of them so I could insert them in between the Arduino Board and the TFT Shield.
As the code is a bit longer and for better understanding I will post the source code of the program in sections with description for each section. And at the end of this article I will post the complete source code.
I will use the UTFT and URTouch libraries made by Henning Karlsen. Here I would like to say thanks to him for the incredible work he has done. The libraries enable really easy use of the TFT Screens, and they work with many different TFT screens sizes, shields and controllers. You can download these libraries from his website, RinkyDinkElectronics.com and also find a lot of demo examples and detailed documentation of how to use them.
Next we need to define the fonts that are coming with the libraries and also define some variables needed for the program. In the setup section we need to initiate the screen and the touch, define the pin modes for the connected sensor, the led and the button, and initially call the drawHomeSreen() custom function, which will draw the home screen of the program.
So now I will explain how we can make the home screen of the program. With the setBackColor() function we need to set the background color of the text, black one in our case. Then we need to set the color to white, set the big font and using the print() function, we will print the string “Arduino TFT Tutorial” at the center of the screen and 10 pixels down the Y – Axis of the screen. Next we will set the color to red and draw the red line below the text. After that we need to set the color back to white, and print the two other strings, “by HowToMechatronics.com” using the small font and “Select Example” using the big font.
Next is the distance sensor button. First we need to set the color and then using the fillRoundRect() function we will draw the rounded rectangle. Then we will set the color back to white and using the drawRoundRect() function we will draw another rounded rectangle on top of the previous one, but this one will be without a fill so the overall appearance of the button looks like it has a frame. On top of the button we will print the text using the big font and the same background color as the fill of the button. The same procedure goes for the two other buttons.
Now we need to make the buttons functional so that when we press them they would send us to the appropriate example. In the setup section we set the character ‘0’ to the currentPage variable, which will indicate that we are at the home screen. So if that’s true, and if we press on the screen this if statement would become true and using these lines here we will get the X and Y coordinates where the screen has been pressed. If that’s the area that covers the first button we will call the drawDistanceSensor() custom function which will activate the distance sensor example. Also we will set the character ‘1’ to the variable currentPage which will indicate that we are at the first example. The drawFrame() custom function is used for highlighting the button when it’s pressed. The same procedure goes for the two other buttons.
So the drawDistanceSensor() custom function needs to be called only once when the button is pressed in order to draw all the graphics of this example in similar way as we described for the home screen. However, the getDistance() custom function needs to be called repeatedly in order to print the latest results of the distance measured by the sensor.
Here’s that function which uses the ultrasonic sensor to calculate the distance and print the values with SevenSegNum font in green color, either in centimeters or inches. If you need more details how the ultrasonic sensor works you can check my particular tutorialfor that. Back in the loop section we can see what happens when we press the select unit buttons as well as the back button.
Ok next is the RGB LED Control example. If we press the second button, the drawLedControl() custom function will be called only once for drawing the graphic of that example and the setLedColor() custom function will be repeatedly called. In this function we use the touch screen to set the values of the 3 sliders from 0 to 255. With the if statements we confine the area of each slider and get the X value of the slider. So the values of the X coordinate of each slider are from 38 to 310 pixels and we need to map these values into values from 0 to 255 which will be used as a PWM signal for lighting up the LED. If you need more details how the RGB LED works you can check my particular tutorialfor that. The rest of the code in this custom function is for drawing the sliders. Back in the loop section we only have the back button which also turns off the LED when pressed.
In order the code to work and compile you will have to include an addition “.c” file in the same directory with the Arduino sketch. This file is for the third game example and it’s a bitmap of the bird. For more details how this part of the code work you can check my particular tutorial. Here you can download that file:
![]()
I want to be able to toggle the altitude from meters to feet, the temperature from Celsius to Fahrenheit, and the pressure from absolute to sea level pressure using a tactile push button.

This tutorial shows how to use the I2C LCD (Liquid Crystal Display) with the ESP32 using Arduino IDE. We’ll show you how to wire the display, install the library and try sample code to write text on the LCD: static text, and scroll long messages. You can also use this guide with the ESP8266.
Additionally, it comes with a built-in potentiometer you can use to adjust the contrast between the background and the characters on the LCD. On a “regular” LCD you need to add a potentiometer to the circuit to adjust the contrast.
Before displaying text on the LCD, you need to find the LCD I2C address. With the LCD properly wired to the ESP32, upload the following I2C Scanner sketch.
After uploading the code, open the Serial Monitor at a baud rate of 115200. Press the ESP32 EN button. The I2C address should be displayed in the Serial Monitor.
Displaying static text on the LCD is very simple. All you have to do is select where you want the characters to be displayed on the screen, and then send the message to the display.
The next two lines set the number of columns and rows of your LCD display. If you’re using a display with another size, you should modify those variables.
Then, you need to set the display address, the number of columns and number of rows. You should use the display address you’ve found in the previous step.
To display a message on the screen, first you need to set the cursor to where you want your message to be written. The following line sets the cursor to the first column, first row.
Scrolling text on the LCD is specially useful when you want to display messages longer than 16 characters. The library comes with built-in functions that allows you to scroll text. However, many people experience problems with those functions because:
The messageToScroll variable is displayed in the second row (1 corresponds to the second row), with a delay time of 250 ms (the GIF image is speed up 1.5x).
In a 16×2 LCD there are 32 blocks where you can display characters. Each block is made out of 5×8 tiny pixels. You can display custom characters by defining the state of each tiny pixel. For that, you can create a byte variable to hold the state of each pixel.
In summary, in this tutorial we’ve shown you how to use an I2C LCD display with the ESP32/ESP8266 with Arduino IDE: how to display static text, scrolling text and custom characters. This tutorial also works with the Arduino board, you just need to change the pin assignment to use the Arduino I2C pins.
We hope you’ve found this tutorial useful. If you like ESP32 and you want to learn more, we recommend enrolling in Learn ESP32 with Arduino IDE course.

The display controller, UC1611, is no longer available in the form of bonding on the PCB which is how Crystalfontz has used it for this design. We are designing a drop-in replacement that uses the UC1611 heat seal package, which will continue to be supported, instead of the PCB bonding package.
This component package change requires us to alter the PCB by moving some components around so that the heat seal tool can be used without causing damage to any components.
The firmware has been updated with new features including Live Display, analog to digital interpretation on GPIO5 and GPIO6, closed loop temperature control. The new datasheets will have more information on these changes.
This is intended as a drop-in replacement. If the new features listed for the 835 are not wanted, a field upgrade kit that supports the new controller without the new features is available.
Fixed an issue with the USB data handling, primarily affecting the command 40 (0x28) subcommand 2 “Send Image Data to Display from Host.” Other USB data throughput improvements were also made.
As part of our continuous improvement process, CFA635 KS, CFA735 KT, and CFA835 display modules with the ATX (power on / off / reset) functionality enabled will have their RS-232 SERIAL cable bundle options changed from a serial cable and WRPWRY24 to a serial cable and a WRPWRY25. With TX (power on / off / reset) functionality enabled, additional
The WRPWRY24 is a power only cable and suitable for powering the CFA635, CFA735, and CFA835 when properly configured. When the displays are configured for ATX (power on / off / reset) functionality additional connections are necessary for proper operation. The WRPWRY25 offers the additional connections.

Printing “Hello, world!” is usually the first thing that programming tutorials will have you do in a new language. This guide starts by blinking an LED, but now we’re going to print out real text using a Liquid Crystal Display (LCD).
Character LCDs are designed to show a grid of letters, numbers and a few special characters. This makes them great for printing data and showing values. When current is applied to this special kind of crystal, it turns opaque. This is used in a lot of calculators, watches and simple displays. Adding an LCD to your project will make it super portable and allow you to integrate up to 32 characters (16 x 2) of information.
Pin 3 on the LCD controls the contrast and brightness of the LCD. Using a simple voltage divider with a potentiometer, the contrast can be adjusted. As you rotate the knob on the potentiometer, you should notice that the screen will get brighter or darker and that the characters become more visible or less visible. The contrast of LCDs is highly dependent on factors such as temperature and the voltage used to power it. Thus, external contrast knobs are needed for displays that cannot automatically account for temperature and voltage changes.
If you look closely at the characters on the LCD, you will notice that they are actually made up of lots of little squares. These little squares are called pixels. The size of displays is often represented in pixels. Pixels make up character space, which is the number of pixels in which a character can exist.
The LCD has 16 pins, and it is polarized. The pins are numbered from left to right, 1 through 16. The LCD utilizes an extremely common parallel interface LCD driver chip from Hitachi called the HD44780. Thankfully, the Arduino community has developed a library to handle a great deal of the software-to-hardware interface. Below is a list of each of the pins on the LCD.
If you are not seeing any characters, are seeing barely visible characters, or see just white rectangles, then you need to adjust the contrast. Twist the potentiometer very slowly until you can clearly read the display. If you reach the end of the potentiometer"s rotation, try twisting in the opposite direction.
“Begin” the LCD. This sets the dimensions of the LCD that you are working with (16 x 2). It needs to be called before any other commands from the LCD library are used.
Move the cursor to the first space of the lower line lcd.setCursor(0,1);, then print the number of seconds that have passed since the RedBoard was last reset.
LiquidCrystal LCD_name(RS_pin, enable_pin, d4, d5, d6, d7);As with servos, you need to create an LCD object and give it a name (you can make more than one). The numbers in the brackets are pins on the RedBoard that connect to specific pins on the LCD.
lcd.setCursor(0,0);Move the cursor to a point on the 16x2 grid of characters. Text that you write to the LCD will start from the cursor. This line is starting back at position (0,0).
Show hours, minutes and secondsTry adding some code so that the display shows the hours, minutes and seconds that have passed since the RedBoard was last reset.
Count button pressesBy adding a button to the circuit, you can count the number of times the button was pressed or have the button change what the LCD is displaying. There could be many pages of information.
Rectangles in first rowIf you see 16 rectangles (like “█”) on the first row, it may be due to the jumper wires being loose on the breadboard. This is normal and can happen with other LCDs wired in parallel with a microcontroller. Make sure that the wires are fully inserted into the breadboard, then try pressing the reset button and adjusting the contrast using the potentiometer.
![]()
In this article, I will show you how to communicate with a DWIN display using the serial port of a computer. I got the privilege to receive two displays from the manufacturer for a review in exchange for content made about them. I accepted their offer because I have been always interested in human-machine interfaces (HMI) and I could see that I can use their displays in many of my upcoming projects as well as I can upgrade some of my older projects using the displays.
So, finally, after climbing the steep learning curve, the content is ready for consumption. If you better like listening to the instructions, I made a video with similar content as you can see below.
These displays communicate via serial communication through their TX and RX pins. This makes it simple to connect them to microcontrollers without implementing difficult i2c or SPI libraries. Just two wires and the power supply rails (+5 V and GND), that’s all.
The displays are based on the T5L ASIC (application-specific integrated circuit) which is developed in-house by DWIN. It is a dual-core chip: one core handles the OS and the other takes care of the GUI.
The software is created with DWIN’s own developing environment called DGUS. This software creates the binary files for controlling, configuring and handling the display as well as it can communicate with the display via the serial port. The display handles images, fonts, icons and other visual stuff. All these features are compiled into a binary (BIN) file which is uploaded to the display. The uploading of the resources (at least on the displays I have) can be done via an SD card. Certain files can be uploaded via serial connection as well, but generally, the SD card upload method has to be used.
Here I will try to summarize all the information that is needed to understand how to set the display up for a basic operation. I had difficulties understanding the principles of the display when I first looked at it but the more time I spent on trying to understand it the clearer the things became.
Once you installed the driver and unpacked the DGUS tool into a folder, you can start working with the display. Keep in mind that at the end of the process, the config files will need to be copied on an SD card. The SD card has to be formatted in a specific way described by the manufacturer. The display then can read the SD card properly. More on this a bit later below.
After establishing a project you will see a new tab called Touch and display config. This is where we will configure the display. But before that, let’s move back to the Welcome tab and generate the fonts.
Select the #0 word bank generating option from the DGUS config tool’s Welcome tab. This will open a new window called “Font Special Generator”. Here you should select your favourite font, then select the widest possible character (W or M), and adjust the two scales and two shifts to fit the letters on the display properly. Once you are satisfied, click on Create and wait until the process is done. The generated file will be placed in the root folder of your DGUS tool. Go to the root folder of the DGUS tool and copy the freshly created .HZK file into the DWIN_SET folder of your project folder.
Then we start building up the GUI. This display works in an initially unusual way if you are used to the typical WYSWYG editors where you can drag and drop the different controls over a specified area and then configure them. With this type of editor, you have to first draw the controls in an image editing software (Paint, GIMP, Photoshop…etc.), then create areas over the image and assign a certain behaviour to these areas. This was very unusual for me in the beginning but once I understood the principles, it actually all made sense.
This exercise will only have a single page, multiple pages will be shown in future exercises. To create a background file, the image that will be shown on the display, there are a few rules.
First, the file name has to start with two zeroes, for example, you can name the file as “00_background.jpg”. Then, this file has to be loaded into the DWIN ICL Generator and an ICL file has to be generated from it. Here comes another trick: the ICL file that you just generated has to start with the number “32”, for example, call it “32.ICL”.
If I understood correctly, the display will recognize the different configuration files and their purpose by these two numbers at the beginning of their file name, so it is important to name them properly. Once this is done, we can start filling up our picture in the editor with functionalities such as buttons, sliders, variables, icons, curves and so on.
In this simple demo, I want to show you how we can send some data from the serial port to the display and how we can translate the interaction with the display (e.g. touching it) into a message on the serial port.
To be able to communicate with the display, before doing anything we must understand how the display communicates. As I said, it communicates via serial communication. It uses hexadecimal (HEX) characters to send and receive information. There are two types of operations: reading and writing.
There are two things inside the display that can be manipulated: the description pointers (SP) and the variable pointers (VP). They sound intimidating in the beginning but actually, they are very simple. Both SP and VP are pointing at RAM addresses, each address (for example 0x5000) has two bytes: a high byte and a low byte. The description pointers point at RAM spaces where the properties of a control is stored. These properties are for example the X and Y position of a control element, the colour of it or other properties. So, you can manipulate these things through the serial port by accessing the control through its SP address. The VP addresses point at different variables. For example, you can send a number from the serial port to the display by sending the value to a VP address that is defined for a control. Also, you can read these VP addresses using the serial port and fetch the values. A crucial thing to remember is that you have to carefully select the address of both of these variables. If the addresses are not planned carefully enough, two addresses can overlap and they will cause you trouble.
54 65 73 74 20 74 65 78 74: Data submitted to the display. In this case, this series of HEX values mean “Test text” in ASCII. Therefore in this demo, we will send this to a text variable on the display. [length = 9 bytes]
I felt it simpler the look at the above series of numbers this way:[Header] [Number of bytes] [Command] [VP/SP Address] [Actual data sent to the display]
The header is always the same, whatever you do. The number of bytes is the length of [Command] + [VP/SP Address] + [Actual data sent to the display] in bytes. The command is either read (83) or write (82) because you can either read or write a value. The VP/SP Address is determined by you in the DGUS software and the data you send to the display is also determined by you.
There will be one field on the display that receives the raw output value of an ADC channel of the Arduino microcontroller. In this demo, I will emulate this by manually sending the number to the display via the serial port. This will be the “receiving part” (Serial→ DWIN) in the example. The sending part (DWIN → Serial) will be a slider that can change a value between 0-1000. The value of the slider will be shown on the display as well as it will be sent to the serial port. I also add a button that will turn an LED on and off.
To accommodate the above functions, I drew a very low-budget design image in GIMP. Both the ADC value and the slide value will be displayed in one of those blue areas. The display can print texts, numbers…etc., so all we will need to do is to place the text over the blue areas and then send the values to the corresponding VP addresses. Then we have that green rectangle which will be functioning as the slider. I also drew a small box that will indicate the position of the slider. And the final item will be that big dark orange/brown button with the “LED” text on it. Pressing it will toggle the LED in a future demonstration. I will implement the handing of the button press in Arduino because it is more straightforward for me.
To add a field to the display that shows the value of a variable, go to Display Control and select the “123 Data Variable Display” icon. This will allow you to draw a rectangle anywhere over the display area and this rectangle will give place to the numbers.
A background picture used as the control panel. The blue fields will accommodate numbers printed by the display, the green line will act as a slider and the dark orange/brown button will toggle an LED on or off.
The above exercise has to be completed twice: once for the ADC value and once for the slider value. I selected the “123 Data Variable Display” icon and drew a rectangle over each blue field on the display. These boxes are where the variables will be printed.
Once again, the most important thing here is to give a proper VP address to this field. Always keep track of each control’s VP address and be careful not to define them in the way that they overlap with each other.
The slider variable parameters are shown on the right side of this text block. I already explained all the parameters for the ADC variable and they are almost the same here. Since this is a different value, it needs another address. I put the variable on the 1000 VP address. This means that when the slider is moved, it will have to write its position to the 1000 VP address and we also know that if the display sends something to the serial with the 1000 VP address then it comes from this variable that represents the position of the slider.
Then we add the slider by adding a “Drag Adjustment” control over the green bar on the display. I actually made it a bit narrower than the size of the display.
Once the control is added to the display, we can adjust its settings. Here, I also chose the 1000 VP address. This is very important! Why I did this is because when I move the slider, then the display will put the corresponding value in the 1000 address. Since the slider variable is also tied to this address, it will get this value and it will display it on the display as a human-readable number. Furthermore, you can see that I checked the “Data auto-uploading” checkbox. This means that whenever I interact with the control, the display will send out the value of the variable under the 1000 VP address through its serial connection. So, as I mentioned above, when we see a message from the display coming from the 1000 address, we will know that the value in that message is the position of the slider. The dragging mode does not need any explanation, neither the “start value” nor the “terminated value”. I think that this is a mistranslation, I would call this parameter the final value or max value.
Finally, we add the button area over the “LED” text with the orange/brown background. First, let’s select the Touch Control menu and select the “Return Key Code” icon. Probably this is not the most efficient way of doing this, but I found it very simple and I can also easily customize the message to be sent.
When the button is pressed, the display will send out a message through the serial port whose value is "0001” and which is coming from the 3000 VP address. Therefore, we can prepare our code on the microcontroller to listen to the 3000 VP address and see when the value 0001 is being read from the address. Then we can very easily write a code that toggles an LED when the above message is received by the MCU.
Here comes a little trick that I needed to discover myself because I could not find an explanation for it. So, first I could not get any reply from the display on the serial terminal whenever I interacted with it. If I sent a command to the display and read the VP address manually, I could see that the value of my variable changed in a way I wanted to, but I could not get it to show up automatically on the serial terminal. Despite the fact that the “Data auto-uploading” was checked in!
It turned out that despite the fact that I enabled the “Data auto-uploading” in the editor, it was not enabled globally in the config file of the display. To enable it, go to settings and click on the DGUS icon.
Click on the CFG Edit tab. Then, on the left side, you can see an option called “Touch-sensitive Variable Changes Update”. For some weird reason, this is “Non-auto” by default. Change it to “Auto”. Also, if you are bothered by the beeping sound of the display whenever you touch it, change the “Touch sound” to “Off”. Furthermore, you can play around with the “Power-on Display Direction”. In my case, I left it at “0°” because I use the display in portrait mode in an orientation where the serial connector is at the bottom of the display and the SD card reader is at the top. Otherwise, I would use 90° or 270° depending on how I want to rotate the display in landscape mode. Once you chose the settings you want, click on “New CFG” and save the file named as T5LCFG.CFG in the DWIN_SET folder of your project. Later on, you will have to copy this file onto an SD card, so it is better to keep everything together in the same folder.
DGUS configuration editor - After choosing your settings, save the file named as T5LCFG.CFG using the “New CFG” button in the bottom right corner. Place the created CFG file in the DWIN_SET folder of your project.
But, before doing anything, please DO NOT hot-swap the SD card in the display. First, remove all power (screen is OFF), then plug in the SD card to the slot, and then connect the display to a power source. Otherwise, you might damage the display. Also, you cannot use the display’s SD card slot as a card reader to upload the config files to the display. You will need a separate card reader!
Once all the files are on the SD card under the DWIN_SET folder, put the card into the display while the display is OFF! After the card is inserted, you can connect the display to a power source. If everything is correct, you should see a blue display that is showing you the progress of the uploading from the SD card to the display. It shows you which file is being transferred at the moment and at the end of the process, there will be a message at the top of the screen (2nd line) which says:SD Card Process… END !
Once you see this message, unplug the display from the power source and then remove the SD card. Now, without the SD card in the slot, power up the display again. If you followed my instructions properly, you should see the background picture you have uploaded and you should be able to interact with the display.
From this point, you can upload modified code to the display via USB, but only the files starting with 13, 14 and 22 numbers. I could not find a way to update everything on the display via USB, so if you want to make a change, it is better to stick to the SD card uploading method. The USB connection is used for communicating with the display but not programming it!
We can see the header (5A A5) as usual, then we see that six bytes are the total amount of data (06), a reading (83) was performed, the data comes from the (1000) VP address and it is 1 word long (01), and the returned data is (026D). 026D is a hexadecimal value; converting it to decimal gives us 621 which is the same number we see on the display. Also, to check the length: [83] + [1000] + [01] + [026D] → 1+2+1+2 = 6. We indeed received 6 bytes.
Notice that I had to send the above values as 0x5A 0xA5 0x5 0x82…etc, but that is just because of how RealTerm processes the values. Also notice that I have received data (5A A5 03 82 4F 4B) from the display after sending the command. This is just some sort of "acknowledging” message from the display.
First I had to send the header (5A A5), then I sent the number of bytes (05), then the write command (82), then the VP address (20 00), and then the value (03 DB). 03DB is 987 in decimal which is the same number which showed up on the display after I sent it to the command.
987 decimal is 0x03 0xDB in HEX. Please notice that the text shown in the terminal is the acknowledging message. The value sent to the display is in the center text box.
Initially, it was a bit difficult to understand the principles of these DWIN displays. But after some time, I got the hang of it and I started to understand how to work with the display. They are really cheap but powerful devices and they can serve a lot of projects. In exchange for their extremely good value-to-performance ratio, you pay a bit more in time while learning how to work with these displays.
I have many projects in my head where I can use this display, so I will make a YouTube playlist for my tutorials on these DWIN displays and I will gradually add more and more videos to it.

This is a very popular LCD Keypad shield for Arduino and other variants. It includes a 2x16 LCD display and 6 momentary push buttons. Pins 4, 5, 6, 7, 8, 9 and 10 are used to interface with the LCD. Just one Analog Pin 0 is used to read the five pushbuttons. The LCD shield supports contrast adjustment and back-lit on/off functions. It also exposes five analog pins with DFRobot color code for easy analog sensor plugging and display. The on board LED indicates power on.
This lcd arduino shield has 5 keys — select, up, right, down and left which allow you move through menus and make selections straight from one board attached to yourArduino project without requiring a massive tower of shields.
This design allows you keep connecting sensors to the rest of the pins, and use it for monitoring or menu selection with the push buttons even for gaming. Project applications require testing or debugging. Displaying information right away help on most occasions when a computer is not at reach. If you are planning to build something not attached to a computer and you need to check what is going on when you place it on position, this addition will prove very valuable to make sure the program is running well.
The used LCD pins are not exposed on top side of the board leaving only the unused ones. This way, conflict with LCD pins on top of the board will not happen anymore. This design includes a APC / Bluetooth v3 socket to enable you data transmission with your robot.
Ms.Josey
Ms.Josey