参考教程:创客智造
arduino开发板、杜邦线、直流电机、L298N电机驱动板
板子的连接参考我之前写的博客:L298N电机驱动器和Arduino板来控制直流电机
参考链接:安装最新arduino和建立ros_lib库
对于新手而言,参考创客智造和我之前写的博客(即第一个和第二个链接)会更容易理解
#include
#include
#include //头文件
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 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);
}
roscore
rosrun rosserial_python serial_node.py /dev/ttyUSB0
rostopic pub model std_msgs/Int8 "data: -1"
注意:-1代表的是代码里的反转函数
若是输入1,则代表正转;输入0,代表停止
上面的步骤虽然能控制电机转动,但每次正转和反转都要在终端输入一遍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"。
touch dianji2.py
#!/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.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