espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.79k stars 7.31k forks source link

Support for Implementing Modbus TCP and ESP-NOW Simultaneously (IDFGH-4994) #6783

Closed diegopivoto closed 2 years ago

diegopivoto commented 3 years ago

Hello, everybody! I've worked in the Modbus TCP and ESP-NOW separately, but now I have a situation which I need to use both to run in the same ESP32. So, basically, I will divide the situation in two parts:

As I said before, the code for the Modbus [PART 1] works fine singly, but if I try to implement the ESP-NOW for store the data from the holding registers and send them to other ESP32, a lot of errors appear and I can't even run the code.

I would like to ask for help for someone who can guide me or give me an example about how to do it.

diegopivoto commented 3 years ago

Here, I will insert just the code of the Modbus, singly, in a text file.

tcp_slave.txt

Basically, here it gets and shows the data from the 3 holding registers in real time:

for(;;) {
        // Check for read/write events of Modbus master for certain events
        mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK);
        const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE";
        // Filter events and process them accordingly
        if (event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) {
            // Get parameter information from parameter queue
            ESP_ERROR_CHECK(mbc_slave_get_param_info(&reg_info, MB_PAR_INFO_GET_TOUT));
            ESP_LOGI(SLAVE_TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u",
                    rw_str,
                    (uint32_t)reg_info.time_stamp,
                    (uint32_t)reg_info.mb_offset,
                    (uint32_t)reg_info.type,
                    (uint32_t)reg_info.address,
                    (uint32_t)reg_info.size);
            // a variable that keeps the value of the action when being accessed
            uint16_t action_value = *(uint16_t*)reg_info.address;
            // Check if the holding register structure field being accessed my host
            if (IS_FIELD_IN_RANGE(reg_info.address, reg_info.size, device_action_0, action_value)) {
                ESP_LOGI(SLAVE_TAG, "Handle ACTION_0 %s , value = %d.", rw_str, action_value);
                // Check the action value and do associated action (set/reset led pin currently)
                // The register can include more actions instead of just switch led on/off (handle these actions appropriately later)
                if (action_value == DEV_ACTION_LAMP_ON) {
                    // Switch lamp on
                    // The state of lamp is available as discrete inputs over Modbus protocol
                    portENTER_CRITICAL(&param_lock);
                    discrete_reg_params.device_action_state0 = 1;
                    // Change the value inside critical section if required.
                    portEXIT_CRITICAL(&param_lock);
                    gpio_set_level(DEV_LED_ACTION_0, 1);
                } else if (action_value == DEV_ACTION_LAMP_OFF) {
                    // Switch lamp off
                    discrete_reg_params.device_action_state0 = 0;
                    gpio_set_level(DEV_LED_ACTION_0, 0);
                }
            }
            // The same way check other fields in range of read/wrote registers
            if (IS_FIELD_IN_RANGE(reg_info.address, reg_info.size, device_action_1, action_value)) {
                ESP_LOGI(SLAVE_TAG, "Handle ACTION_1 %s , value = %d.", rw_str, action_value);
                if (action_value == DEV_ACTION_LAMP_ON) {
                    // Switch lamp on
                    discrete_reg_params.device_action_state1 = 1;
                    gpio_set_level(DEV_LED_ACTION_1, 1);
                } else if (action_value == DEV_ACTION_LAMP_OFF) {
                    // Switch lamp off
                    discrete_reg_params.device_action_state1 = 0;
                    gpio_set_level(DEV_LED_ACTION_1, 0);
                }
            }
            if (IS_FIELD_IN_RANGE(reg_info.address, reg_info.size, device_action_2, action_value)) {
                ESP_LOGI(SLAVE_TAG, "Handle ACTION_2 %s , value = %d.", rw_str, action_value);
                if (action_value == DEV_ACTION_LAMP_ON) {
                    // Switch lamp on
                    discrete_reg_params.device_action_state2 = 1;
                    gpio_set_level(DEV_LED_ACTION_2, 1);
                } else if (action_value == DEV_ACTION_LAMP_OFF) {
                    // Switch lamp off
                    discrete_reg_params.device_action_state2 = 0;
                    gpio_set_level(DEV_LED_ACTION_2, 0);
                }
            }
            if (IS_FIELD_IN_RANGE(reg_info.address, reg_info.size, device_action_9, action_value)) {
                // Exit condition: device_action_9
                break;
            }
            // This is how to safely change fields in the Modbus structure that being accessed by Modbus driver
            portENTER_CRITICAL(&param_lock);
            holding_reg_params.device_action_last = action_value; // Keep last action
            portEXIT_CRITICAL(&param_lock);
            // Do the same to filter other actions accordingly
        }
    }

So, it shows the values received from device_action_0, device_action_1 and device_action_2, and according to these values lamps are switched or not (just ignore this application). So, while I'm receiving these data, I need to store and send them in real-time to other ESP32 via ESP-NOW. Please, someone can help me! I will be very grateful.

xueyunfei998 commented 3 years ago

hi @diegopivoto

I think Modbus TCP and ESP-NOW can work at the same time.

You can refer to the IDF example.

esp-idf/examples/wifi/espnow/main/espnow_example_main.c

alisitsyn commented 3 years ago

Hi @diegopivoto,

but if I try to implement the ESP-NOW for store the data from the holding registers and send them to other ESP32, a lot of errors appear and I can't even run the code.

What exactly errors do you have?

Alvin1Zhang commented 3 years ago

@diegopivoto Thanks for reporting and sorry for slow turnaround, would you please help share if any further updates for the issue? Thanks.

Alvin1Zhang commented 2 years ago

Thanks for reporting, feel free to reopen.