在树莓派上做一个远程控制的小车(基于Python) 您所在的位置:网站首页 树莓派vnc远程控制 在树莓派上做一个远程控制的小车(基于Python)

在树莓派上做一个远程控制的小车(基于Python)

2023-11-06 19:04| 来源: 网络整理| 查看: 265

自制基于树莓派3B的WIFI控制小车 所需材料开发环境搭建实现的功能系统架构效果客户端实现代码标题服务端实现代码总结

所需材料

1.履带式底盘及电机:能适应大多数地形 2.L298N步进电机驱动板:驱动电机 3.AR9271无线网卡:虽然树莓派3B内置了wifi模块,但是此网卡信号更好。 4.树莓派500万摄像头:提供实时的视频信号 5.移动电源:树莓派的功耗低,移动电源为10000mA,给小车提供较长时间的续航。 6.超声波测距模块:使用距离探测避免碰撞

开发环境搭建

1.下载树莓派系统:在https://www.raspberrypi.org/downloads/下载Raspbian系统 2.下载win32软件 3.使用win32将下载好的系统文件烧录至内存卡 4.将内存卡插入树莓派并上电启动 5.使用sudo apt-get install python3 安装python3 6.使用python3 –m pip install upgrade pip 升级pip 7.使用pip install pyqt5 安装qt包 8.使用pip install pyqt-tools安装qt依赖包 9.使用sudo apt-get install mjpg-streamer安装视频服务 10.使用pip install socket 安装socket服务

实现的功能 远程控制小车行为接收小车的视频信号使用超声波模块避免碰撞 系统架构

在这里插入图片描述

效果

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

客户端实现代码 1.导入必要的包 from PyQt5 import QtCore, QtWidgets from PyQt5.QtCore import * from PyQt5.QtWidgets import * from PyQt5.QtGui import * import cv2 import sys import socket 2.定义 socket 方法: def sent_msg(msg): # 创建 socket 对象 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = '192.168.43.223' # 获取本地主机名 port = 9999 # 设置端口号 s.connect((host, port)) # 连接服务,指定主机和端口 s.sendall(msg.encode('utf-8')) #编码方式 s.close() 3.定义用户界面及行为 (利用QtDesigner和UIC对界面进行设计并转成Python文件) class Ui_Controller(object): def setupUi(self, Controller): Controller.setObjectName("Controller") Controller.resize(680, 535) self.widget = QtWidgets.QWidget(Controller) self.widget.setGeometry(QtCore.QRect(50, 30, 571, 271)) self.widget.setObjectName("widget") self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget) self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_4.setObjectName("horizontalLayout_4") spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem) self.label = QtWidgets.QLabel(self.widget) self.label.setText("") self.label.setObjectName("label") self.horizontalLayout_4.addWidget(self.label) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_4.addItem(spacerItem1) self.widget1 = QtWidgets.QWidget(Controller) self.widget1.setGeometry(QtCore.QRect(0, 330, 671, 193)) self.widget1.setObjectName("widget1") self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.widget1) self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_5.setObjectName("horizontalLayout_5") spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem2) spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem3) self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem4) spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem5) self.pushButton = QtWidgets.QPushButton(self.widget1) self.pushButton.setObjectName("pushButton") self.horizontalLayout.addWidget(self.pushButton) spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem6) spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem7) self.verticalLayout.addLayout(self.horizontalLayout) spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem8) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") spacerItem9 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem9) self.pushButton_3 = QtWidgets.QPushButton(self.widget1) self.pushButton_3.setObjectName("pushButton_3") self.horizontalLayout_2.addWidget(self.pushButton_3) spacerItem10 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem10) self.pushButton_5 = QtWidgets.QPushButton(self.widget1) self.pushButton_5.setObjectName("pushButton_5") self.horizontalLayout_2.addWidget(self.pushButton_5) spacerItem11 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem11) self.pushButton_4 = QtWidgets.QPushButton(self.widget1) self.pushButton_4.setObjectName("pushButton_4") self.horizontalLayout_2.addWidget(self.pushButton_4) spacerItem12 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem12) self.verticalLayout.addLayout(self.horizontalLayout_2) spacerItem13 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem13) self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") spacerItem14 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem14) spacerItem15 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem15) self.pushButton_2 = QtWidgets.QPushButton(self.widget1) self.pushButton_2.setObjectName("pushButton_2") self.horizontalLayout_3.addWidget(self.pushButton_2) spacerItem16 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem16) spacerItem17 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem17) self.verticalLayout.addLayout(self.horizontalLayout_3) self.horizontalLayout_5.addLayout(self.verticalLayout) self.checkBox = QtWidgets.QCheckBox(self.widget1) self.checkBox.setObjectName("checkBox") self.horizontalLayout_5.addWidget(self.checkBox) spacerItem18 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_5.addItem(spacerItem18) self.retranslateUi(Controller) QtCore.QMetaObject.connectSlotsByName(Controller) 4.用户行为方法调用 def retranslateUi(self, Controller): _translate = QtCore.QCoreApplication.translate Controller.setWindowTitle(_translate("Controller", "Form")) self.pushButton.setText(_translate("Controller", "前进")) self.pushButton.clicked.connect(self.on_Forward) self.pushButton_3.setText(_translate("Controller", "左转")) self.pushButton_3.clicked.connect(self.on_Turn_Left) self.pushButton_4.setText(_translate("Controller", "右转")) self.pushButton_4.clicked.connect(self.on_Turn_Right) self.pushButton_2.setText(_translate("Controller", "后退")) self.pushButton_2.clicked.connect(self.on_Back) self.pushButton_5.setText(_translate("Controller", "停止")) self.pushButton_5.clicked.connect(self.on_Stop) self.checkBox.setText(_translate("Controller", "防撞")) self.checkBox.stateChanged.connect(self.on_distance_module) @staticmethod def on_Forward(self): sent_msg("Forward") @staticmethod def on_Turn_Left(self): sent_msg("Left") @staticmethod def on_Turn_Right(self): sent_msg("Right") @staticmethod def on_Back(self): sent_msg("Back") @staticmethod def on_Stop(self): sent_msg("Stop") def on_distance_module(self,state): if state == QtCore.Qt.Checked: sent_msg("on") else: sent_msg("off") 5.使用 cv2 处理视频信号 class MainWindow(QMainWindow, Ui_Controller): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.timer_camera = QTimer(self) self.cap = cv2.VideoCapture("http://192.168.43.223:8085/?action=stream") self.timer_camera.timeout.connect(self.show_pic) self.timer_camera.start(10) def show_pic(self): success, frame = self.cap.read() frame = cv2.flip(frame, -1) if success: show = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) showImage = QImage(show.data, show.shape[1], show.shape[0], QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(showImage)) self.timer_camera.start(10) 6.主函数调用 if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) 标题服务端实现代码 1.导入必要的包 import socket,sys,os import wiringpi,time,multiprocessing 2.初始化使能引脚 wiringpi.wiringPiSetup() wiringpi.pinMode(0, 1) wiringpi.pinMode(1, 1) wiringpi.pinMode(2, 1) wiringpi.pinMode(3, 1) wiringpi.pinMode(24,0) wiringpi.pinMode(25,1) wiringpi.pinMode(28,0) wiringpi.pinMode(29,1) 3.定义小车类及方法 class Car(object): def __init__(self): self.Stop() def right_stop(self): wiringpi.digitalWrite(2, 0) wiringpi.digitalWrite(3, 0) def left_back(self): wiringpi.digitalWrite(0, 0) wiringpi.digitalWrite(1, 1) def right_back(self): wiringpi.digitalWrite(2, 0) wiringpi.digitalWrite(3, 1) def left_stop(self): wiringpi.digitalWrite(0, 0) wiringpi.digitalWrite(1, 0) def left_roll(self): wiringpi.digitalWrite(0, 1) wiringpi.digitalWrite(1 ,0) def right_roll(self): wiringpi.digitalWrite(2, 1) wiringpi.digitalWrite(3, 0) def Stop(self): self.right_stop() self.left_stop() def Run(self): self.right_roll() self.left_roll() def Left(self): self.left_back() self.right_roll() def Right(self): self.left_roll() self.right_back() def Back(self): self.left_back() self.right_back() 4.使用 socket 进行连接 def rec_msg(car,num): serversocket = socket.socket( socket.AF_INET, socket.SOCK_STREAM) host = '192.168.43.223' print(host) port = 9999 serversocket.bind((host, port)) serversocket.listen(5) while True: clientsocket, addr = serversocket.accept() rec_msg = clientsocket.recv(1024).decode('utf-8') if rec_msg == "Forward": car.Stop() car.Run() elif rec_msg == "Back": car.Stop() car.Back() elif rec_msg == "Left": car.Stop() car.Left() elif rec_msg == "Right": car.Stop() car.Right() elif rec_msg == "on": with num.get_lock(): num.value = 1 elif rec_msg == "off": with num.get_lock(): num.value = 0 else : car.Stop() clientsocket.close() 5.距离探测进行防撞 #模块中的引脚操作较多是因为这是一个相对独立的模块,同时测试也比较方便 def detect_distance(): time.sleep(0.01) wiringpi.digitalWrite(29, 1) time.sleep(0.00001) wiringpi.digitalWrite(29, 0) while wiringpi.digitalRead(28) == 0: pass time_start_F = time.time() while wiringpi.digitalRead(28) ==1: pass time_end_F = time.time() distance_F = ((time_end_F - time_start_F) * 34000) / 2 wiringpi.digitalWrite(25, 1) time.sleep(0.00001) wiringpi.digitalWrite(25, 0) while wiringpi.digitalRead(24) == 0: pass time_start_B = time.time() while wiringpi.digitalRead(24) ==1: pass time_end_B = time.time() distance_B = ((time_end_B - time_start_B) * 34000) / 2 if distance_F < 10 and distance_B > 15: wiringpi.digitalWrite(0, 0) wiringpi.digitalWrite(1 ,1) wiringpi.digitalWrite(2, 0) wiringpi.digitalWrite(3, 1) time.sleep(0.5) wiringpi.digitalWrite(0, 0) wiringpi.digitalWrite(1 ,0) wiringpi.digitalWrite(2, 0) wiringpi.digitalWrite(3, 0) if distance_F > 15 and distance_B < 10: wiringpi.digitalWrite(0, 1) wiringpi.digitalWrite(1 ,0) wiringpi.digitalWrite(2, 1) wiringpi.digitalWrite(3, 0) time.sleep(0.5) wiringpi.digitalWrite(0, 0) wiringpi.digitalWrite(1 ,0) wiringpi.digitalWrite(2, 0) wiringpi.digitalWrite(3, 0) if distance_F < 10 and distance_B < 10: wiringpi.digitalWrite(0, 0) wiringpi.digitalWrite(1 ,0) wiringpi.digitalWrite(2, 0) wiringpi.digitalWrite(3, 0) time.sleep(0.1) return distance_F, distance_B def safe_distance(num): while True: if num.value == 0: time.sleep(1) continue elif num.value == 1 : F,B = detect_distance() #print("f:",F,"b:",B) time.sleep(0.2) continue 6.主函数开启多进程 if __name__ == "__main__": car = Car() num = multiprocessing.Value('B',0) pid = os.fork() if pid == 0: rec_msg(car,num) else: safe_distance(num) 总结

这个项目花了三周时间才调试完成,其中主要是对于Python库的学习花的时间比较长,但是也让我充分认识到了Python的强大,另外,毕竟是第一次用Python写的一个完整的项目,总还是有不足的地方,希望网友们指针批评。

参考内容: [1] 简单WiFi控制小车系统(树莓派+python+web控制界面) https://blog.csdn.net/qq_41923622/article/details/85850780 [2]wiringPi使用手册 https://pypi.org/project/wiringpi/ [3] python +cv2实现视频流播放 https://www.baidu.com/link?url=VTy7HETvmQ6C73iq3Qz8xqFobfCZTMK52zyJZBXsQNPCPbmrihezYkhLdoKbK876IJzDtNWenbz8QkFcooalnciPbcrvv13pTPp0k2z6B93&wd=&eqid=f0fbfd88001672f5000000065cfbaddf [4] PyQt5中的事件和信号 https://www.cnblogs.com/archisama/p/5454200.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有