1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 1.树莓派 Python STM32 上位机 局域网 PC智能遥控小车(含源码)

1.树莓派 Python STM32 上位机 局域网 PC智能遥控小车(含源码)

时间:2023-10-19 17:21:10

相关推荐

1.树莓派 Python STM32 上位机 局域网 PC智能遥控小车(含源码)

整体功能:电脑上观看小车前方画面,通过电脑方向键控制小车前后运动、左右转弯,如前进后退键,按下前进或后退,松开停车,左右同理

关键技术部分:PC端:使用pygame编写上位机,作为服务器

树莓派端:图像获取、客户端编程、IO电平控制

STM32端:IO输入、PWM输出

电路端:STM32电路设计、H桥驱动电路设计

写在前面:局域网超视距遥控小车是笔者大四时的心愿,无奈当时没有时间和能力,研二才有机会继续完成,从车上的电路设计到树莓派程序,到局域网通信,到电脑上的UI设计到近期才全部能串起来,借这一DIY项目彩排一下老师的项目和实践近期所学。电脑端本计划写个像样的上位机,但没找的理想的键盘事件算法,但可以用pyqt5的按钮做控制,对使用Python写软件有兴趣的小伙伴移步专栏/qq_36071362/category_9697208.html

环境陈述:

1.老年时代的飞思卡尔c车,双电机,舵机转向

2.STM32C8T6单片机,keil,配双H桥驱动电路

3.树莓派4B,16G卡,Raspbian系统

4.Windows10,pycharm,Python3.7

功能陈述:

1.stm32制做底层控制板,H桥驱动,可直接接航模遥控器遥控

2.树莓派做小车端的图像获取和WiFi连接工具,运行socket的客户端

3.电脑端(Windows10)运行socket的服务端,显示树莓派传回的画面,检测电脑键盘方向键

控制流程:

电脑的服务端程序获取到方向键按下

→方向和前后信息传输至树莓派

→树莓派将画面实时传给电脑(一直传)将方向信息传给STM32

→32控制H桥控制电机正反转、控制舵机左右转

通信方式:

1.树莓派与电脑:WiFi,电脑和树莓派连接到同一路由器

2.树莓派与STM32:4个IO(因为作烧了树莓派的串口。。。。)

3.STM32与电机舵机:pwm,频率不同的脉宽调制信号,电机:10000hz,舵机:50hz

相关资料:

1.code1:STM32的小车控制程序-keil,c语言

2.code2:树莓派上的Python写的client程序,通过socket传输画面给电脑

3.code3:电脑上的Python写的server程序,通过socket接收画面,检测键盘按键,发送小车动作指令

4.schdoc、pcbdoc:电路设计文件

所做工作:

1.底层控制电路设计、焊接,作者前几年干过。。这版借师弟学习机会由他设计焊接板子,板子集成STM32与双H桥电机驱动电路

2.树莓派程序编写调试,树莓派端作为客户端需要从CSI摄像头获取画面通过WiFi传输至电脑,同时获取来自电脑的控制信息

3.电脑上编写服务器程序,使用pygame获取方向按键(没找的别的合适的包),显示树莓派的摄像头画面,发送方向控制信息

未来功能规划:

1.人脸跟踪人脸识别

2.目标识别

3.语音识别(语音控制)

4.xxxxx

下面贴出源码及介绍:

电脑端(服务端):

实现功能:

(1)通过socket实时接收树莓派的相机画面图片,并使用pygame显示

(2)在pygame的画面中,检测键盘方向键按下弹起情况,按下时分别通过socket发送“sta1”,“sta2”, “fta1”,“fta2”,弹起时若是前后键(即方向上下键),发送“sta0”,若是左右键,发送“fta0”

import socketimport cv2import numpyimport pygame# 服务器端的IP地址address = ("192.168.2.240", 8088)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.bind(address)s.listen(True)conn, addr = s.accept()sta = '0'fta = '0'def check_keydown_events(event, sock):if event.key == pygame.K_UP:sta = "sta1"print(sta)sock.send(sta.encode())elif event.key == pygame.K_DOWN:sta = "sta2"print(sta)sock.send(sta.encode())elif event.key == pygame.K_RIGHT:fta = "fta1"print(fta)sock.send(fta.encode())elif event.key == pygame.K_LEFT:fta = "fta2"print(fta)sock.send(fta.encode())#print(sta)#print(fta)def check_keyup_events(event, sock):if event.key == pygame.K_UP:sta = "sta0"print(sta)sock.send(sta.encode())elif event.key == pygame.K_DOWN:sta = "sta0"print(sta)sock.send(sta.encode())elif event.key == pygame.K_RIGHT:fta = "fta0"print(fta)sock.send(fta.encode())elif event.key == pygame.K_LEFT:fta = "fta0"print(fta)sock.send(fta.encode())##def check_events(sock):for event in pygame.event.get():# print("oooooo")if event.type == pygame.KEYDOWN:check_keydown_events(event, sock) #检测按键,发送数据print("1111111")elif event.type == pygame.KEYUP:check_keyup_events(event, sock)print("2222222")def recvall(sock, count):buf = b''start = "okok"start = start.encode()start = start.decode()start = start.encode()while count:newbuf = sock.recv(count)check_events(sock)#sock.send(start)if not newbuf: return Nonebuf += newbufcount -= len(newbuf)return bufpygame.init()screen = pygame.display.set_mode((640, 480))pygame.display.set_caption("遥控平台")while 1:length = recvall(conn, 16)stringData = recvall(conn, int(length))# stringData = stringData.encode()data = numpy.fromstring(stringData, dtype='uint8')decimg = cv2.imdecode(data, 1)#cv2.imshow('SERVER', decimg)cv2.imwrite('messigray.bmp', decimg)decimg1 = pygame.image.load('messigray.bmp')rect = decimg1.get_rect()screen.blit(decimg1, (0,0))pygame.display.update()# key = cv2.waitKeyEx(0)# print('key =', key)if cv2.waitKey(10) == 27:breaks.close()cv2.destroyAllWindows()

树莓派端(客户端):

实现功能:

(1)通过socket发送摄像头的画面图片

(2)接收socket中的方向和前后动作信息,即sta0-2和fta0-2,1和2分别是前进后退,左转右转,0是恢复,即停车或舵机回正

(3)通过IO传输从WiFi(socket)接收到的动作信息,因为串口占用,故使用4个IO,通过不同电平状态传输小车动作,因为转向动作和前后动作各包含三种状态(前后左右,回正和停车,不调速),故各分配两个引脚控制方向和前后

import socketimport cv2,timeimport numpyimport RPi.GPIO as GPIOimport pigpioGPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)# 设置引脚data1 = 4data2 = 17speed1 = 27speed2 = 22address = ('192.168.2.240', 8088)sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)sock.connect(address)capture = cv2.VideoCapture(0)ret, frame = capture.read()encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),90]GPIO.setup(data1, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(data2, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(speed1, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(speed2, GPIO.OUT, initial=GPIO.LOW)def forward():GPIO.setup(data1, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(data2, GPIO.OUT, initial=GPIO.HIGH)def back():GPIO.setup(data1, GPIO.OUT, initial=GPIO.HIGH)GPIO.setup(data2, GPIO.OUT, initial=GPIO.LOW)def stop():GPIO.setup(data1, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(data2, GPIO.OUT, initial=GPIO.LOW)def right():GPIO.setup(speed1, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(speed2, GPIO.OUT, initial=GPIO.HIGH)def left():GPIO.setup(speed1, GPIO.OUT, initial=GPIO.HIGH)GPIO.setup(speed2, GPIO.OUT, initial=GPIO.LOW)def retu():GPIO.setup(speed1, GPIO.OUT, initial=GPIO.LOW)GPIO.setup(speed2, GPIO.OUT, initial=GPIO.LOW)str222 = "123"str222 = str222.encode#sock.send(str222);while ret:ret, frame = capture.read()#frame = frame[200:480,0:640]frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)result, imgencode = cv2.imencode('.jpg', frame, encode_param)data = numpy.array(imgencode)stringData = data.tostring()strrr = str(len(stringData)).ljust(16)strrr = strrr.encode()sock.send(strrr);sock.send(stringData);# 用来非阻塞机制通信,0x40参数非常重要try:sdata = sock.recv(4, 0x40)sdata=sdata.decode()except BlockingIOError as e:sdata = "nnn"print(sdata)#print("35553")if sdata == "fta0":retu()if sdata == "fta1":right()if sdata == "fta2":left()if sdata == "sta0":stop()if sdata == "sta1":forward()if sdata == "sta2":back()#sdata = sock.recv(4)#if len(sdata)>0:print(sdata)#time.sleep(0.5)#sdata = sock.recv(2)#if len(sdata)>0:# print(sdata)#print(frame.shape)#frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)#decimg=cv2.imdecode(data,1)#cv2.imshow('CLIENT',frame)sock.close()cv2.destroyAllWindows()

STM32端(底盘控制端):

实现功能:

(1)检测树莓派输出引脚的电平状态,获取目标动作

(2)从(1)的信息中根据动作控制舵机转动

(3)从(1)的信息中根据动作控制电机动作

#include "led.h"#include "delay.h"#include "sys.h"#include "key.h"#include "usart.h"#include "exti.h"#include "wdg.h"#include "timer.h"#include "control.h"#include "pwm_in.h"#include "LQ12864.h"float angle_x;float angle_y;float angle_z;char stxt[20];int angle;int speed;int sta = 0;int FXsta = 0;int default_speed = 500;int main(void){SystemInit();delay_init(72);//ÑÓʱ³õʼ»¯NVIC_Configuration();//ÅäÖÃÖжÏ//KEY_Init();//°´¼ü¶Ë¿Ú³õʼ»¯ TIM2_PWM_Init();//ÐγÉPWM²¨ÐÎTIM1_PWM_Init();//ÐγÉPWM²¨ÐÎ//Timerx_Init(1000-1,72-1);//10KhzµÄ¼ÆÊýƵÂÊ£¬¼ÆÊýµ½5000Ϊ1ms TIM4_Cap_Init(0xffff,71); //ÒÔ1MhzµÄƵÂʼÆÊýLED_Init();//LCDÒý½Å³õʼ»¯ÔÚÕâÀïÃæLCD_Init(); //A0,A1ÓëÒ£¿ØÆ÷´«³åÍ»speed = 600;angle = 8570;TIM_SetCompare2(TIM1, angle);//TIM1µÄÕ¼¿Õ±È·´ÏòÊä³ö 8650Öмä ×î×ó8500 ×îÓÒ8800while(1){if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 0 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 0) speed=0; //Í£³µif(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 0 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1) {sta=1;speed=default_speed;} //Ç°½øif(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 0) {sta=2;speed=default_speed;} //ºóÍË// if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1) sta=4; //±¸ÓÃ---if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 0 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 0) angle=8555; //»ØÕýif(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 0 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1) angle=8755; //ÓÒתif(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 0) angle=8395; //×óת// if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1 && GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1) speed=500; //±¸ÓÃ----//Èí¼þÒ£¿Øif(sta == 1)//Ç°½ø{TIM_SetCompare1(TIM2, speed);TIM_SetCompare2(TIM2, 0);TIM_SetCompare3(TIM2, speed);TIM_SetCompare4(TIM2, 0);}if(sta == 2)//µ¹³µ{TIM_SetCompare1(TIM2, 0);TIM_SetCompare2(TIM2, speed);TIM_SetCompare3(TIM2, 0);TIM_SetCompare4(TIM2, speed);}if(speed == 0)//Í£³µ{TIM_SetCompare1(TIM2, 0);TIM_SetCompare2(TIM2, 0);TIM_SetCompare3(TIM2, 0);TIM_SetCompare4(TIM2, 0);}TIM_SetCompare2(TIM1, angle);//TIM1µÄÕ¼¿Õ±È·´ÏòÊä³ö 8650Öмä ×î×ó8500 ×îÓÒ8800}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。