[树莓派] 轻松制作一个遥控小车(C++,Socket)
Posted Weasker威斯克
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[树莓派] 轻松制作一个遥控小车(C++,Socket)相关的知识,希望对你有一定的参考价值。
最近闲来无事,便开始倒腾一些小玩具。我想从比较简单的开始入手,就先是树莓派遥控小汽车吧!
本文用来分享和总结经验。从0开始,小白级教程。
一.必备材料:
1.树莓派 1 个(什么版本都可以)
2.智能小车底盘 1 套(带电机)
3.L298N电机驱动板模块 1 个(3轮最多一个,4轮可以两个,但是需要更多电池,不推荐)
4.公对母杜邦线×8、普通导线×8
5.螺丝刀、扎带、小型充电宝
6.5号电池 4 节
二.小车组件安装
1.电机接线
按照下图,将电机的两端用两根导线相连,玩过四驱车的肯定都懂。因为是直流电机,所以不存在正负之分,随便连,剩下三个复制此操作。
2.L298N模块接线
AB:电机1接口,将一组电机导线两端分别接上。
CD:电机2接口,将另一组电机导线两端分别接上。
E:接电池正极,由于4节干电池电压不够,所以最好将树莓派+5V GPIO引脚也接入。
F:接电池负极。
G:接树莓派+5V GPIO引脚。
HIJK:IN1、IN2、IN3、IN4(IN1和IN2控制AB组电机,IN3和IN4控制CD组电机)。
3.树莓派GPIO接线
树莓派4b的GPIO接口图
由上图可知树莓派的GPIO口有7、11、12、13、15、16、18、22、29、31、32、33、36、37,小车只需用到4个即可(还有两个+5V口)。
将IN1、IN2、IN3、IN4分别接到GPIO口7、11、13、15位置。
(图中红色的是散热扇的线,请忽略)
4.车身固定
先将4个电机装好,再用扎带将电池盒、L298N模块、树莓派固定在底盘上,树莓派最好使用移动电源供电,所以部件摆放位置可以自由发挥。
二.代码实现
在终端输入
mkidr /home/pi/car #创建car目录
cd /home/pi/car #进入car目录
touch up.py #创建python文件
vim up.py #编辑python文件
然后在编辑器中按下"i"进入插入编辑模式并输入下面的代码。
"up.py"
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD) #设置GPIO口引用模式
IN1 = 7 #引用刚才接线的GPIO口
IN2 = 11
IN3 = 13
IN4 = 15
GPIO.setup(IN1,GPIO.OUT) #设置GPIO口为输出模式
GPIO.setup(IN2,GPIO.OUT)
GPIO.setup(IN3,GPIO.OUT)
GPIO.setup(IN4,GPIO.OUT)
GPIO.output(IN1,GPIO.HIGH) #根据L298N的操作说明来改变电平
GPIO.output(IN2,GPIO.LOW)
GPIO.output(IN3,GPIO.LOW)
GPIO.output(IN4,GPIO.HIGH)
输入完后按下"ESC"退出编辑模式,英文输入法下输入":“并输入"wq"保存退出(详情见VIM编辑器使用方法)
代码中的变量IN1和IN2控制第一组电机,IN3和IN4控制第二组电机。
上面的代码是负责前进的,根据他我们再创建"down.py”、“left.py”、“right.py”、"stop.py"四个python文件并修改对应的代码。
"down.py"
GPIO.output(IN1,GPIO.LOW)
GPIO.output(IN2,GPIO.HIGH)
GPIO.output(IN3,GPIO.HIGH)
GPIO.output(IN4,GPIO.LOW)
"left.py"
GPIO.output(IN1,GPIO.LOW)
GPIO.output(IN2,GPIO.HIGH)
GPIO.output(IN3,GPIO.LOW)
GPIO.output(IN4,GPIO.HIGH)
"right.py"
GPIO.output(IN1,GPIO.HIGH)
GPIO.output(IN2,GPIO.LOW)
GPIO.output(IN3,GPIO.HIGH)
GPIO.output(IN4,GPIO.LOW)
"stop.py"
GPIO.output(IN1,GPIO.LOW)
GPIO.output(IN2,GPIO.LOW)
GPIO.output(IN3,GPIO.LOW)
GPIO.output(IN4,GPIO.LOW)
此时我们的树莓派对GPIO的管理代码已经完毕,在终端输入:
sudo python up.py
即可调用"up.py"使小车转起来。
再输入:
sudo python stop.py
即可让小车停下。
这里可能的问题:
1.只有一两根轮子能转:说明电压不够,返回步骤"二-2"查看E接口,有没有将树莓派+5V接入。
2.轮子转动方向不同:说明电机接线反了或者代码里电平给错了,按组排查即可。
到了这里,小车就算是能跑起来了!但是不要沾沾自喜,还有很多功能等待你发掘。
用"sudo python XX.py"控制小车是不是非常蛋疼?由于python是为了玩这个紧急学习的,了解的并不多,所以我这里决定使用C++来编写一个socket通信来通过图形界面控制小车,也就是做个遥控器。这里只展示PC上的遥控器。
三.进阶遥控(选修)
1.服务端
我让树莓派作为服务端,在/home/pi/car路径下新建一个文件叫"CarServer.cpp"(确保你的树莓派装有g++用来编译.cpp文件,新一点的树莓派都自带,安装方法自行百度)。
使用vim CarServer.cpp进行编辑并将下面的代码复制进去。
#include <iostream>
#include <unistd.h>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
using namespace std;
#define USEPORT 1234
int main()
//****创建套接字
int serverSock = socket(AF_INET, SOCK_STREAM, 0);
//Windows中,AF_INET==PF_INET
//Linux中,不同的版本这两者有微小差别.对于BSD是AF,对于POSIX是PF
if (serverSock < 0)
cout << "socket creation failed" << endl;
exit(-1);
cout << "socket creation successfully" << endl;
//****绑定ip和端口
struct sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(USEPORT);
//INADDR_ANY绑定所有IP
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//****绑定套接字
if (bind(serverSock,(struct sockaddr*)&serverAddr,sizeof(struct sockaddr)) == -1)
cout << "Bind error, Port[" << USEPORT << "]" << endl;
exit(-1);
cout << "Bind successfully" << endl;
//****监听
if (listen(serverSock, 10) == -1)
cout << "Listen error!" << endl;
cout << "Listening on port[" << USEPORT << "]" << endl;
//****开始接收accept()
struct sockaddr clientAddr;
int size = sizeof(struct sockaddr);
int clientSock = accept(serverSock, (struct sockaddr*)&clientAddr, (socklen_t*)&size);
cout << "The Controler Connected!" << endl;
system("sudo python stop.py");
//****通信
while (1)
char revData[5];
int ret = recv(clientSock,revData,5,0);
if(ret > 0)
revData[ret] = 0x00;
cout<<"retrevData:"<<revData<<endl;
cout<<"lenth:"<<ret<<endl;
cout<<"revData:"<<revData<<endl;
if(strcmp(revData, "UPUP") == 0)
cout<<"up"<<endl;
system("ls");
system("sudo python up.py");
else if(strcmp(revData,"DOWN") == 0)
system("sudo python down.py");
printf("down");
else if(strcmp(revData,"LEFT") == 0)
system("sudo python left.py");
printf("left");
else if(strcmp(revData,"RIGHT") == 0)
system("sudo python right.py");
printf("right");
else if(strcmp(revData,"STOP") == 0)
system("sudo python stop.py");
printf("stop");
else if(strcmp(revData,"QUIT") == 0)
cout<<"shutdown"<<endl;
break;
close(serverSock);
return 0;
保存后在终端输入:
g++ CarServer.cpp
服务端就编写完了。
2.客户端
(1).在Qt Creator中,新建一个Qt Widgets Application项目,Build system选择qmake,基类选择QMainWindow。
(2).进入设计页面添加6个按钮和1个标签
(3).将4个控制上下左右的按钮的objectName改为:UpButton、DownButton、LeftButton、RightButton。
(4).将两个控制服务连接的按钮objectName改为:ConnectButton、BreakButton。(按钮的objectName可以自定义,不过下面的代码里也要跟着改)(双击组件可以修改标题名称)
(5).返回编辑页面,在.pro文件里添加:
QT += network
LIBS += -lpthread libwsock32 libws2_32
(6).在.h文件的构造函数的public里添加:
QTcpSocket* socket;
(7).在.h文件的构造函数里的public和private之间添加:
private slots:
void on_ConnectButton_clicked();
void on_UpButton_pressed();
void on_UpButton_released();
void on_BreakButton_clicked();
void on_DownButton_pressed();
void on_DownButton_released();
void on_LeftButton_pressed();
void on_LeftButton_released();
void on_RightButton_pressed();
void on_RightButton_released();
(8).进入mainwindow.cpp并将下面代码复制进去(注意修改下面的IP,每个人都不同):
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "iostream"
#include "string"
#include "winsock2.h"
#include <QApplication>
using namespace std;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
ui->setupUi(this);
socket = new QTcpSocket();
QObject::connect(socket,&QTcpSocket::readyRead,this,&MainWindow::on_ConnectButton_clicked);
MainWindow::~MainWindow()
delete ui;
void MainWindow::on_ConnectButton_clicked()
socket->abort();
socket->connectToHost("192.168.3.30",1234); //这里修改为你树莓派的IP,端口是服务端里设置的
if(!socket->waitForConnected(30000))
ui->label->setText("连接失败,请重试!");
else
ui->label->setText("连接成功!");
void MainWindow::on_UpButton_pressed()
socket->write("UPUP");
void MainWindow::on_UpButton_released()
socket->write("STOP");
void MainWindow::on_BreakButton_clicked()
socket->write("QUIT");
ui->label->setText("未连接!");
void MainWindow::on_DownButton_pressed()
socket->write("DOWN");
void MainWindow::on_DownButton_released()
socket->write("STOP");
void MainWindow::on_LeftButton_pressed()
socket->write("LEFT");
void MainWindow::on_LeftButton_released()
socket->write("STOP");
void MainWindow::on_RightButton_pressed()
socket->write("RIGHT");
void MainWindow::on_RightButton_released()
socket->write("STOP");
3.开始连接
先在Qt Creator中点击运行,然后在树莓派终端/home/pi/car路径下先输入:
g++ CarServer.cpp
./a.out
运行CarServer.cpp,此时点击连接按钮,终端显示连接成功。
此时点击"↑",服务端会显示信息说明通信成功。
出现"stop.py:RuntimeWarning:This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warning.”忽视即可。
至此小车就可以通过windows遥控了!
Bili视频教程:https://www.bilibili.com/video/BV1Di4y1E7dr/
如果过程中有问题欢迎私信我!记得关注喔!
以上是关于[树莓派] 轻松制作一个遥控小车(C++,Socket)的主要内容,如果未能解决你的问题,请参考以下文章
树莓派小车By 树莓派爱好者ITJoker(通过C socket通信实现树莓派视频小车)