【IoT】蔽障智能车设计:带有无线调试系统的蔽障小车

news2024/11/14 18:30:56

说明

近年来随着计算机在社会领域的渗透和大规模集成电路的发展,单片机的应用正在不断地走向深入,由于它具有功能强,体积小,功耗低,价格便宜,工作可靠,使用方便等特点,因此越来越广泛地应用各个领域. 51单片机是应用最广泛的一种。该系列单片机是应用最广泛的8位单片机之一,其代表型号是ATMEL公司的AT89系列。本项目采用STC89C52单片机。

在小车的实车行车中,需要大量的数据才能得到客观准确的结论。因此在开发调试过程中有一个使用简单,方便可靠的调试系统显得越来越重要。本项目基于nrf24L01进行无线传输,并基于VB进行上位机开发。

本项目整体架构就是以蔽障小车为载体对调试系统进行了开发。小车通过红外对管感应前方的障碍,利用各轮之间的差速实现转弯。无线采集系统会对实车行驶中的各项参数进行采集。

实物图

 硬件设计

1、主控电路板

小车利用三个(左、中、右)红外对管检测障碍物,并以STC89C52单片机为控制芯片控制电动小汽车的速度及转向,从而实现自动避障的功能。智能避障是基于红外传感系统,采用红外传感器实现前方障碍物检测。

2、参数

    A. 充电输入电压 10-12V。

     B. 充电电压最大8.4V 。

     C. 5V 输出最大电流 2A 。

    D. 电机驱动电流最大 1.2

3、主要功能

     A.蔽障。

     B.无线数据采集。

软件设计

程序对单片机端口以及nrf24L01无线模块进行初始化设置,然后启动定时器。如果定时器发生中断则执行中断程序。采集传感值并改变PWM值通过各轮的差速实现转向蔽障的功能。如果没有发生中断请求则进行无线发送数据。

无线调试系统设计

在实车的调试和结论分析过程中,需要大量的数据才能得到全面正确的结论。这就需要一个数据采集系统可以实时、准确的采集到相应的参数。无线数据采集系统可以满足这一要求。其相比于一般的数据采集系统在硬件方面得到很大程度的简化且使用可靠性更高。一般的数据采集系统是通过传感器将捕捉的现场信号转换为电信号,经模数转换器ADC采样、量化、编码后,为成数字信号,存入数据存储器,送给微处理器,通过串口方式送到上位机进行处理。无线数据传输系统就是这样一套利用无线手段,将采集的数据由测量站发送到主控站的设备。无线数据传输,它不仅简单、方便而且还成本低廉,受到普遍欢迎,开发的潜质也是有目共睹的。

nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型“SchockBurst”模式控制器、功率放大器、晶体振荡器、调制器和解调器。输出功率频道选择和协议的设置可以通过SPI 接口进行设置。几乎可以连接到各种单片机芯片,并完成无线数据传送工作。

极低的电流消耗:当工作在发射模式下发射功率为0dBm 时电流消耗为11.3mA ,接收模式时为12.3mA,掉电模式和待机模式下电流消耗更低。

1.无线数据采集系统整体框架

无线数据采集系统将各路传感器的信号、端口值经STC89C52单片机的转化处理通过nRF24L01的发送端将数字量发送给nRF24L01的接收端。nRF24L01的接收端接收到数据后,与上位机通信,上位机将数据经再处理后进行显示、保存等。

2.无线数据采集系统下位机设计

2.1下位机硬件设计

nRF24L01发送模块有两种:1.PCB板内置天线;2.模块外置天线。由于无线的传播距离的要求不是很远,采用了内置天线的nRF24L01发送模块,如下图所示。

2.2下位机软件设计

下位机的软件设计可分为四大部分:

(1). MISO、IRQ、CSN等端口状态设置

(2).nRF24L01通道、发射速率、中断响应等参数设置

(3). nRF24L01发送函数设计

nRF24L01发送函数:

void  nRF24L01_TxPacket(uint16 *Send_dat)

{

      NRF24L01_WriteReg(STATUS,0x7E);     //清除中断位

    CE_L();                    //StandBy I模式

    lot_write(0xA0-32,Send_dat,32);          //装数据

    CE_H();                  //置高CE,激发数据发送

while(IRQ_V()==1) ;

      CE_L();

  NRF24L01_WriteReg(STATUS,0x7E);     //清除中断位

}

此函数可以实现每次发送32字节。调用简单,只需将需要发送的数组写入函数的指针形参中即可。

(4).发送控制策略设计

发送控制策略:

方式一:在PIT中断中执行发送命令

方式二:在main主函数中执行发送命令

比较两种控制策略,方式一的发送数据的实时性,可靠性都优于方式二。但在实际的实验中发现,发送命令的执行会对其他PIT中断里的函数执行产生影响,不时发生程序跑飞的情况。鉴于在main主函数中执行发送命令,其程序运行的稳定性高,且发送数据的实时性和可靠性也可以满足实验要求,最终采用了方式二。

发送控制部分程序代码:

   for( ; ; )

 {

nRF24L01_TxPacket(Data);

     Delay(100);

  }

3.无线数据采集系统上位机设计

 3.1、上位机软件设计

(1)无线数据采集处理软件的界面(未运行)如图所示

 

 (2)无线数据采集处理软件的界面(运行)如图所示

 本软件基于VB6.0编写,其最大的特点在于:可视化强、使用方便。用户在使用本软件前应只需将USBnRF24L01接收模块  

插入usb端口,然后打开本软件,点击连接按钮。USBnRF24L01接收到的数据会自动显示在接收区内,并自动将数据以xls格式保存在excel文档中。点击保存按钮可以将数据以txt格式保存在文本文档中,方便后期对数据的分析处理。

(2)无线数据采集处理软件程序设计

①.实现无线的数据采集功能有两种:

方法一:基于普通nRF24L01接收模块。

硬件:普通nRF24L01接收模块,单片机,max232电平转换,串口线。

软件:基于vb自带的MSComm控件编程。

方法二.基于USBnRF24L01接收模块

硬件:USBnRF24L01接收模块。

软件:基于动态链接库Netusb.dll

比较两种方法,方法一基于vb自带的MSComm控件,编程难度相对简单,但硬件复杂,并且在发送频率高的情况下,易出现缓存溢出,数据丢失和卡死现象。方法二基于USBnRF24L01接收模块,硬件简单,使用方便。使用DLL文件可以在多个应用程序共享代码和数据。综合各方面,最终选定基于USBnRF24L01接收模块进行上位机开发。

②.程序主流程图(见图)

 

③.数据处理模块

I.进制转化

从缓存区读取得到的数据为二进制数

据可通过vb内置函数Hex(data)实现二进

制到十六进制数据的转换。但是无法直接

二进制到十进制的转化。于是,编写了十

六进制到十进制的转化函数HEX_to_DEC(data)

II.成列存储

每六个数据为一行所以通过求余运算,

对6求余为0时,则加换行符vbCrLf。这样就可形成6列的数据块。                       

III.数据再处理策略

由于对每一列数据的再处理不同,所以不能采用一个For循环对一组数据进行读取。最终采取了三个For循环来进行数据处理。

④.数据保存模块

I. xls格式保存

Excel文档中每一个单元格都有相应的坐标,所以只需将相应的数据置入相应的单元格即可。

II.txt格式保存

    需要先将一个文本文档打开,然后写入软件接收区的文本,最后关闭文档。完成保存。

⑤.通信模块

建立Netusb模块的bas文件。在bas文件中申明Netusb.dll动态链接库。实现USBnRF24L01接收模块与上位机的通信

⑥.程序部分代码

数据捕捉程序部分代码

Result = NetusbGetData_Noblock(buffer(0), datalen(0))

数据处理程序部分代码
s = " " & Hex(buffer(i))

sjz = HEX_to_DEC(s)

zzf = sjz / 10#

数据excle保存程序部分代码

ExSheet.Cells(count, j) = Text8.Text                 

ExSheet.Cells(count, d) = Text9.Text

数据文本显示程序部分代码

On Error Resume Next

ActiveWorkbook.SaveAs ("e:\data.xls")

If (i + 1) Mod 6 = 0 Then

Text4.Text = Text4.Text + "" + sjz + "                             " + vbCrLf

Else

Text4.Text = Text4.Text + "" + sjz + "                             "

End If

通信模块部分代码

Public Declare Function NetusbGetNumDevices Lib "Netusb.dll" Alias "_NetusbGetNumDevices@8" (ByVal vid As Integer, ByVal pid As Integer) As Long

Public Declare Function NetusbOpen Lib "Netusb.dll" Alias "_NetusbOpen@12" (ByVal deviceIndex As Long, ByVal vid As Integer, ByVal pid As Integer) As Byte

4.无线采集的数据 

小车程序代码

#include<reg52.h>
#define  uint unsigned int
#define  uchar unsigned char

#define CONFIG          0x00  // 配置收发状态,CRC校验模式以及收发状态响应方式
#define EN_AA           0x01  // 自动应答功能设置
#define EN_RXADDR       0x02  // 可用信道设置
#define SETUP_AW        0x03  // 收发地址宽度设置
#define SETUP_RETR      0x04  // 自动重发功能设置
#define RF_CH           0x05  // 工作频率设置
#define RF_SETUP        0x06  // 发射速率、功耗功能设置
#define STATUS          0x07  // 状态寄存器
#define OBSERVE_TX      0x08  // 发送监测功能
#define CD              0x09  // 地址检测           
#define RX_ADDR_P0      0x0A  // 频道0接收数据地址
#define RX_ADDR_P1      0x0B  // 频道1接收数据地址
#define RX_ADDR_P2      0x0C  // 频道2接收数据地址
#define RX_ADDR_P3      0x0D  // 频道3接收数据地址
#define RX_ADDR_P4      0x0E  // 频道4接收数据地址
#define RX_ADDR_P5      0x0F  // 频道5接收数据地址
#define TX_ADDR         0x10  // 发送地址寄存器
#define RX_PW_P0        0x11  // 接收频道0接收数据长度
#define RX_PW_P1        0x12  // 接收频道0接收数据长度
#define RX_PW_P2        0x13  // 接收频道0接收数据长度
#define RX_PW_P3        0x14  // 接收频道0接收数据长度
#define RX_PW_P4        0x15  // 接收频道0接收数据长度
#define RX_PW_P5        0x16  // 接收频道0接收数据长度
#define FIFO_STATUS     0x17  // FIFO栈入栈出状态寄存器设置

#define READ_REG 0;//读寄存器命令
#define WRITE_REG 0X20;//写寄存器命令
#define RD_RX_PLOAD 0X61;//读取接收数据命令
#define WT_TX_PLOAD 0XA0;//写代发数据命令
#define FLUSH_TX 0XE1;
#define FLUSH_RX 0XE2;
#define NOP 0XFF;//空命令
//标志位检测函数
uint NRF24L01_TxAddr[5];//={0x34,0x43,0x10,0x10,0XE7};
uint NRF24L01_RxAddr[5];//={0x34,0x43,0x10,0x10,0XE7};
uint Rev_dat[32]={0,0,0,0,0,0,0,0};
uint NRF24L01_TxAddr[5]={0x34,0x43,0x10,0x10,0XE7};
uint NRF24L01_RxAddr[5]={0x34,0x43,0x10,0x10,0XE7};

sbit Lsingal=P1^0;
sbit Msingal=P1^1;
sbit Rsingal=P1^2;

sbit CSN=P3^3;		
sbit MOSI=P3^4;
sbit SCK=P3^1;
sbit MISO=P3^2;
sbit IRQ=P3^5;
sbit CE=P3^0;
void SCK_H()   {SCK=1;}  
void MOSI_H()  { MOSI=1;}      //PA3
void CSN_H()   {CSN=1;}       //PA1
void CE_H()    {CE=1;}       //PA0
//置低函数
void SCK_L()  {SCK=0;}
void MOSI_L() {MOSI=0;}
void CSN_L()  {CSN=0;}
void CE_L()   {CE=0;}
void SpiWrite(uint send)
void lot_write(uint addr, const uint *str1,uint len)
void nRF24L01_TxPacket(uint *Send_dat)
void NRF24L01_Unit(void)
{
  
PORT_SET();//必须先进行端口状态设置,才能进行各种参数的配置
  
CE_L();    // chip enable
CSN_H();   // Spi disable 
SCK_L();   // Spi clock line init high
lot_write(TX_ADDR,NRF24L01_TxAddr,5);/// 写发送地址
lot_write(RX_ADDR_P0,NRF24L01_RxAddr,5);/// 写接收地址
NRF24L01_WriteReg(EN_AA,0x00);//0自动应答
NRF24L01_WriteReg(EN_RXADDR,0x01);//设置通道
NRF24L01_WriteReg(RF_CH,0);        
NRF24L01_WriteReg(RX_PW_P0,32); //设置接收数据长度,本次设置为32字节
NRF24L01_WriteReg(RF_SETUP, 0x0f); 
NRF24L01_WriteReg(CONFIG, 0x0e);   		 
}

/************************************************
* 												*
*                 IO口初始化					*
*												*
************************************************/
void io_Init(){
	 P2=0x00;
	 Lsingal=1;
	 Msingal=1;
	 Rsingal=1;
}
/************************************************
* 晶振频率:11.0592                             *
* T0:定时器 频率:100k  							*
* T1:计数器                                     *
************************************************/
void timer_Init(){
    TR0 = 0;
    TMOD = 0x01;
    TL0 =  0xD8;     	  //T0初值=2^16-定时时间/机器周期 机器周期=12*晶振
	TH0 =  0xEF;		  //      =55553
	TR0 = 1;
	IE =0x8A;
}
// 延时子程序 ms*250
void delayms(uchar ms)	
{						
	uchar i,j;
	while(ms--)
	{
		for(i = 0; i < 120; i++){
		   for(j = 0; j < 250; j++); 
		}
	}
}
//10ms
void delayten(uchar ms)	
{						
	uchar i,j;
	while(ms--)
	{
		for(i = 0; i < 120; i++){
		   for(j = 0; j < 10; j++); 
		}
	}
}
main (){
    P2=0xAA;
    io_Init();
    NRF24L01_Unit();
	timer_Init();
    for(;;){
	 nRF24L01_TxPacket(Rev_dat);
	 delayten(1);

	}
}
/*************************************************
* 1: 定时器0的中断号                             *
* 电机频率:1k                                   *
* 占空比:dutyRatio								 *
*************************************************/
void pwmInter(void) interrupt 1{
     uint lsgn=1;
	 uint msgn=1;
	 uint rsgn=1;
	 uint asgn=12;
	 lsgn=Lsingal;
	 msgn=Msingal;
	 rsgn=Rsingal;
	 EA=0;
     TH0 =  0xD8;
     TL0 =  0xEF;
	 asgn=4*lsgn+2*msgn+rsgn;
	 /*if(msgn==0){P3=0x99;}
	 else if(lsgn==0&&rsgn==1) {P3=0x99;}
	 else if(lsgn==1&&rsgn==0) {P3=0x66;}
	 else if(lsgn==0&&rsgn==0) {P3=0x99;}
	 else {P3=0xAA;}  */
	 switch(asgn)
	 {
	 case 7:
	        P2=0xAA;	
		    break;
	 case 6:
	        P2=0x44;
			while(Rsingal==0);
			delayms(20);
		    break;//					01000100
	 default:P2=0x11;
	         while(Lsingal==0||Msingal==0);
			 delayms(20);
	         break;				//		  00010001
	 }	 
	 Rev_dat[0]=lsgn;
	 Rev_dat[1]=msgn;
	 Rev_dat[2]=rsgn;
	 Rev_dat[3]=P1;
	 Rev_dat[4]=P2;
	 Rev_dat[5]=P3;
//	 nRF24L01_TxPacket(Rev_dat);
	 EA=1;	
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/188412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Activiti7工作流-使用idea插件actiBPM设计请假流程---工作流工作笔记005

首先我们看一下我们之前写的测试类, ProcessEngine 这个流程引擎,打开 看源码可以看到有几个常用的, HistoryService就是用来管理之前_hi表的,关于历史的 TaskService用来管理任务的 RuntimeService用来管理_run那些运行时的表的 然后我们还可以通过,上面定义的processEngi…

程序员的成长离不开哪些软技能?

道破一个残忍的真相&#xff1a;一个程序员的成长往往是软技能&#xff1e;硬技能&#xff0c;想纯靠技术能力一路挺过35岁基本是不可能的任务&#xff0c;作为一个优秀的程序员&#xff0c;离不开以下这些软技能。 较真 所有在技术上的较真都是一次专业技能的提升&#xff0…

Ruoyi-Cloud框架学习-【07 新增功能模块】

根据该博客新建模块后&#xff0c;在添加具体的数据表实现增删改查 在ruoyi-cloud中建立数据表 新建business_device表中【与gen_table、gen_table_column在一个库】 CREATE TABLE business_device (id bigint NOT NULL AUTO_INCREMENT COMMENT 主键,name varchar(255) COLLA…

USB转双串口芯片 CH342 兼容替代CP2105

概述CH342是一个USB总线的转接芯片&#xff0c;实现USB转两个异步串口。每个串口都支持高速全双工&#xff0c;支持奇偶校验&#xff0c;提供了常用的MODEM联络信号&#xff0c;用于为计算机扩展异步串口&#xff0c;或者将普通的串口设备或者MCU直接升级到USB总线。特点全速US…

PySpark数据分析基础:核心数据集RDD原理以及操作一文详解(一)

目录 前言 一、RDD概念 二、RDD与DataFrame之间的区别 特性区别 本质区别 三、PySpark中RDD的操作 1.aggregate 2.aggregateByKey 3.map 4.mapPartitions 5.getNumPartitions 6. glom() 点关注&#xff0c;防走丢&#xff0c;如有纰漏之处&#xff0c;请留言指教&am…

< 每日算法 - JavaScript解析:用两个栈实现队列 >

每日算法 - JavaScript解析&#xff1a;用两个栈实现队列一、任务描述&#xff1a;拓展知识二、问题解析三、解决方案&#xff1a;参考文献往期内容 &#x1f4a8;一、任务描述&#xff1a; 用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和…

JS扩展运算符(...)的用法

参考链接&#xff1a; 本文可以说是完全抄写的参考链接的内容&#xff0c;本文的目的只用于自己进行记录&#xff0c;加深理解。原文参考链接 一、定义&#xff1a; 扩展运算符(...)是ES6的新增语法&#xff0c;用于取出参数对象中的所有可遍历属性&#xff0c;然后拷贝到当前…

vue移动端适配方案

一、基于rem的适配方案 rem是什么&#xff1f; rem是指相对于根元素的字体大小的单位&#xff0c;在日常开发过程中我们通常把根元素&#xff08;html/body&#xff09;的字体设置为10px,方便于我们计算&#xff08;此时子元素的1rem就相当于10px&#xff09;。 适用场景 不…

开学季,给上小学的孩子送什么比较好?小学生比较实用的礼物

很快来临开学的日子&#xff0c;对于上小学的孩子们&#xff0c;送写学习用具之类&#xff0c;或者是孩子自身喜欢的玩具也可以的&#xff0c;但是因为大部分小朋友在学习时都会眨眼睛&#xff0c;也有些近视的现象了&#xff0c;所以我会选择送护眼的用具比较合适的&#xff0…

DBCO-SS-NHS;CAS NO:1435934-53-4 二苯并环辛炔-二硫键-活性酯,科研实验用试剂

DBCO-SS-活性酯|DBCO-SS-NHS酯 名称;二苯并环辛炔-二硫键-活性酯&#xff1b;DBCO-SS-NHS CAS NO&#xff1a;1435934-53-4 分子量&#xff1a;565.66 分子式&#xff1a;C28H27N3O6S2 含 量&#xff1a;>95% 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于诊治…

Kettle(三)数据写入错误如何处理?

Kettle作为数据治理工具&#xff0c;总是会涉及到数据的搬迁&#xff0c;在原始数据过大、种类过多时写入肯定会出现一些错误&#xff08;缺少必填项、数据格式错误、主键冲突等等&#xff09;&#xff0c;那么Kettle如何解决&#xff1f;其实Kettle与我们自己写程序的思维不会…

从零开发一个非常有意思的 Python 项目:手势识别

最近开发了一个手势处理的项目&#xff08;零基础也可以学&#xff0c;就是针对零基础的&#xff09;&#xff0c;我在这儿简单的复述一下原理&#xff0c;总体来说还是比较简单的&#xff0c;主要运用的知识就是opencv&#xff0c;python基本语法&#xff0c;图像处理基础知识…

OCR文字识别技术

OCR全称是optical character recognition&#xff0c;中文光学字符识别。主要技术是&#xff1a;把图像形状转变为文本字符。简单来说&#xff0c;OCR技术就是通过图像处理和模式识别技术对光学的字符进行识别&#xff0c;即&#xff0c;对文本资料进行扫描&#xff0c;然后对图…

呕心沥血保姆级Fiddler移动端抓包

本篇文章&#xff0c;博主想使用通俗易懂的话语&#xff0c;让大家明白以下内容&#xff1a;什么是抓包哪些场景需要用到抓包Fiddler抓包的原理怎样使用Fiddler进行移动端抓包抓包包 (Packet) 是TCP/IP协议通信传输中的数据单位&#xff0c;一般也称“数据包”。我们平常测试过…

PCI设备的访问方法_非桥设备(type0)

PCI设备的访问方法_非桥设备(type0) 文章目录PCI设备的访问方法_非桥设备(type0)一、硬件结构二、 PCI本地总线的信号三、 访问PCI设备3.1 怎么访问PCI设备3.1 PCI设备的地址空间3.2 访问PCI设备的步骤3.3 示例&#xff1a;配置PCI Agent设备致谢一、硬件结构 PCI系统框图&…

2023年第七届航空航天、机械与机电工程国际会议(CAMME 2023)

2023年第七届航空航天、机械与机电工程国际会议(CAMME 2023) 重要信息 会议网址&#xff1a;www.camme.org 会议时间&#xff1a;2023年5月26-28日 召开地点&#xff1a;中国西安 截稿时间&#xff1a;2023年4月26日 录用通知&#xff1a;投稿后2周内 收录检索&#xff1a;EI,S…

ORA-01691: unable to extend lob segment

报错信息&#xff1a; ORA-01691: unable to extend lob segment YUNYAO.SYS_LOB0000152921C00013$$ by 1024 in tablespace USERS 针对此问题查了一些文章&#xff0c;排查到原因是表空间“USERS”的数据文件满了&#xff0c;到达最大值。 可能会出现的原因如下&#xff1a…

【Linux】gdb调试器

【Linux】gdb调试器 文章目录【Linux】gdb调试器1、调试器的意义2、gdb调试器介绍2.1 gdb的作用2.2 gdb的配置3、gdb调试器的使用3.1 常用调试命令3.2 调试前准备3.3 指令演示3.3.1 断点3.3.2 逐过程、逐语句3.3.3 查询变量3.3.4 跳转3.3.5 结束函数、跳出执行3.3.4 跳转3.3.5 …

Redis缓存穿透——实战代码教学,亲身体验高并发如何解决

&#x1f680; 注重版权&#xff0c;转载请注明原作者和原文链接 &#x1f96d; 作者&#xff1a;全栈小袁 &#x1f34e; 原创个人开源博客项目(目前V2.0微服务版本)&#xff1a;https://github.com/yuanprogrammer/xiaoyuanboke &#x1f349; 开源项目觉得还行的话点点star&…

Drain3改进的日志解析方法+代码

这本项目继承于https://github.com/logpai/Drain3 在此项目的基础上进行了改进&#xff0c;目前代码在PR阶段&#xff0c;感兴趣的可以从PR上拉取&#xff1a; 前言&#xff1a; 本项目继承于https://github.com/logpai/Drain3 在此项目的基础上进行了改进&#xff0c;目前代码…