arduino作为下位机连接VL6180X与ROS上位机进行通信的两种方式

arduino作为下位机连接VL6180X与ROS上位机进行通信的两种方式

一、通过串口直接进行通信

这种方法直接通过arduino的ros库,节点直接在下位机中就已经构建,上位机只需安装rosserial_arduino,就可以订阅到此时下位机发出的信息,但实验过程中发现该种方式只适用于Python2.7的环境,如果你的开发环境大部分处在Python3.6环境下,会对后期的数据提取造成一定困难。而且此种方式在通信时会出现数据传输不稳定的情况,以及串口等各类问题,如果你只需要简单的数据回传不需要对后续的数据进行处理可以使用该种方式。

Ubuntu环境下arduino IDE的安装以及需要环境的配置

sudo apt-get install arduino           //arduino的安装
sudo apt-get install ros-melodic-rosserial-python     //串口通讯功能安装

arduino安装完毕后还需要安装对应的ROS库文件,教程详见此博客

使用arduino IDE 将VL6180X对应的底层代码烧录至下位机中

下位机代码如下:

#include <ros.h>            //ROS&arduino通信头文件
#include <Wire.h>          //arduino通讯
#include <VL6180X.h>   //传感器对应头文件
#include <std_msgs/Int64.h>   //定义的数据类型

using namespace std;

ros::NodeHandle  nh;

VL6180X sensor;
std_msgs::Int64 str_msg;
ros::Publisher distance("distance", &str_msg);
int dis;

void setup() 
{
  Serial.begin(9600);
  Wire.begin();
  nh.initNode();
  nh.advertise(distance);
  sensor.init();
  sensor.configureDefault();
  sensor.setTimeout(100);
}

void loop() 
{ 
    Serial.print(sensor.readRangeSingleMillimeters());
  dis = sensor.readRangeSingleMillimeters();
  str_msg.data = dis;
  distance.publish( &str_msg );
  nh.spinOnce();
  delay(200);
}

通过cutecom观察此时arduino回传数据是否正确。
在这里插入图片描述

启动rosserial_python中的serial_node.py即可,注意串口号,如:

rosrun rosserial_python serial_node.py /dev/ttyACM0

即可看到输出的当前下位机信息。

二、使用ROS节点进行通信

此种方法不用在意串口通信的规则,也不再限制此时你的开发环境,只需要通过arduino的serial.print()函数就可以在上位机中定义相关节点获取信息。

下位机代码如下:

#include <Wire.h>
#include <VL6180X.h>

VL6180X sensor;

void setup() 
{
  Serial.begin(9600);
  Wire.begin();
  
  sensor.init();
  sensor.configureDefault();
  sensor.setTimeout(500);
}

void loop() 
{ 
  Serial.print(sensor.readRangeSingleMillimeters());
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
  Serial.println();
}

烧录完毕后在ros工作环境中创建节点

#include <ros/ros.h>
#include <serial/serial.h>
#include <std_msgs/String.h>
#include <std_msgs/Int8.h>
#include <std_msgs/Bool.h>
#include <std_msgs/Float64.h>
#include <std_msgs/Empty.h>
#include <iostream>
using namespace std;
serial::Serial _serial;	
std_msgs::String result;

void distance_write_callback(const std_msgs::Int8& msg)
{
	std::string Gcode = "";
	ROS_INFO("%s", Gcode.c_str());
	_serial.write(Gcode.c_str());
	result.data = _serial.read(_serial.available());
}

int main(int argc, char** argv)
{	
	ros::init(argc, argv, "distance_find_node");
	ros::NodeHandle nh;
  ros::Subscriber sub1 = nh.subscribe("distance_topic", 1, distance_write_callback);
  ros::Publisher pub_dis = nh.advertise<std_msgs::Float64>("/distance", 10);
	// ros::spin();
  ros::Rate loop_rate(20);
	try
	{
    _serial.setPort("/dev/ttyACM0");
		_serial.setBaudrate(9600);
		_serial.setFlowcontrol(serial::flowcontrol_none);
		_serial.setParity(serial::parity_none);
		_serial.setStopbits(serial::stopbits_one);
		serial::Timeout to = serial::Timeout::simpleTimeout(1000);
		_serial.setTimeout(to);
		_serial.open();
		ROS_INFO_STREAM("Port has been open successfully");
	}
	catch (serial::IOException& e)
	{
		ROS_ERROR_STREAM("Unable to open port");
		return -1;
	}
  if (_serial.isOpen())
	{
		ROS_INFO_STREAM("Attach and wait for commands ");
	}
  while (nh.ok()){
    std::string tmp_data = _serial.readline();
//    std::cout<<tmp_data;
    std_msgs::Float64 data;
    double data_;
    stringstream stream;
    stream<<tmp_data;
    stream>>data_;
    data.data = data_;
//    data.data = atoi(tmp_data.c_str());
//    ROS_INFO("data_ = %lf, data.data = %lf", data_, data.data);
    pub_dis.publish(data);
//    ros::spinOnce();
//    loop_rate.sleep();
	}
   
}

配置完环境后编译即可完成ROS节点的订阅。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值