Introduction
Requirements
Step 1: Determine the Communication Interface
In this tutorial , we will see how to connect Stone HMI Display to ESP32 using ESP-IDF. We will control an LED connected to ESP32 using buttons on the display, and we will print some numeric values on the display.
For this tutorial, I will be using the ESP32 WROOM controller . HMI displays usually communicate using UART , so to control the display, all we need is a controller with a UART peripheral, which is actually very common.
We have covered How to use UART in ESP32 using ESP-IDF . So if you haven’t seen it yet, I recommend you to watch it.
Let’s start with the connection
Connection instructions
The HMI Stone display has a connector header to connect to the microcontroller. But the spacing between the pins is too wide, I couldn’t find a suitable male header. The display comes with a USB-UART board that can also be used to power the display.
After doing some continuous testing, I found that the pins of this USB-UART board can also be used as TX and RX pins. The same schematic is shown below
The HMI display communicates in RS232 format and to convert it to TTL I am using RS232 to TTL converter. The MCU is connected to the display through this converter as shown below.
Note that between the MAX232 converter and the USB-UART board there is a cross connection TX->RX and RX->TX. But between the MCU and the MAX232 converter there is a straight connection , TX->TX and RX->RX.
The MAX232 needs to be supplied with 5V, as it will malfunction at 3.3V. Additionally, the ESP32 board has an on-board LED that is connected to the GPIO2 pin.
Design Guide
Below is an image from Stone Designer that includes all the elements used in the Design.
There are 3 Group
- Label 1 indicates the LED status
- Label 2 has a fixed string “VALUE =” and does not change
- Label 3 will be updated with the value from the Integer Variable.
There are 2 buttons, LED01 is the ON button and we will program it to turn the LED ON. LED02 is the Off button and it will turn the LED OFF.
By default, we will first create a project using the examples provided in the IDE. Later we will modify it according to our needs.
- First we will create a new Espressif IDF project
- Then name this project and click next
- Check “Create project using one of the templates”
- go to Peripherals -> uart and select “uart_async_rxtxtasks”
- The project name will be modified later, so make sure you change it back.
- Click finish to create the project
The example we chose above is the simplest method of sending and receiving data, i.e. using blocking mode.
view code
When the button on the display is pressed, it sends data via UART. The data sent by the HMI Display is shown below:
Basically we get 12 bytes of fixed data and the rest depends on the name we have given to the button. In this tutorial I have named the button as LED01 and LED02 , so the total data sent by the display will be 12 Bytes + 5 Bytes for button name + 1 byte for value = 18 Bytes.
We can write a simple UART receive task to receive data and then check the button name in the received data. This task will run every 200 milliseconds so that we don’t have much delay after pressing the button.
const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 200 / portTICK_RATE_MS);
If we receive the data successfully, we check the node name present in the received data.
if (strncmp((char *)(data+7), "LED01", 5) == 0)
{
gpio_set_level(LED, 1);
TxData = (char *)malloc(100);
int len = sprintf(TxData, "ST<{\"cmd_code\":\"set_text\",\"type\":\"label\",\"widget\":\"label1\",\"text\":\"LED ON\"}>ET");
uart_write_bytes(UART_NUM_2, TxData, len);
free(TxData);
}
- Here we will check if the received data contains the string “ LED01 ” which is actually the name of the ON button.
- Note that we are checking the node name from position 7 , as I explained above that the first 7 bytes are constant, so the node name starts at position 7 .
- If the string is found it means the ON button was pressed, we will continue.
- First we will set the LED pin HIGH.
- Then send the text “LED ON” to label 1 indicating that the LED is ON.
To send text to the label, we used the command given in the display’s manual. Below is an image from the manual showing this command.
ST<{"cmd_code":"set_text","type":"label","widget":"label","text":"Hello Stone"}>ET
ST<{“cmd_code”:”set_text”,”type”:”label”, “widget”:”label”,”text”:”1234567890″}>ET
Sprintf is simply used to copy the string into the TxData buffer, which is then sent over the UART .
Similar to the ON button, we also check the OFF button and proceed accordingly. Below is the complete code related to the buttons.
else if (strncmp((char *)(data+7), “LED02”, 5) == 0)
{
gpio_set_level(LED, 0);
TxData = (char *)malloc(100);
int len = sprintf(TxData, “ST<{\”cmd_code\”:\”set_text\”,\”type\”:\”label\”,\”widget\”:\”label1\”,\”text \”:\”LED OFF\”}>ET”);
uart_write_bytes(UART_NUM_2, TxData, len);
free(TxData);
}
We also need to send the Integral value to another label we created on the screen. To do so, I will increment a variable, then convert its value to Ascii format and send it to the label.
I have assigned Tx task for this purpose as shown below.
static void tx_task(void *arg)
{
while (1)
{
TxData = (char *)malloc(100);
int len = sprintf(TxData, "ST<{\"cmd_code\":\"set_text\",\"type\":\"label\",\"widget\":\"label3\",\"text\":\"%d\"}>ET", num++);
uart_write_bytes(UART_NUM_2, TxData, len);
free(TxData);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
- Here we will first allocate memory for TX data buffer
- Then save the command to the TxData buffer with the text field as the format specifier of the integral value (%d)
- The value stored in this identifier is the value of the variable num.
- We will then send the data to your art using the uart_write_bytes function .
- This task will run every 500 ms.
The main functions are shown below.
void app_main(void)
{
gpio_set_direction(LED, GPIO_MODE_OUTPUT);
init();
xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, configMAX_PRIORITIES, NULL);
xTaskCreate(tx_task, "uart_tx_task", 1024*2, NULL, configMAX_PRIORITIES-1, NULL);
}
Here first we will set the direction of the LED as output
Then initialize the UART
Then we will create two tasks one to receive data (RX Task) and another to send data (TX Task)
Once created these tasks will start executing.
Result
Below is the image of LCD and ESP32
- In the above figure, the LED is turned on after pressing the ON button.
- LED status shows LED is ON
- Also note the value = 49, which is the value of the num variable that we incremented in the code
- In the above figure, the LED turns off after pressing the OFF button.
- LED status shows LED OFF
- Also note the value = 53, which is the value of the num variable that we incremented in the code
So we have finished programming and connecting, I wish you success, I hope this article is helpful to you.a
Conclusion
Connecting HMI STONE with ESP32 opens up many opportunities for smart control and monitoring applications. By following the steps above, you can build an efficient integrated system between the touch screen and powerful microcontroller.
Author: tonay