ros与arduino通信控制直流电机

前言:在成功通过arduino开发板控制直流电机后,开始尝试用ros与arduino通信来控制直流电机,为无人小车作准备

参考教程:创客智造

1.硬件

arduino开发板、杜邦线、直流电机、L298N电机驱动板

板子的连接参考我之前写的博客:L298N电机驱动器和Arduino板来控制直流电机

2.在ubuntu下安装arduino IDE和rosserial arduino

参考链接:安装最新arduino和建立ros_lib库

3.打开arduino上传代码

对于新手而言,参考创客智造和我之前写的博客(即第一个和第二个链接)会更容易理解


#include <ros.h>
#include <std_msgs/String.h>
#include <std_msgs/Int8.h>   //头文件


ros::NodeHandle  nh;  //初始化节点

#define IN3 5  //定义IN3为5口
#define IN4 4  //定义IN4为4口
#define  ENA  3 //定义ENA为3口

std_msgs::String str_msg; //定义消息类型为std_msgs::String

void stop_move(void) //电机停止函数
{                   
  digitalWrite(IN3,LOW);   
  digitalWrite(IN4,LOW);
  analogWrite(ENA,200); 
    
}   
void advance(void)  //电机正传函数        
{
   digitalWrite(IN3,HIGH);  //控制电机正转
   digitalWrite(IN4,LOW);
   analogWrite(ENA,200);   //控制电机转速,迳我自己测试超过150电机才开始转
   
}  
void back_off (void)    //电机反转函数      
{
   digitalWrite(IN3,LOW);   //电机反转
   digitalWrite(IN4,HIGH);
   analogWrite(ENA,200);
   
}

void ModelCb(const std_msgs::Int8& model){ //定义回调函数为ModelCb,订阅String消息里的model
  if(model.data==-1){
    back_off();
  }
  else if(model.data==1){
    advance();
  }
  else if(model.data==0){
    stop_move();
  }
}


ros::Subscriber<std_msgs::Int8> sub("model", ModelCb );//创建一个订阅者,主题名model,回调函数名ModelCb,消息类型std_msgs::Int8

void setup(void) //Arduino的Setup函数,需要初始化ROS节点处理,并宣告所有的发布或订阅
{ 
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(ENA,OUTPUT);
  nh.initNode();
  nh.subscribe(sub);
} 
 
void loop(void) //在Arduino的loop函数,调用nh.spinOnce(),这样所有的ROS回调函数就会被处理。
{

  nh.spinOnce();
  delay(1);
}

4.使用ros与arduino通信控制电机

4.1运行roscore

roscore

4.2新终端运行,/dev/ttyUSB0为Arduino设备端口,如果你的端口不是这个,注意修改

rosrun rosserial_python serial_node.py /dev/ttyUSB0

4.3发布主题,让电机转动

rostopic pub model std_msgs/Int8 "data: -1" 

注意:-1代表的是代码里的反转函数

             若是输入1,则代表正转;输入0,代表停止

5.键盘控制

         上面的步骤虽然能控制电机转动,但每次正转和反转都要在终端输入一遍rostopic pub model std_msgs/Int8 "data: 1"或着rostopic pub model std_msgs/Int8 "data: -1",非常不方便,因此就准备写一个python的控制脚步来代替终端来调用上面的程序,换句话说就是写一个键盘控制程序,定义“w==1(正转),s==0(停止),x==-1(反转)”,这样只需要在终端按w-s-x就可以控制电机了,不再需要一遍遍的输入rostopic pub model std_msgs/Int8 "data: x"。

5.1 检查ubuntu是否已下载好python编译器,没有的话自行下载

 5.2创建python脚步文件,名字随便取,后缀必须是.py

touch dianji2.py

 5.3打开文件输入代码

#!/usr/bin/env python
# coding=utf-8
import rospy

import geometry_msgs.msg 

from std_msgs.msg import Int8

import sys, select, termios, tty

count =0
model=0
#键值对应移动方向
moveBindings = {
        'w':(1),
        's':(0),
        'x':(-1),
           }
#获取键值函数
def getKey():
    tty.setraw(sys.stdin.fileno())
    rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
    if rlist:
        key = sys.stdin.read(1)
    else:
        key = ''

    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
    return key

#主函数
if __name__=="__main__":
    settings = termios.tcgetattr(sys.stdin) #获取键值初始化,读取终端相关属性
    
    rospy.init_node('up_down_plat') #创建ROS节点,节点名称为“up_down_plat"
    pub = rospy.Publisher('model',Int8,queue_size=5) #创建话题发布者,发布"model"为话题的消息

    try:
        while(1):
            key = getKey() #获取键值

            #判断键值是否在移动方向键值内
            if key in moveBindings.keys():
                model  = moveBindings[key]
                count = 0
                if(model==1):
                    print("上升")
                elif(model==0):
                    print("停止")
                elif(model==-1):
                    print("下降")


            #空键值/'k',相关变量置0
            elif key == ' ' or key == 'k' :
                model=0

            #长期识别到不明键值,相关变量置0
            else:
                count = count + 1
                if count > 4:
                    model= 0
                if (key == '\x03'):
                    break

            pub.publish(model) 

    #运行出现问题则程序终止并打印相关错误信息
    except Exception as e:
        print(e)

    #程序结束前发布速度为0的速度话题
    finally:
        model =0
        pub.publish(model)

    #程序结束前设置终端相关属性
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

这样就可以通过键盘实现按w上升,s下降,松开即停

5.4运行代码

5.4.1运行roscore

roscore

5.4.2新终端运行,/dev/ttyUSB0为Arduino设备端口

rosrun rosserial_python serial_node.py /dev/ttyUSB0

5.4.3另开一个终端运行dianji.py文件

python dianji2.py

猜你喜欢

转载自blog.csdn.net/m0_63647490/article/details/126797838
今日推荐