毕业设计 基于STM32的自动跟随小车 您所在的位置:网站首页 平衡车控制原理动画演示 毕业设计 基于STM32的自动跟随小车

毕业设计 基于STM32的自动跟随小车

2023-03-10 18:56| 来源: 网络整理| 查看: 265

0 前言

🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 毕业设计 基于STM32的自动跟随小车

🥇学长这里给一个题目综合评分(每项满分5分)

难度系数:3分工作量:3分创新点:4分

🧿 选题指导, 项目分享:

https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md

1 简介

自动跟随小车系统由两部分组成:跟随小车和移动目标携带装置。 工作原理:跟随小车系统通过无线通信模块发送寻找信号,同时超声波接收器开始计时,如果移动目标接收到无线寻找信号,则立即发送超声波信号。这样小车的三角超声波接收器陆续收到超声波信号,CPU通过每个超声波模块接收到的时间,计算出移动目标到3个超声波接收点的距离,通过三边定位算法即可确定移动目标的位置。如果计算出来的距离大于设定距离,则控制电机向目标方向移动,如果计算出来的距离小于设定距离,则控制电机停止,从而实现小车的自动跟随功能。

2 主要器件

STM32F103RCT6主控单片机

NRF2401无线收发模块

TL852超声波接收模块

L298N电源模块

电机及电机驱动模块

报警模块

3 实现效果

KMLKOA8}YD@{C(EPEHJJKRR.png在这里插入图片描述

4 设计原理 4.1 硬件设计

小车硬件设计:

自动跟随小车硬件模块包括控制器模块、无线收发模块、超声波接收模块、电机及电机驱动模块、报警模块、电源模块组成,下面对每个模块做具体介绍。

由于跟随小车需要进行实时目标位置定位计算、无线信号收发处理、电机管理、电源管理等任务 ,采用普通单片机其资源及速度难以满足使用要求,需要高性能DSP处理器才能够完成,因此选择STM32F103RCT6作为控制器。

引脚图

在这里插入图片描述

无线收发是用来实现同步,当小车发射无线信号,同时人手携带装置接收到无线信号时,人手携带装置发射超声波。所以本次设计选用NRF2401做为无线收发模块。

NRF2401各引脚功能为:

(1)CSN:芯片的片选线,CSN为低电平工作。

(2)SCK:芯片控制的时钟线(SPI时钟)。

(3)MISO:芯片控制数据线 。

(4)IRQ:中断信号,无线通信过程中MCU主要是通过IRQ与NRF2401通信。

(5)CE:芯片的模式控制线。

(6)MOSI:芯片控制数据线。

在这里插入图片描述

NRF的数据收发,是一包一包进行的,一包(帧)数据:包括了前导码、目标地址、包控制域、有效数据、CRC, 但我们只管有效数据,其它的不用我们负责,NRF发送时自动打包,接收到数据时自动拆包。

每一包的有效数据最大为32个字节。当然,也可以只发一个字节的数据。

要发送的数据大于32字节,就要分包进行,自行手动分包处理。

因为在配置部分时,已配置好了频道,速率,重发次数等各种参数,在需要发送数据时,只要往芯片写入要发送的数据和地址,然后切换为发送状态,芯片就会自动发送。

发送成功(收到ack),会产生TX_DS中断。

发送失败了(达到最大重发次数), 也会产生MAR_RT中断。

在中断函数里,根据情况作处理就好。

void vNrf24l01_TxPacket(u8 *txbuf) { CE_LOW; Nrf24l01_WriteBuf(W_TX_PAYLOAD, txbuf, 32); // 写数据到TX_BUFF Nrf24l01_WriteBuf(W_REGISTER+TX_ADDR, (u8*)TX_ADDRESS, 5); // 写入要发送的目标地址 Nrf24l01_WriteBuf(W_REGISTER+RX_ADDR_P0, (u8*)TX_ADDRESS, 5); // 通道0的地址设为和目标地址一致,以接收自动回复auto_ack信号 Nrf24l01_WriteReg(W_REGISTER+CONFIG, 0x0E); // 设置为发送模式,开启所有中断 CE_HIGH; }

TL852超声波接收模块

超声波接收模块是采用具有单独接收功能的模块,如图所示。其中接收模块核心部分是由专用超声波接收集成电路TL852构成的超声波信号检测电路,这部分主要完成的是回波的检测和放大。 B6FFG}LB~ZVM@FUO4]@%{Y4.png 直流电机的控制很简单,性能出众,直流电源也容易实现。这种直流电机的驱动及控制需要电机驱动模块进行驱动,采用L298N电源模块。

系统电源

系统电源采用7.4V可充电锂电池。7.4V锂电池组属于多串并锂电池组。

在这里插入图片描述

目标携带装置硬件设计:

由于跟随小车需要进行实时目标位置定位计算、无线信号收发处理、电机管理、电源管理等任务 ,采用普通单片机其资源及速度难以满足使用要求,需要高性能DSP处理器才能够完成,因此选择STM32F103RCT6作为控制器。

无线收发是用来实现同步,当小车发射无线信号,同时人手携带装置接收到无线信号时,人手携带装置发射超声波。所以本次设计选用NRF2401做为无线收发模块。

超声波发射模块是采用具有单独发射功能的模块,如图所示。其中发射模块中的P1 、R4、R5。因为利用了变压器和发射头的谐振,好处是能得到近似正弦波。但附带的问题是:在驱动信号停止后,由于谐振的原因,发射头还会持续较长时间发射,直至能量在变压器的次级线包直流电阻上消耗完,这样就导致在近距离测量时,回波都到了,余波还未结束,导致测量失败。所以设计了一个余波抑制电路,将变压器初级构成回路,利用初级较小的电阻快速消耗掉次级的能量。为此,要多占一个MCU的I/O口。而且,由于驱动电压的原因,必须使用OC(或者开漏)驱动,否则会无法可靠关断P1,导致正常发射不正常。如果测量的距离较远,或者觉得余波不影响测量,则不必接这个信号。如若使用,一定要注意和发射驱动信号的配合,不要两个同时有效,导致发射效率大减。从原理图上看,如果要提高驱动能量,可以适当提高驱动电压,但要要注意MOS管的耐压只有20V,发射头的最高电压是80V。

在这里插入图片描述

4.2 软件设计

小车控制流程图 在这里插入图片描述 目标携带装置控制流程图 在这里插入图片描述

5 部分核心代码 #define DEBUG 0 // set to 1 to print to serial monitor, 0 to disable #include Servo headservo; // // Constants const int EchoPin = 2; // const int TrigPin = 3; // const int leftmotorpin1 = 4; // const int leftmotorpin2 = 5; const int rightmotorpin1 = 6; const int rightmotorpin2 = 7 const int HeadServopin = 9; // const int Sharppin = 11; // const int maxStart = 800; // run dec time // Variables int isStart = maxStart; // int currDist = 0; // boolean running = false; void setup() { Serial.begin(9600); // pinMode(EchoPin, INPUT); pinMode(Sharppin, INPUT); for (int pinindex = 3; pinindex if (DEBUG) { Serial.print("running:"); if (running) { Serial.println("true"); } else { Serial.println("false"); } } if (isStart totalhalt(); // } int findsomebody = digitalRead(Sharppin); if (DEBUG) { Serial.print("findsomebody:"); Serial.println(findsomebody); } if (findsomebody > 0) { isStart = maxStart; } delay(4000); return; } isStart--; delay(100); if (DEBUG) { Serial.print("isStart: "); Serial.println(isStart); } currDist = MeasuringDistance(); // if (DEBUG) { Serial.print("Current Distance: "); Serial.println(currDist); } if (currDist > 30) { nodanger(); } else if (currDist // whichway(); randTrun(); } } / long MeasuringDistance() { long duration; // pinMode(TrigPin, OUTPUT); digitalWrite(TrigPin, LOW); delayMicroseconds(2); digitalWrite(TrigPin, HIGH); delayMicroseconds(5); digitalWrite(TrigPin, LOW); // pinMode(EchoPin, INPUT); duration = pulseIn(EchoPin, HIGH) return duration / 29 / 2; } // void nodanger() { running = true; digitalWrite(leftmotorpin1, LOW); digitalWrite(leftmotorpin2, HIGH); digitalWrite(rightmotorpin1, LOW); digitalWrite(rightmotorpin2, HIGH); return; } // void backup() { running = true; digitalWrite(leftmotorpin1, HIGH); digitalWrite(leftmotorpin2, LOW); digitalWrite(rightmotorpin1, HIGH); digitalWrite(rightmotorpin2, LOW); delay(1000); } // void whichway() { running = true; totalhalt(); // first stop! headservo.write(20); delay(1000); int lDist = MeasuringDistance(); // check left distance totalhalt(); // headservo.write(120); // turn the servo right delay(1000); int rDist = MeasuringDistance(); // check right distance totalhalt(); // if (lDist body_rturn(); } return; } // void totalhalt() { digitalWrite(leftmotorpin1, HIGH); digitalWrite(leftmotorpin2, HIGH); digitalWrite(rightmotorpin1, HIGH); digitalWrite(rightmotorpin2, HIGH); headservo.write(70); // set servo to face forward running = false; return; delay(1000); } // void body_lturn() { running = true; digitalWrite(leftmotorpin1, LOW); digitalWrite(leftmotorpin2, HIGH); digitalWrite(rightmotorpin1, HIGH); digitalWrite(rightmotorpin2, LOW); delay(1500); totalhalt(); } // void body_rturn() { running = true; digitalWrite(leftmotorpin1, HIGH); digitalWrite(leftmotorpin2, LOW); digitalWrite(rightmotorpin1, LOW); digitalWrite(rightmotorpin2, HIGH); delay(1500); totalhalt(); } void randTrun() { long randNumber; randomSeed(analogRead(0)); randNumber = random(0, 10); if (randNumber > 5) { body_rturn(); } else { body_lturn(); } } 最后


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

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