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

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

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

STM32端:IO输入、PWM输出

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

写在前面:局域网超视距遥控小车是笔者大四时的心愿,无奈当时没有时间和能力,研二才有机会继续完成,从车上的电路设计到树莓派程序,到局域网通信,到电脑上的UI设计到近期才全部能串起来,借这一DIY项目彩排一下老师的项目和实践近期所学。电脑端本计划写个像样的上位机,但没找的理想的键盘事件算法,但可以用pyqt5的按钮做控制,对使用Python写软件有兴趣的小伙伴移步专栏https://blog.csdn.net/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 socket
import cv2
import numpy
import 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 socket
import cv2,time
import numpyimport RPi.GPIO as GPIO
import pigpioGPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)# 设置引脚
data1 = 4
data2 = 17
speed1 = 27
speed2 = 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}
}

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

  1. LabVIEW上位机学习 面对对象编程实例项目源码 与下位机PLC

    LabVIEW上位机学习 面对对象编程实例项目源码 与下位机PLC,工厂MES通讯,数据库,NI vision视觉等开发,及操作者框架源码可运行,想学习面对对象的可以参考 ID:16199647294 ...

  2. Python毕业设计基于django的就业系统项目(含源码)

    目录 一.Python毕业设计基于django的就业系统项目(含源码) 二.基于django的就业系统项目文件说明 一.Python毕业设计基于django的就业系统项目(含源码) 源 码 免 费 下 ...

  3. 基恩士上位机链路通讯_基恩士PLC通讯源码

    基恩士PLC KV7000,8000还是比较好用的,那如何和上位机通讯,我把源码写出来了.采用上位链路通讯,基恩士官方给我们留了8501端口,这个端口有意思刚好是我生日.基恩士的资料我觉得做的特别好, ...

  4. python图书推荐系统_在线图书推荐系统的实现含源码(协同过滤)

    项目简介 基于模型的协同过滤应用---图书推荐 本文实现对用户推荐图书的简单应用. 推荐算法: 在我们的在线图书推荐系统中,我们借用Spark的ALS算法的训练和预测函数,每次收到新的数据后,将其更新 ...

  5. Python桌面可视化+自动登录学校教务系统(含源码!!!)

    前言:通过Python爬虫与tkinter模块实现桌面快捷自动化登录教务系统 目录: 前言:通过Python爬虫与tkinter模块实现桌面快捷自动化登录教务系统 效果展示: 整体思路: 总体框架: ...

  6. python 生成exe 图片资源_爱豆图片下载(含源码及打包exe可执行文件)

    import requests from lxml import etree import os # etree解析网页并返回 def parse(url): headers = { 'User-Ag ...

  7. 毕设分享:基于STM32两轮自平衡小车 含源码、原理图及PCB文件

    love421个人博客地址:https://love421.github.io 一.硬件介绍 主控芯片用的是100脚的STM32F103VET6,陀螺仪用的是MPU6050,电机驱动用的是TB6612 ...

  8. python代码弄成网站_原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)...

    原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想) 总体思想: 希望让调用方通过 http调用传入一个需要生成图片的网页链接生成一个网页的图片并返回图片链接 最终调用 ...

  9. 原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)...

    原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想) 总体思想:     希望让调用方通过 http调用传入一个需要生成图片的网页链接生成一个网页的图片并返回图片链接 ...

最新文章

  1. python的执行效率没有c语言高,Python代码优化
  2. Oracle 11.2.0.4 x64 RAC扩展存储空间
  3. 合并分支到master上
  4. 网络营销外包——网络营销外包专员如何做好网站搜索引擎优化
  5. 多无人机对组网雷达的协同干扰问题 数学建模
  6. sql server自动备份
  7. 图像处理常用八大算法
  8. 助力双十一,促销海报设计模板收好!
  9. Fiddler代理配置
  10. 基于android的个人记账系统,android平台的个人记账系统的设计与实现.docx
  11. 二维码固定资产管理系统能解决企业的哪些痛点?
  12. pdf格式文件怎么编辑
  13. STM32H743IIT6+USB3300,USB_HS高速双向HID通讯开发
  14. oracle负数金额大写,Oracle 小写金额转换为大写
  15. word方框(□)打勾(√)方法
  16. linux获取android界面,Android中 adb shell ps 查看手机中进程信息
  17. Flak-SQLAlchemy安装和介绍
  18. otter异常——zookeeper重新初始化
  19. qlabel文本改变信号_改变人类历史的17个方程,神奇!
  20. 九章算术卷第八 方程

热门文章

  1. anacoda里面安装包显示失败_Photoshop解决安装失败!怎么办?!!!
  2. EDG刷屏、花椒沉寂,“初老”花房如何闯关IPO?
  3. Synergy在Linux与Win10上的下载和安装
  4. cosmos源码分析之二整体流程
  5. 浅析用户角色与用户画像
  6. kubernetes的Service Account和secret
  7. excel文件导入hive
  8. MAPGIS67无法显示点、无法保存点至e00的解决方法
  9. 《修改BIOS为品牌机信息安装激活Windows XP SP2》
  10. Drony 定向抓指定app的http,https包