鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    话题/read_485无响应

    已定时 已固定 已锁定 已移动
    多协议传输控制器
    read485无响应 rs485通讯
    3
    9
    460
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 4
      开心
      最后由 编辑

      与电压模拟量RS485传输模块通讯,话题/read_485无响应,代码如下:

      import rclpy
      from rclpy.node import Node
      from rclpy.qos import qos_profile_sensor_data
      from robot_interfaces.msg import RawUInt8
      import time
      
      class Write485PublisherFx(Node):
      
          def __init__(self):
              super().__init__('write_485_publisher')
              self.publisher_ = self.create_publisher(RawUInt8, '/write_485', qos_profile_sensor_data)
              self.subscription_ = self.create_subscription(
                  RawUInt8,
                  '/read_485',
                  self.handle_read_485,
                  qos_profile_sensor_data)
              self.timer_ = self.create_timer(2.0, self.publish_message)
              
      
          def publish_message(self):
              '''
              在Modbus RTU协议中,数据包 {0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0xCB} 具有以下含义:
      
              1. **0x01**:从站地址。这表明命令是发送到地址为1的设备。
              2. **0x04**:功能码。0x04表示读输入寄存器(Read Input Registers)。
              3. **0x00, 0x00**:起始地址。0x0000表示从第一个寄存器开始读。
              4. **0x00, 0x02**:寄存器数量。0x0002表示读取两个寄存器。
              5. **0x71, 0xCB**:CRC校验码。用于错误检查,确保数据传输的完整性和正确性。
      
              总结起来,这个数据包的含义是:从Modbus网络中的地址为1的设备读取两个输入寄存器,从地址0x0000开始。
              '''
              message = RawUInt8()
              message.size = 8
              message.data = [0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0x0B]
              self.get_logger().info("------------------------------------------------------------")
              self.get_logger().info("发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}")
              self.publisher_.publish(message)
      
          def handle_read_485(self, msg):
              '''
              返回数据包 `01 04 04 01 33 02 31 CA C3` 的含义如下:
      
              1. **01**:从站地址。这表明返回数据来自地址为1的设备。
              2. **04**:功能码。0x04表示读输入寄存器(Read Input Registers)。
              3. **02**:数据字节数。这表明返回的寄存器数据有2个字节。
              4. **01 33**:寄存器数据。这2个字节是两个寄存器的数据,组合成16位数据。
              5. **CA C3**:CRC这个校验码怎么确,说数没有怎麽确定?
      
              6.把5v对标5000.0g返回2个字节16位数据
      
            
      
              '''
              if msg.size != 7: #因为只需要一个通道的数值所以把9改成7
                  self.get_logger().error("Received message size is not 7 bytes.")
                  return
      
              received_data = " ".join([f"{byte:02x}" for byte in msg.data])
              self.get_logger().info(f"收到数据 {received_data}")
      
              id = msg.data[0]
              function_code = msg.data[1]
              byte_count = msg.data[2]
      
              # 解析重量数据
              temp_raw = (msg.data[3] << 8) | msg.data[4]
              
      
              # 重量解析方式为每个数据乘以0.1
              temperature = temp_raw * 0.1 # 输出5v对标5000g,精确到0.1g
              
      
              self.get_logger().info(f"接收 ID: 0x{id:02x} 重量: {temperature:.1f} ")
      
      def main(args=None):
          rclpy.init(args=args)
          node = Write485PublisherFx()
          rclpy.spin(node)
          node.destroy_node()
          rclpy.shutdown()
      
      if __name__ == '__main__':
          main()
      

      运行程序日志如下:

      root@ubuntu:~/ros2_transmission_ws# ros2 run fx_weight weight_read
      [INFO] [1736344761.905488032] [write_485_publisher]: ------------------------------------------------------------
      [INFO] [1736344761.908431040] [write_485_publisher]: 发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}
      [INFO] [1736344763.791418193] [write_485_publisher]: ------------------------------------------------------------
      [INFO] [1736344763.794267330] [write_485_publisher]: 发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}
      [INFO] [1736344765.791321297] [write_485_publisher]: ------------------------------------------------------------
      [INFO] [1736344765.794136144] [write_485_publisher]: 发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}
      [INFO] [1736344767.791279940] [write_485_publisher]: ------------------------------------------------------------
      [INFO] [1736344767.794188283] [write_485_publisher]: 发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}
      [INFO] [1736344769.791319163] [write_485_publisher]: ------------------------------------------------------------
      [INFO] [1736344769.794140551] [write_485_publisher]: 发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}
      [INFO] [1736344771.791941279] [write_485_publisher]: ------------------------------------------------------------
      [INFO] [1736344771.795029198] [write_485_publisher]: 发布读取命令 {0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0xB0, 0xOB}
      。。。
      ^CTraceback (most recent call last):
        File "/root/ros2_transmission_ws/install/fx_weight/lib/fx_weight/weight_read", line 33, in <module>
          sys.exit(load_entry_point('fx-weight==0.0.0', 'console_scripts', 'weight_read')())
        File "/root/ros2_transmission_ws/install/fx_weight/lib/python3.10/site-packages/fx_weight/weight_read.py", line 78, in main
          rclpy.spin(node)
        File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/__init__.py", line 226, in spin
          executor.spin_once()
        File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 739, in spin_once
          self._spin_once_impl(timeout_sec)
        File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 728, in _spin_once_impl
          handler, entity, node = self.wait_for_ready_callbacks(timeout_sec=timeout_sec)
        File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 711, in wait_for_ready_callbacks
          return next(self._cb_iter)
        File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 608, in _wait_for_ready_callbacks
          wait_set.wait(timeout_nsec)
      KeyboardInterrupt
      [ros2run]: Interrupt
      

      话题列表:

      root@ubuntu:~/ros2_transmission_ws# ros2 topic list
      /parameter_events
      /read_485
      /rosout
      /write_485
      

      查看话题无响应

      ^Croot@ubuntu:~/ros2_transmission_ws# ros2 topic echo /read_485
      ^Croot@ubuntu:~/ros2_transmission_ws# 
      
      小鱼小 1 条回复 最后回复 回复 引用 0
      • 小伊小
        机器人小伊
        最后由 编辑

        从你提供的日志和代码来看,有几个关键点需要检查和调整,以确保 /read_485 话题能够正确接收和响应数据:

        1. CRC校验问题:

          • 你在发布的数据包中使用了 0xB0, 0x0B 作为CRC校验码,但在注释中提到“CRC校验码怎么确,说数没有怎麽确定?”。CRC校验码是用来确保数据完整性的,如果CRC不正确,接收端可能会忽略或丢弃数据包。
          • 确保你发送的数据包的CRC校验码是正确的。你可以使用在线CRC计算器或编写代码来计算正确的CRC值。
        2. 接收数据长度不匹配:

          • 你的代码检查接收到的消息大小是否为7字节,但根据Modbus RTU协议,一个典型的读响应消息应该包含至少7个字节(设备地址、功能码、字节数、数据、CRC校验)。如果数据寄存器为2个字节,则整个消息应为9个字节(包括CRC)。
          • 你可以尝试将 if msg.size != 7: 改为 if msg.size != 9: 来匹配可能的完整响应消息长度。
        3. 数据解析问题:

          • 你的代码试图解析两个字节的数据为重量,但注释中提到“5v对标5000.0g返回2个字节16位数据”。确保你的解析逻辑正确,并且符合设备的数据手册或通信协议。
          • 检查是否有必要进行单位转换或缩放,以正确解释数据。
        4. 硬件和连接:

          • 确保RS485硬件(如转换器、线缆等)正确连接并且工作正常。
          • 检查是否有任何终端电阻或偏置电阻需要配置在RS485总线上。
          • 确保Modbus设备已正确配置为监听指定的从站地址,并且没有其他通信冲突。
        5. 调试和日志:

          • 在接收回调中添加更多的日志输出,以便更好地了解何时接收到数据以及数据的具体内容。
          • 检查ROS2节点的日志以查找可能的错误或警告信息。
        6. 代码中的小错误:

          • 在你的 publish_message 方法中,CRC部分写为 0xB0, 0xOB,其中 0xOB 应该是 0x0B。确保这只是一个打字错误,并且在实际代码中使用了正确的值。

        通过上述检查和调整,你应该能够更接近问题的根源,并找到导致 /read_485 话题无响应的原因。如果问题仍然存在,可能需要进一步检查硬件连接或联系设备制造商获取支持。


        以上为生成回答,仅供参考~

        我是小伊,已接入ChatGpt,所有回复,仅供参考~

        4 1 条回复 最后回复 回复 引用 0
        • 4
          开心 @小伊
          最后由 编辑

          @小伊 如果都正常如何引入此类,引用里面的函数,对外发送数据,和读取返回数据处理结果

          1 条回复 最后回复 回复 引用 0
          • 小伊小
            机器人小伊
            最后由 编辑

            在编程中,引入模块(类库)、使用其函数、发送数据并处理返回结果是一个常见的流程。以下是一个通用的步骤说明,假设你使用的是Python语言。这些步骤可以适用于大多数编程语言,只是语法和具体实现会有所不同。

            1. 引入模块或类

            首先,你需要引入所需的模块或类。在Python中,这通常通过import语句完成。

            import some_module  # 引入整个模块
            from some_module import SomeClass  # 从模块中引入特定的类
            from some_module import some_function  # 从模块中引入特定的函数
            

            2. 实例化对象(如果使用了类)

            如果引入了类,你需要创建该类的实例。

            my_object = SomeClass()
            

            3. 调用函数或方法发送数据

            接下来,你需要调用函数或方法来发送数据。这可能涉及到发送HTTP请求、调用API、写入文件等。

            # 假设有一个函数send_data,它发送数据并返回一个响应
            response = some_function(data_to_send)
            # 或者,如果使用的是对象的方法
            response = my_object.send_data(data_to_send)
            

            4. 处理返回的数据

            收到响应后,你需要处理这些数据。这可能包括解析JSON、检查状态码、处理异常等。

            # 假设响应是一个JSON格式的字符串,我们将其解析为Python字典
            import json
            data = json.loads(response)
            
            # 处理数据,例如提取所需的信息
            result = data['some_key']
            
            # 根据需要对结果进行处理或进一步操作
            

            示例代码

            以下是一个完整的示例,假设你有一个名为api_client的模块,它有一个ApiClient类,该类有一个send_request方法用于发送数据并接收响应。

            # api_client.py
            import requests
            
            class ApiClient:
                def __init__(self, base_url):
                    self.base_url = base_url
            
                def send_request(self, endpoint, data):
                    url = f"{self.base_url}/{endpoint}"
                    response = requests.post(url, json=data)
                    return response.text  # 返回响应的文本内容
            
            # main.py
            from api_client import ApiClient
            
            # 实例化ApiClient对象
            api_client = ApiClient(base_url="https://api.example.com")
            
            # 准备要发送的数据
            data_to_send = {
                "key1": "value1",
                "key2": "value2"
            }
            
            # 发送数据并接收响应
            response = api_client.send_request("some_endpoint", data_to_send)
            
            # 处理响应数据
            import json
            data = json.loads(response)
            
            # 提取和处理结果
            result = data.get("result")
            if result:
                print("操作成功:", result)
            else:
                print("操作失败:", data.get("error"))
            

            注意事项

            1. 错误处理:在实际应用中,你应该添加错误处理逻辑,例如处理网络异常、API错误等。
            2. 环境配置:根据环境(开发、测试、生产)的不同,可能需要配置不同的API端点或凭据。
            3. 日志记录:添加日志记录可以帮助你跟踪和调试问题。
            4. 数据验证:在发送数据之前,验证数据的完整性和格式可以避免很多潜在的问题。

            这些步骤和示例提供了一个基本的框架,你可以根据具体的需求和上下文进行调整和扩展。


            以上为生成回答,仅供参考~

            我是小伊,已接入ChatGpt,所有回复,仅供参考~

            1 条回复 最后回复 回复 引用 0
            • 小鱼小
              小鱼 技术大佬 @43996173
              最后由 编辑

              @43996173 三种可能吧

              1. 发的数据不正确,比如crc不正确
              2. 没有发出去
                • 比如波特率不正确,这种可以用示波器量485ab口看看有没有波形,或者再用一个485模块看看有没有接受到数据
                • 比如agent没有正常工作,这种考虑ros2 topic echo /read_io 看看有没有数据
              3. 外部设备没有响应,有可能是接线问题,或者是设备本身有问题,地址不对等等

              新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

              4 2 条回复 最后回复 回复 引用 0
              • 4
                开心 @小鱼
                最后由 编辑

                @小鱼 /read_io正常

                ^Croot@ubuntu:~/ros2_transmission_ws# ros2 topic echo /read_io
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                ---
                analog: []
                digital:
                - 1
                - 1
                - 1
                - 1
                
                1 条回复 最后回复 回复 引用 0
                • 4
                  开心 @小鱼
                  最后由 编辑

                  @小鱼 启动顺序是不是:

                  ros2 run micro_ros_agent micro_ros_agent  udp4 --port 8888 -v4
                  ros2 run fx_weight weight_read
                  ros2 topic echo /read_485
                  
                  小鱼小 1 条回复 最后回复 回复 引用 0
                  • 小鱼小
                    小鱼 技术大佬 @43996173
                    最后由 编辑

                    @43996173 在 话题/read_485无响应 中说:

                    ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888 -v4

                    只要这个启动了,能连接上就行,你试试
                    ros2 topic echo /read_485 看看有没有数据

                    新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

                    4 1 条回复 最后回复 回复 引用 0
                    • 4
                      开心 @小鱼
                      最后由 编辑

                      @小鱼 没反应,这个多功能传输控制器可以作为usb转485用吗,能用的话直接用电脑测一下采集模块

                      1 条回复 最后回复 回复 引用 0
                      • 第一个帖子
                        最后一个帖子
                      皖ICP备16016415号-7
                      Powered by NodeBB | 鱼香ROS