Preface: After successfully controlling the DC motor through the arduino development board, I began to try to use ros to communicate with the arduino to control the DC motor to prepare for the unmanned car
Reference Tutorial: Maker Smart Manufacturing
1. Hardware
Arduino development board, DuPont line, DC motor, L298N motor driver board
The connection of the board refers to my previous blog: L298N motor driver and Arduino board to control DC motor
2. Install arduino IDE and rosserial arduino under ubuntu
Reference link: Install the latest arduino and build ros_lib library
3. Open arduino to upload code
For beginners, it will be easier to understand by referring to Maker Wisdom and my previous blog (ie the first and second links)
#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. Use ros to communicate with arduino to control the motor
4.1 run roscore
roscore
4.2 The new terminal is running, /dev/ttyUSB0 is the Arduino device port, if your port is not this, pay attention to modify
rosrun rosserial_python serial_node.py /dev/ttyUSB0
4.3 Publish the topic and let the motor rotate
rostopic pub model std_msgs/Int8 "data: -1"
Note: -1 represents the inversion function in the code
If you input 1, it means forward rotation; if you input 0, it means stop
5. Keyboard control
Although the above steps can control the rotation of the motor, it is necessary to enter rostopic pub model std_msgs/Int8 "data: 1" or rostopic pub model std_msgs/Int8 "data: -1" in the terminal every time it is forward and reverse , very Inconvenient, so I am going to write a python control script to replace the terminal to call the above program, in other words, write a keyboard control program, define "w==1 (forward rotation), s==0 (stop), x==-1 (reverse)", so that you only need to press wsx on the terminal to control the motor, no need to input rostopic pub model std_msgs/Int8 "data: x" over and over again.
5.1 Check whether ubuntu has downloaded the python compiler, if not, download it yourself
5.2 Create a python script file, the name is random, and the suffix must be .py
touch dianji2.py
5.3 Open the file input code
#!/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)
In this way, you can use the keyboard to realize pressing w to rise, s to fall, and release to stop
5.4 Running the code
5.4.1 Running roscore
roscore
5.4.2 The new terminal is running, /dev/ttyUSB0 is the Arduino device port
rosrun rosserial_python serial_node.py /dev/ttyUSB0
5.4.3 Open another terminal to run the dianji.py file
python dianji2.py