micro-ROS / micro_ros_stm32cubemx_utils

A set of utilities for integrating micro-ROS in a STM32CubeMX project
Apache License 2.0
149 stars 59 forks source link

rcl_publish() doesn't publish with success #82

Open anton789456 opened 1 year ago

anton789456 commented 1 year ago

Hi, I try to start example program in stm32 cube ide that publish data. Hardware description: custom board witm stm32h743VIT6 image

RTOS: FreeRTOS Installation type: micro_ros_stm32cubemx_utils Version or commit hash: Foxy I did everything like in the start up guide. Default task:

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN 5 */
      // micro-ROS configuration

      rmw_uros_set_custom_transport(
        true,
        (void *) &huart2,
        cubemx_transport_open,
        cubemx_transport_close,
        cubemx_transport_write,
        cubemx_transport_read);

      rcl_allocator_t freeRTOS_allocator = rcutils_get_zero_initialized_allocator();
      freeRTOS_allocator.allocate = microros_allocate;
      freeRTOS_allocator.deallocate = microros_deallocate;
      freeRTOS_allocator.reallocate = microros_reallocate;
      freeRTOS_allocator.zero_allocate =  microros_zero_allocate;

      if (!rcutils_set_default_allocator(&freeRTOS_allocator)) {
          printf("Error on default allocators (line %d)\n", __LINE__);
      }

      // micro-ROS app

      rcl_publisher_t publisher;
      std_msgs__msg__Int32 msg;
      rclc_support_t support;
      rcl_allocator_t allocator;
      rcl_node_t node;

      allocator = rcl_get_default_allocator();

      //create init_options
      rclc_support_init(&support, 0, NULL, &allocator);

      // create node
      rclc_node_init_default(&node, "cubemx_node", "", &support);

      // create publisher
      rclc_publisher_init_default(
        &publisher,
        &node,
        ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
        "cubemx_publisher");

      msg.data = 0;

      for(;;)
      {
        rcl_ret_t ret = rcl_publish(&publisher, &msg, NULL);
        if (ret != RCL_RET_OK)
        {
          printf("Error publishing (line %d)\n", __LINE__);
        }

        msg.data++;
        osDelay(10);
      }

I checked with debugger that task is executed, but there is error code no. 300 - RCL_RET_PUBLISHER_INVALID. I'm using DMA transport. Communication in the hardware layer works. When: rclc_support_init(&support, 0, NULL, &allocator); is called I see 10 messages with the logic analyzer(every one is the same): image I have another task related to communication with motors and other peripherals with the lowest possible priority and that one works fine. What can be reason of that issue? I can't debug what happens inside rcl_publish() from my program. image There is a few problems with the DMA on the STM32H743 - to use it it is necessary to use cache invalidation function. Is that possible that can cause the problem?

Best regards

Acuadros95 commented 1 year ago

is called I see 10 messages with the logic analyzer(every one is the same):

It looks like you are not communicating with the Agent.

anton789456 commented 1 year ago

I didn't have running Agent on the PC. Is this necessary to have running agent to publish data? Since now I looked only with logic analyzer to observe if the publisher sends something over the uart, without connection with agent. I think that I can send data with provided transport(on the screen from the analyzer is data send after rclc_support_init(&support, 0, NULL, &allocator); is called.

anton789456 commented 1 year ago

rclc_support_init return 1 - RCL_RET_ERROR. Is that because I didn't started Agent?

anton789456 commented 1 year ago

I ran the agent, and it works properly(like in the tutorials that I watched). But I can't receive any data. With -v6 option nothing changed - I don't see anything in the terminal. image I checked if I can see messages that is send during rclc_support_init() call in putty - my ftdi works properly image I think that there is problem with the rclc_support_init(), but I have no idea what can cause the error. During tests I ran Agent, and after that I restarted MCU to be sure that PC see everything what it transmit. What should happen from the Agent side after receiving init messages? Is the rclc_support_init() waiting for the response from the PC? Nothing appears on the PC Tx line.

Acuadros95 commented 1 year ago

How are you initializing the agent? Could you share the command?

And yes, all micro-ROS communication goes through the Agent which acts as a bridge to ROS2.

anton789456 commented 1 year ago

Firstly, I give proper privileges to the FTDI device: sudo chmod a+rw /dev/ttyUSB0 From the agent workspace location, I use commands: source install/local_setup.sh ros2 run micro_ros_agent micro_ros_agent serial -b 115200 --dev /dev/ttyUSB0

anton789456 commented 1 year ago

I observed once that client was created, but I can't reproduce that. It was on the first launch of the PC, I'll try with reboot. image

anton789456 commented 1 year ago

I tried to turn on everything step by step - disconnecting and connecting again ftdi, giving privileges to the usb, initializing agent and finally turning on board supply, but I didn't succeded with creating client second time. I see on the FTDI led, that it blinks during initialization, so MCU sends the data. So, it looks like that the agent doesn't react?

Acuadros95 commented 1 year ago

There is a few problems with the DMA on the STM32H743 - to use it it is necessary to use cache invalidation function. Is that possible that can cause the problem?

Could be, you should debug the transport methods and check if you can send/receive data correctly: dma_transport.c

Also, there is an interrupt based transport which you can try out : it_transport.c

Another thought: check that your huart baudrate is set to 115200 and that it is not being used for anything else.

anton789456 commented 1 year ago

I switched to interrupt based transport. It's more deterministic, every time I restart MCU I see session establishing. But I still have the same error with publisher - 300 - RCL_RET_PUBLISHER_INVALID as return value from rcl_publish(&publisher, &msg, NULL); That;s the log from the agent (-v6). Can you help me interpret it? I wonder if it is two-way communication. image

anton789456 commented 1 year ago

I checked what the functions return: rclc_support_init(&support, 0, NULL, &allocator); ret = 1 rclc_node_init_default(&node, "cubemx_node", "", &support); ret = 101 rclc_publisher_init_default( &publisher, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), "cubemx_publisher"); ret = 200 rcl_publish(&publisher, &msg, NULL); ret = 300

Acuadros95 commented 1 year ago

Can you help me interpret it? I wonder if it is two-way communication.

Looking at it, you are probably not receiving data on the board side. Try debugging the cubemx_transport_read method and check if you are receiving data from the Agent.

Also, try to start the Agent before you plug in the board.

I checked what the functions return:

Any return different from 0 equals to an error. Also, you should not continue if any of the init methods fail, as your publish call will fail anyways.

anton789456 commented 1 year ago

Thanks, I checked that. cubemx_transport_read method is called. Every time the session is re-established new data appears in the buffer: image image

Is that the data that I should see? Unfortunately my logic analyzer decided to stop working, so that everything I can check. Log from the agent:(looks like like earlier, with v6 also). image

anton789456 commented 1 year ago

I switched today to ros2 humble to check if it maybe solve problems. For now it still doesn't works, but I looked once again on the transport buffers. Firstly, the tx_buffer from the MCU in the cubemars_transport_write() method: image It looks like that agent receives data from the mcu: image If I'm correct, 7E 00 00 18 00 is the SOF, and the BF 71 is EOF. So I think writing to the agent works. About the receive buffer, I'm not sure what happens here. Below the screenshot with the it_buffer(program stopped on the HAL_UART_RxCpltCallback end: image after a few re-establishions. The rx_data is different than tx data from the v6 debug: image image Is that correct? From the other place in the program - cubemx_transport_read() after a few re-establishions rx_buffer looks that: image image

Summarizing:

Do you have any idea what else I can check or try?

mwleeds commented 1 year ago

@anton789456 what size rx and tx buffers are you using on the mcu? For me I had to increase them from 16 to 256 bytes to get the session to establish.

anton789456 commented 1 year ago

Rx_buffer(in the transport_it.c file called it_buffer) has 2048 bytes. #define UART_IT_BUFFER_SIZE 2048 static uint8_t it_buffer[UART_IT_BUFFER_SIZE];

Tx buffer doesn't exists as variable - there is cubemx_transport_write() function with pointer and data length, and uart_transmit function sends data from defined address and lenght: `size_t cubemx_transport_write(struct uxrCustomTransport transport, uint8_t buf, size_t len, uint8_t err){ UART_HandleTypeDef uart = (UART_HandleTypeDef*) transport->args;

HAL_StatusTypeDef ret;
if (uart->gState == HAL_UART_STATE_READY){
    ret = HAL_UART_Transmit_IT(uart, buf, len);
    while (ret == HAL_OK && uart->gState != HAL_UART_STATE_READY){
        osDelay(1);
    }

    return (ret == HAL_OK) ? len : 0;
}else{
    return 0;
}

} ` Where did you increased buffers size?

mwleeds commented 1 year ago

I'm running micro-ROS on different hardware than you, and with a custom transport implementation, so it seems my experience in this case is not applicable for you.

do-coding-J commented 1 year ago

I've got similar issue Nucleo-H7A3ZI-Q with freeRTOS stm32Cubeide and micro_ros_cubemx_utils

copied sample_main to test

agent with docker docker run -it --rm -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial -D /dev/ttyACM0 -v6

has something on serial communication but not connected to agent

anton789456 commented 1 year ago

I've got similar issue Nucleo-H7A3ZI-Q with freeRTOS stm32Cubeide and micro_ros_cubemx_utils

copied sample_main to test

agent with docker docker run -it --rm -v /dev:/dev --privileged microros/micro-ros-agent:foxy serial -D /dev/ttyACM0 -v6

has something on serial communication but not connected to agent

Did you solved that issue?

do-coding-J commented 1 year ago

not yet

anton789456 commented 1 year ago

After a long break I returned to the problem. My HW setup didn't changed. I use ros2 humble.

I see that I have two-direction communication - I checked with logic analyzer: image image image

image image image

So Agent sends data to MCU and MCU responds. What looks quite strange, message that is received is before it is sent? image On the top is message [==>> SER <<==] below [ <> ]

On the MCU in transport I have access to two buffers: It_buffer, which after a few tries of connecting between mcu and agent looks like that: image I checked in the buffer inside the transport object: image And it looks like quite good, but I see a few missing zeros(when there are 3 0x0 one by one). Could you tell what can be reason? I would like to use finally microros, and I think that there is small low level detail in the protocol, but I don't see the whole data processing which happens with usage of cubemx_transport functions.

Thank you in advance