how to run Modbus RTU On ESP IDF
-
- Posts: 3
- Joined: Wed Aug 04, 2021 1:50 pm
how to run Modbus RTU On ESP IDF
Hello, newbie here,
I have worked on Modbus on Arduino IDE and also on raspberry pi, Now I am exploring the ESP IDF.
But the https://github.com/espressif/esp-idf/tr ... bus/serial given in the ESP IDF is a bit confusing.
Could anyone please help how to use this lib to send data from one ESP32 to another ESP32 using Modbus RTU?
Thanks in advance.
I have worked on Modbus on Arduino IDE and also on raspberry pi, Now I am exploring the ESP IDF.
But the https://github.com/espressif/esp-idf/tr ... bus/serial given in the ESP IDF is a bit confusing.
Could anyone please help how to use this lib to send data from one ESP32 to another ESP32 using Modbus RTU?
Thanks in advance.
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: how to run Modbus RTU On ESP IDF
Hello @rjrajbir7178,
The examples of Modbus Master and Modbus Slave have the readme files:
https://github.com/espressif/esp-idf/bl ... /README.md
https://github.com/espressif/esp-idf/bl ... /README.md
These files describe how to start the communication from scratch. Please follow the instruction:
1. Refer to https://docs.espressif.com/projects/esp ... et-started to install (update) esp-idf.
2. Connect the master and slave board as showed on the "RS485 example circuit schematic" in slave readme file.
You need couple of RS485 line drivers. It is possible to configure the pins to which the driver is connected, port and baud rate in the menuconfig later (idf.py menuconfig) but defaults will work just fine.
You need just change the `Modbus communication mode -> RTU mode` and save the settings pressing `S` button.
The same needs to be done for slave project (see below).
3. Connect your boards to the USB ports of your computer and get the serial port name for each board (PORT_WHERE_MASTER_BOARD_CONNECTED - master and PORT_WHERE_SLAVE_BOARD_CONNECTED - slave).
4. Open the command prompt or terminal (linux)
5. Open second terminal and place commands below:
If everything went well you will be able to see the logs of master and slave like on below picture.
If some aspects are still unclear, feel free to ask questions. Once this works I can explain how to adopt examples to use it with third party Modbus masters and slaves.
Also please take a look to this simple Modbus master implementation:
The examples of Modbus Master and Modbus Slave have the readme files:
https://github.com/espressif/esp-idf/bl ... /README.md
https://github.com/espressif/esp-idf/bl ... /README.md
These files describe how to start the communication from scratch. Please follow the instruction:
1. Refer to https://docs.espressif.com/projects/esp ... et-started to install (update) esp-idf.
2. Connect the master and slave board as showed on the "RS485 example circuit schematic" in slave readme file.
You need couple of RS485 line drivers. It is possible to configure the pins to which the driver is connected, port and baud rate in the menuconfig later (idf.py menuconfig) but defaults will work just fine.
You need just change the `Modbus communication mode -> RTU mode` and save the settings pressing `S` button.
The same needs to be done for slave project (see below).
3. Connect your boards to the USB ports of your computer and get the serial port name for each board (PORT_WHERE_MASTER_BOARD_CONNECTED - master and PORT_WHERE_SLAVE_BOARD_CONNECTED - slave).
4. Open the command prompt or terminal (linux)
Code: Select all
cd $IDF_PATH/examples/protocols/modbus/serial/mb_master
source $IDF_PATH/export.sh (%IDF_PATH%/export.bat - for Windows)
idf.py fullclean
idf.py menuconfig (set the RTU mode in the Modbus communication mode )
idf.py build
idf.py -p PORT_WHERE_MASTER_BOARD_CONNECTED -b 921600 flash monitor
Code: Select all
cd $IDF_PATH/examples/protocols/modbus/serial/mb_slave
idf.py fullclean
idf.py menuconfig (set the RTU mode in the Modbus communication mode )
idf.py build
idf.py -p PORT_WHERE_SLAVE_BOARD_CONNECTED -b 921600 flash monitor
If some aspects are still unclear, feel free to ask questions. Once this works I can explain how to adopt examples to use it with third party Modbus masters and slaves.
Also please take a look to this simple Modbus master implementation:
Code: Select all
https://github.com/alisitsyn/modbus_support/blob/mb_support/simple_modbus_master/main/master.c
- Attachments
-
- Modbus communication opts and logs
- master_example_opts_comm.png (178.21 KiB) Viewed 11548 times
-
- Modbus customized demo boards
- boards.png (1.98 MiB) Viewed 11548 times
-
- Posts: 3
- Joined: Wed Aug 04, 2021 1:50 pm
Re: how to run Modbus RTU On ESP IDF
Yes, I have tried the sample code but I want to send slave data to the master
I want to connect the temp and humid sensor to slave( ESP32--->2) and want to get its data to master( ESP32--->1), but I don't know how to configure the GPIO pins in the code to connect the sensor. The code is very complecated.
Please help.
I want to connect the temp and humid sensor to slave( ESP32--->2) and want to get its data to master( ESP32--->1), but I don't know how to configure the GPIO pins in the code to connect the sensor. The code is very complecated.
Please help.
- Attachments
-
- Connection
- processed.jpeg (3.29 MiB) Viewed 11246 times
-
- Posts: 3
- Joined: Wed Aug 04, 2021 1:50 pm
Re: how to run Modbus RTU On ESP IDF
Here is output of master and slave when tested the default code of master and slave from esp-idf
Master output:
Slave Output:
Why I am not able to read all the data.
Please help.
Master output:
Code: Select all
E (20579) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20579) MASTER_TEST: Characteristic #0 (Data_channel_0) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
E (20599) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20609) MASTER_TEST: Characteristic #1 (Humidity_1) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
E (20619) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20629) MASTER_TEST: Characteristic #2 (Temperature_1) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
E (20649) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20649) MASTER_TEST: Characteristic #3 (Humidity_2) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
E (20669) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20679) MASTER_TEST: Characteristic #4 (Temperature_2) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
E (20699) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20699) MASTER_TEST: Characteristic #5 (Humidity_3) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
E (20719) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x108) (ESP_ERR_INVALID_RESPONSE).
E (20729) MASTER_TEST: Characteristic #6 (Test_regs) read fail, err = 0x108 (ESP_ERR_INVALID_RESPONSE).
I (20739) MASTER_TEST: Characteristic #7 RelayP1 (on/off) value = OFF (0x55) read successful.
I (20749) MASTER_TEST: Characteristic #8 RelayP2 (on/off) value = OFF (0xaa) read successful.
E (21249) MASTER_TEST: Alarm is not triggered after 30 retries.
I (21249) MASTER_TEST: Destroy master...
Code: Select all
[0;32mI (68413) SLAVE_TEST: COILS READ (68106852 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (68423) SLAVE_TEST: COILS READ (68115940 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (69083) SLAVE_TEST: COILS READ (68776978 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (69093) SLAVE_TEST: COILS READ (68786206 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (69753) SLAVE_TEST: COILS READ (69446897 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (69763) SLAVE_TEST: COILS READ (69456124 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (70423) SLAVE_TEST: COILS READ (70116815 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (70433) SLAVE_TEST: COILS READ (70126042 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (71093) SLAVE_TEST: COILS READ (70786802 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (71103) SLAVE_TEST: COILS READ (70796030 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (71763) SLAVE_TEST: COILS READ (71456790 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (71773) SLAVE_TEST: COILS READ (71466017 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (72433) SLAVE_TEST: COILS READ (72126847 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (72443) SLAVE_TEST: COILS READ (72136074 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (73103) SLAVE_TEST: COILS READ (72796765 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (73113) SLAVE_TEST: COILS READ (72805992 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (73773) SLAVE_TEST: COILS READ (73466688 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (73783) SLAVE_TEST: COILS READ (73475911 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (74443) SLAVE_TEST: COILS READ (74136742 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (74453) SLAVE_TEST: COILS READ (74145968 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (75113) SLAVE_TEST: COILS READ (74806667 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (75123) SLAVE_TEST: COILS READ (74815886 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (75783) SLAVE_TEST: COILS READ (75476655 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (75793) SLAVE_TEST: COILS READ (75485873 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (76453) SLAVE_TEST: COILS READ (76146642 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (76463) SLAVE_TEST: COILS READ (76155861 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (77123) SLAVE_TEST: COILS READ (76816560 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (77133) SLAVE_TEST: COILS READ (76825779 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (77793) SLAVE_TEST: COILS READ (77486618 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (77803) SLAVE_TEST: COILS READ (77495906 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (78463) SLAVE_TEST: COILS READ (78157776 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (78473) SLAVE_TEST: COILS READ (78167073 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (79133) SLAVE_TEST: COILS READ (78827695 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (79143) SLAVE_TEST: COILS READ (78837061 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (79803) SLAVE_TEST: COILS READ (79497752 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (79813) SLAVE_TEST: COILS READ (79507048 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (80473) SLAVE_TEST: COILS READ (80167670 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (80483) SLAVE_TEST: COILS READ (80176967 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (81143) SLAVE_TEST: COILS READ (80837657 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (81153) SLAVE_TEST: COILS READ (80846954 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (81813) SLAVE_TEST: COILS READ (81507645 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (81823) SLAVE_TEST: COILS READ (81516942 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (82483) SLAVE_TEST: COILS READ (82177563 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (82493) SLAVE_TEST: COILS READ (82186929 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (83153) SLAVE_TEST: COILS READ (82847551 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (83163) SLAVE_TEST: COILS READ (82856847 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (83823) SLAVE_TEST: COILS READ (83517538 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (83833) SLAVE_TEST: COILS READ (83526835 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (84493) SLAVE_TEST: COILS READ (84187526 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (84503) SLAVE_TEST: COILS READ (84196823 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (85163) SLAVE_TEST: COILS READ (84857514 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (85173) SLAVE_TEST: COILS READ (84866812 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (85833) SLAVE_TEST: COILS READ (85527432 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (85843) SLAVE_TEST: COILS READ (85536801 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (86503) SLAVE_TEST: COILS READ (86197419 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (86513) SLAVE_TEST: COILS READ (86206724 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (87173) SLAVE_TEST: COILS READ (86867407 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (87183) SLAVE_TEST: COILS READ (86876712 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (87843) SLAVE_TEST: COILS READ (87537325 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (87853) SLAVE_TEST: COILS READ (87546700 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
[0;32mI (88513) SLAVE_TEST: COILS READ (88207382 us), ADDR:0, TYPE:32, INST_ADDR:0x3ffb26a4, SIZE:8[0m
[0;32mI (88523) SLAVE_TEST: COILS READ (88216687 us), ADDR:8, TYPE:32, INST_ADDR:0x3ffb26a5, SIZE:8[0m
Please help.
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: how to run Modbus RTU On ESP IDF
The issue discussion is here:
https://github.com/espressif/esp-idf/issues/7527
https://github.com/espressif/esp-idf/issues/7527
-
- Posts: 5
- Joined: Mon Oct 10, 2022 12:27 am
Re: how to run Modbus RTU On ESP IDF
Hi, I would like to use modbus function 6 for write single holding register, so how I can do this with modbus library? Because it uses function 10 for write multiple registers, and my device doesn't recognise this function.
I hope someone can help me.
Thanks in advance.
I hope someone can help me.
Thanks in advance.
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: how to run Modbus RTU On ESP IDF
Hi Cacomixtle,
There are several variants to do this. The most simple way is to use the function :
https://github.com/espressif/esp-modbus ... ster.c#L83
in your code and fill the request structure with the modbus command 6 (`mb_param_request_t`).
It is possible to use the cpp wrapper code and change the command to 6 here: https://github.com/alisitsyn/modbus_sup ... r.cpp#L170. This will require to do a cycle writing the registers if your code needs to write several registers.
There are several variants to do this. The most simple way is to use the function :
https://github.com/espressif/esp-modbus ... ster.c#L83
in your code and fill the request structure with the modbus command 6 (`mb_param_request_t`).
It is possible to use the cpp wrapper code and change the command to 6 here: https://github.com/alisitsyn/modbus_sup ... r.cpp#L170. This will require to do a cycle writing the registers if your code needs to write several registers.
-
- Posts: 5
- Joined: Mon Oct 10, 2022 12:27 am
Re: how to run Modbus RTU On ESP IDF
Hi ESP_alisitsyn,
Thanks a lot, it works like a charm with mbc_master_send_request
Thanks a lot, it works like a charm with mbc_master_send_request
-
- Posts: 5
- Joined: Mon Oct 10, 2022 12:27 am
Re: how to run Modbus RTU On ESP IDF
Hi, I would like to flush the UART RX Buffer because I'm getting wrong data after encountering a 0x108 error. For example, I have CID_TEMPERATURE and CID_HUMIDITY values in device_parameters. When I get a 0x108 error while calling mbc_master_get_parameter for CID_TEMPERATURE, the next call for CID_HUMIDITY receives data meant for CID_TEMPERATURE and so on. This issue occurs randomly, and I'd like to avoid this data shift.
After searching thorugh GitHub issues I came acrossthe following function that seems to address the issue:
static void vMBMasterRxFlushTimeout( void )
{
size_t xSize = 1;
esp_err_t xErr = ESP_OK;
int64_t xStartTime = esp_timer_get_time();
int64_t xTimeLeft = 0;
while( (xTimeLeft < (1000 * MB_MASTER_TIMEOUT_MS_RESPOND)) ){
xTimeLeft = esp_timer_get_time() - xStartTime;
xErr = uart_get_buffered_data_len(xPortContext.ucUartNumber, &xSize);
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
BaseType_t xStatus = xQueueReset(xPortContext.xMbUartQueue);
if (xStatus) {
xErr = uart_flush_input(xPortContext.ucUartNumber);
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
}
}
}
However, I'm unsure about how to use it because I don't know how to get the xPortContext.xMbUartQueue reference. Any help would be appreciated.
After searching thorugh GitHub issues I came acrossthe following function that seems to address the issue:
static void vMBMasterRxFlushTimeout( void )
{
size_t xSize = 1;
esp_err_t xErr = ESP_OK;
int64_t xStartTime = esp_timer_get_time();
int64_t xTimeLeft = 0;
while( (xTimeLeft < (1000 * MB_MASTER_TIMEOUT_MS_RESPOND)) ){
xTimeLeft = esp_timer_get_time() - xStartTime;
xErr = uart_get_buffered_data_len(xPortContext.ucUartNumber, &xSize);
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
BaseType_t xStatus = xQueueReset(xPortContext.xMbUartQueue);
if (xStatus) {
xErr = uart_flush_input(xPortContext.ucUartNumber);
MB_PORT_CHECK((xErr == ESP_OK), ; , "mb flush serial fail, error = 0x%x.", xErr);
}
}
}
However, I'm unsure about how to use it because I don't know how to get the xPortContext.xMbUartQueue reference. Any help would be appreciated.
-
- Posts: 211
- Joined: Fri Feb 01, 2019 4:02 pm
- Contact:
Re: how to run Modbus RTU On ESP IDF
Hi,
This approach works to flush the buffer: https://github.com/espressif/esp-modbus/issues/11.
The latest esp-modbus v1.0.12 solves the issues with shifting of registers.
This approach works to flush the buffer: https://github.com/espressif/esp-modbus/issues/11.
The latest esp-modbus v1.0.12 solves the issues with shifting of registers.
Who is online
Users browsing this forum: rsimpsonbusa and 96 guests