how to run Modbus RTU On ESP IDF

rjrajbir7178
Posts: 3
Joined: Wed Aug 04, 2021 1:50 pm

how to run Modbus RTU On ESP IDF

Postby rjrajbir7178 » Thu Aug 05, 2021 9:08 am

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.

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: how to run Modbus RTU On ESP IDF

Postby ESP_alisitsyn » Mon Aug 09, 2021 3:22 pm

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)

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
5. Open second terminal and place commands below:

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 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:

Code: Select all

https://github.com/alisitsyn/modbus_support/blob/mb_support/simple_modbus_master/main/master.c
Attachments
master_example_opts_comm.png
Modbus communication opts and logs
master_example_opts_comm.png (178.21 KiB) Viewed 11548 times
boards.png
Modbus customized demo boards
boards.png (1.98 MiB) Viewed 11548 times

rjrajbir7178
Posts: 3
Joined: Wed Aug 04, 2021 1:50 pm

Re: how to run Modbus RTU On ESP IDF

Postby rjrajbir7178 » Fri Sep 03, 2021 6:15 am

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.
Attachments
processed.jpeg
Connection
processed.jpeg (3.29 MiB) Viewed 11246 times

rjrajbir7178
Posts: 3
Joined: Wed Aug 04, 2021 1:50 pm

Re: how to run Modbus RTU On ESP IDF

Postby rjrajbir7178 » Fri Sep 03, 2021 8:16 am

Here is output of master and slave when tested the default code of master and slave from esp-idf

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...
Slave Output:

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
Why I am not able to read all the data.
Please help.

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: how to run Modbus RTU On ESP IDF

Postby ESP_alisitsyn » Tue Sep 07, 2021 8:37 am


Cacomixtle
Posts: 5
Joined: Mon Oct 10, 2022 12:27 am

Re: how to run Modbus RTU On ESP IDF

Postby Cacomixtle » Mon Oct 10, 2022 2:10 am

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.

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: how to run Modbus RTU On ESP IDF

Postby ESP_alisitsyn » Thu Oct 20, 2022 8:08 am

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.

Cacomixtle
Posts: 5
Joined: Mon Oct 10, 2022 12:27 am

Re: how to run Modbus RTU On ESP IDF

Postby Cacomixtle » Thu Oct 20, 2022 9:34 pm

Hi ESP_alisitsyn,

Thanks a lot, it works like a charm with mbc_master_send_request

Cacomixtle
Posts: 5
Joined: Mon Oct 10, 2022 12:27 am

Re: how to run Modbus RTU On ESP IDF

Postby Cacomixtle » Wed Sep 13, 2023 9:25 pm

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.

ESP_alisitsyn
Posts: 211
Joined: Fri Feb 01, 2019 4:02 pm
Contact:

Re: how to run Modbus RTU On ESP IDF

Postby ESP_alisitsyn » Thu Oct 26, 2023 7:29 am

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.

Who is online

Users browsing this forum: rsimpsonbusa and 96 guests