单片机设计基于STM32的驿站取货小车系统


主要介绍

  本设计采用的是STM32F103C8T6单片机作为主控模块,视觉识别系统采用带FIFO的OV7670作为信号输入,实现数字识别的功能。显示系统部分采用的是ILI9341显示屏,具有显示及触摸功能,提高取货准确率。循迹部分采用的是黑色胶带对光的反射作用会对光敏电阻的阻值产生影响,继而实现本设计的循迹功能,确保小车不会脱轨,电机驱动部分采用强磁直流减速电机,为本设计提供驱动力。另外,本设计通过控制电机正反转实现设计的自由变换方向和启动停止。通过视觉识别功能,可以达到准确识别取货码,确定位置,实现取货的要求。

一、系统主要功能

  

1.2.1 系统的工作原理

⑴ 循迹原理:该原理利用了光的反射,相同光照强度的光照射在颜色不同的物体上,其反射之后的光亮是不同的,对于光敏电阻阻值的影响也是不同的,而且反射值可以通过AD采样值进行检测。光线反射到光敏电阻上,可以通过检测光敏电阻的阻值来判断小车是否在黑色区域内。离黑色区域越近,光吸收的越多,反射的越少,光敏电阻阻值越大,分压也就越大,反之,离黑色区域越远,分压越小,电压大小控制电机,进而控制小车方向。
⑵ 数字识别原理:
① 图片预处理。此步骤分为识别图像,灰度化以及二值化。
② 图像分割。首先对原始图像的字符进行上下切割个左右切割。基本原理是,从图像第一列开始,从左往右扫描,当遇到像素值为0时,记录该列号s Col,继续扫描遇到整列像素值为255时,记录列号e col,s col与e Col之间为字符所在区间。复制二值图该区域,这样完成了左右分割,之后再依照这种方式进行上下分割。
③ 识别。利用代码将原始图像进行上下左右切割,使其具有与模板的数字图像同样的大小,之后将切割后的图片的对应坐标像素点与其余的模板的像素点相减(像素点一般挑选十个),求出所有像素点之差的绝对值之和。
④ 最后切割后的图片与哪个模板之差的绝对值最小,则可以确定这两个数字最为匹配,即可得到该数字值。

1.2.2 系统的结构

系统结构框图如图1.1所示:

在这里插入图片描述

图1.1 系统框图
⑴ 主机控制模块
主控芯片采用STM32f103c8t6,通过软件程序控制显示模块、电机驱动模块及视觉识别模块。
⑵ 电机驱动模块
包括2个电机,一个万向轮。通过两个电机的正反转开控制小车的方向及行驶,达到符合程序所要求的目的。
⑶ 视觉识别模块
起到信号传递及识别的作用。通过ov7670完成图像的获取,再通过程序及stm32实现数字识别,最终根据已识别的数字准确找到目标快件。
数字识别过程框图如图1.2所示:
在这里插入图片描述
图1.2 数字识别过程框图

二、 软件设计

  

3.1系统主程序设计

主程序循环模块中的程序执行优先级应是最低的。主程序的设计首先应包含单片机初始化,以及开机过程中所必要的实施模块,这些模块大部分只在单片机开机复位结束之后执行一次。其次,单片机应该具有循环执行的模块,这些模块即是在单片机运行过程中保持单片机一直运行的模块。在程序设计中,最重要的操作是确定程序流程框图。
如图3.1主程序流程框图所示,主程序部分包括系统的初始化、等待取货码、循迹、识别、完成取货、最后返回。如图可知,这个循环处理模块分别包含等待取货码、循迹、识别、完成取货四个部分。

在这里插入图片描述

3.2 数字识别子程序设计

数字识别实现的基本过程是:灰度处理、二值化、图像分割、识别。
子程序设计图如图3.2所示。

三、实物展示

  
系统主要有六个部分组成:电源模块、ov7670模块、电机驱动模块、显示模块、按键模块以及主控模块这六个模块组成,在系统的搭建上,采用模块分别进行的方式在万用板上搭建电路。分模块进行的好处就是系统走线比较清晰,适合在万用板上进行电路的搭建。四节干电池放在电池盒内,与此同时引出两根导线,与电路板相接,为整个系统提供电流,系统控制主要模块展示如图4.1所示:

在这里插入图片描述

循迹模块展示图如图4.2所示:
在这里插入图片描述

图4.2 循迹模块展示图

程序

单片机程序全部源码:
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "ov7670.h"
#include "exti.h"
#include "key.h"
#include "sram.h"	
#include "math.h"
#include "usart.h"	
#include "malloc.h"	
#include "w25qxx.h" 

void Prewitt(void);
void horizontal(void);
void small2big(u8 YL,u8 YH,u16 XL,u16 XH);
void big2small(u8 x1,u16 y1);
u8 charcter_zoen();

extern u8 ov_sta;	
u16 picture[320][240] __attribute__((at(0X68000000)));
u8 dis_gray[320][240]   __attribute__((at(0X68025804)));
u8 dis_sobel1[320][240] __attribute__((at(0X68038408)));
u8 dis_sobel2[320][240] __attribute__((at(0X6804b00c)));

u16 astart,aend;
u8 bstart,bend;

u8 mheight,mwidth;

#define RGB565_RED 0xf800
#define RGB565_GREEN  0x7e0
#define RGB565_BLUE 0x1f

void camera_refresh(void)
{
	u32 j;
 	u16 color;	
  u8 r,g,b;	
	if(ov_sta)
	{

		LCD_WriteRAM_Prepare(); 	
		OV7670_RRST=0;				   
		OV7670_RCK_L;
		OV7670_RCK_H;
		OV7670_RCK_L;
		OV7670_RRST=1;				 
		OV7670_RCK_H;
		
		for(j=0;j<76800;j++)
		{
			OV7670_RCK_L;
			color=GPIOC->IDR&0XFF;	
			OV7670_RCK_H; 
			color<<=8;  
			OV7670_RCK_L;
			color|=GPIOC->IDR&0XFF;	
			OV7670_RCK_H; 
			picture[j%320][j/320] = color;
			r=(color&RGB565_RED)>>11;
			g=(color&RGB565_GREEN)>>6;
			b=(color&RGB565_BLUE);
			color=(r*19595+g*38469+b*7472+32768)>>16;			
			dis_gray[j%320][j/320] = color;
		   
		}   							  
 		ov_sta=0;					

	} 
}	   

void datashow(u8 mode)
{
		 u32 j;
	for(j=0;j<76800;j++){
	     if(1==mode)
					LCD->LCD_RAM=picture[j%320][j/320];	
				else if(2==mode)
					LCD->LCD_RAM=(u16)((dis_gray[j%320][j/320]<<11)|(dis_gray[j%320][j/320]<<6)|dis_gray[j%320][j/320]);
				else if(4==mode)
					LCD->LCD_RAM=(u16)((dis_sobel1[j%320][j/320]<<11)|(dis_sobel1[j%320][j/320]<<6)|dis_sobel1[j%320][j/320]);
	     else if(6==mode)
					LCD->LCD_RAM=(u16)((dis_sobel2[j%320][j/320]<<11)|(dis_sobel2[j%320][j/320]<<6)|dis_sobel2[j%320][j/320]);	
			} 							  
}

 u8 key=0;

 int main(void)
 {	 

  u8 s,data;
	u8* demo;
	int i,j,kk;
	delay_init();	    	 	  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	KEY_Init();
	EXTIX_Init();
	W25QXX_Init();
	uart_init(115200);
	FSMC_SRAM_Init();			  
	LCD_Init();			   		  
	LCD_Scan_Dir(U2D_L2R);		  

	demo=mymalloc(0,180*90);
	memset(demo,0,90*180); 
	while(OV7670_Init())//初始化OV7670
	{
	
	  LCD_Fill(30,230,239,246,WHITE);
		delay_ms(200);
	}
 
  OV7670_Mode_Init();	
	EXTI8_Init();						
	OV7670_Window_Set(12,176,240,320);		  
  OV7670_CS=0;					
	LCD_Clear(BLACK);

 	while(1)
	{	
		camera_refresh();
		datashow(1);
		
		 if(key!=0)
		 {
			switch(key)
			{				 
				case  2:	
				{		
					for(s=1;s<11;s++)
					{
					 W25QXX_Read((u8*)demo,s*16200,16200);
					
					for(i=0;i<180;i++)
	        {
		        for(j=0;j<90;j++)
						{
							kk=i*90+j;
							dis_sobel2[i][j]=demo[kk];
						}
					}
					 LCD_Clear(WHITE);	 
		     datashow(6);
					delay_ms(1000);
			
				}
			}
					break;
				
				case 4:	
				{
					datashow(2);
					Prewitt();
          datashow(4);
					horizontal();
					small2big(bstart,bend,astart,aend);
			    big2small(0,0);
			   data=charcter_zoen();
	       LCD_Scan_Dir(DFT_SCAN_DIR);					
					POINT_COLOR=BLACK;
          LCD_ShowString(15,250,200,24,24,"The number is:  ");	
          POINT_COLOR=RED;					
				  LCD_ShowNum(190,250,data,1,24); 
					delay_ms(5000);
					LCD_Scan_Dir(U2D_L2R);		
				}
					break;
				
			}
	
      	key=0;
	}	
}		 
}
void Templat(u8 dis_sobel[320][240],u8 wide,u16 height,u8 tempH,u8 tempW,u8 tempMX,u8 tempMY,float fparray[],float fCoef)
{
	u16 lie,hang,k,l;
	float fResult;	
	for(hang=tempMY;hang<height-tempH+tempMY+1;hang++)
		for(lie=tempMX;lie<wide-tempW+tempMX+1;lie++)
		{
			fResult=0;
			for(k=0;k<tempH;k++)
				for(l=0;l<tempW;l++)
				{
					fResult+=dis_gray[(hang-tempMY+k)][(lie-tempMX+l)]*fparray[k*tempW+l];
				}
				fResult*=fCoef;
				fResult=(float)fabs(fResult);
				if(fResult>31) dis_sobel[hang][lie]=31;
				else dis_sobel[hang][lie]=(u8)(fResult+0.5);
		}	
}
void Prewitt(void)
{
	u16 i,j;
	float tempC,Template[9];
	u8 tempH,tempW,tempMX,tempMY;
	tempW=3;
	tempH=3;
	tempC=1;
	tempMX=1;
	tempMY=1;
	Template[0]=-1;
	Template[1]=-1;
	Template[2]=-1;
	Template[3]=0;
	Template[4]=0;
	Template[5]=0;
	Template[6]=1;
	Template[7]=1;
	Template[8]=1;
	Templat(dis_sobel1,240,320,tempH,tempW,tempMX,tempMY,Template,tempC);
	Template[0]=1;
	Template[1]=0;
	Template[2]=-1;
	Template[3]=1;
	Template[4]=0;
	Template[5]=-1;
	Template[6]=1;
	Template[7]=0;
	Template[8]=-1;
	Templat(dis_sobel2,240,320,tempH,tempW,tempMX,tempMY,Template,tempC);
	for(i=0+1;i<240-1;i++)
		for(j=0+1;j<320-1;j++)
		{
			if(dis_sobel2[j][i]>dis_sobel1[j][i])
				dis_sobel1[j][i]=dis_sobel2[j][i];
		}

}
void aver_t(u8 temp[320][240],u16 h,u16 w,u16 begin_x,u16 begin_y)
{
	u8 T1=0;
	u32 i,j,t=0;
	
	for(j=begin_y;j<h+begin_y;j++)
		for(i=begin_x;i<w+begin_x;i++)
			t+=dis_gray[j][i];
	T1=t/((h)*(w))-12;

	for(i=begin_x;i<w+begin_x;i++)
	{
		for(j=begin_y;j<h+begin_y;j++)
		{
			if(temp[j][i]<T1) temp[j][i]=0;
			else temp[j][i]=31;
		
		}
	}
}


void aver_t1(u8 temp[320][240],u16 h,u16 w,u16 begin_x,u16 begin_y)
{
	u8 T1=0;
	u32 i,j,t=0;
	
	for(j=begin_y;j<h+begin_y;j++)
		for(i=begin_x;i<w+begin_x;i++)
			t+=dis_gray[j][i];
	T1=t/((h)*(w))-5;

	for(i=begin_x;i<w+begin_x;i++)
	{
		for(j=begin_y;j<h+begin_y;j++)
		{
			if(temp[j][i]<T1) temp[j][i]=0;
			else temp[j][i]=31;
		
		}
	}
}
void horizontal(void)
{
	u16 i,j;
	u16 start=0,end=0; 
	u8 in=0,white=0,num=0,uline=0,x=0;
	aver_t(dis_sobel1,320,240,0,0);
	datashow(4);
	for(j=10;j<320;j++)
		for(i=10;i<240;i++)
			dis_sobel2[j][i]=0;
	for(j=0;j<319;j++)
	{
		for(i=0;i<239;i++)
		{
			if(dis_sobel1[j][i]==31)	white=1;
			
			if((0==in)&&(1==white))in=1;
			else if((1==in)&&(1==white))num++;
			else if((1==in)&&(0==white)&&(num>=1)) 
			{
				in=0;
				x++;
				num=0;
			}
			white=0;
		}
		if(x>=1)
		{
			if(0==uline)
				start=j;
			  uline++;
		}
		else
		{
			if(uline>=5)
			{
				//end=j;
				astart=start;
				aend=j;
				break;
			}
			start=0;
			uline=0;
		}
		x=0;
	}	
	
		POINT_COLOR=BLUE;  	
	LCD_DrawLine(astart,0,astart,319);
  POINT_COLOR=GREEN;
  LCD_DrawLine(aend,0,aend,319);
	mheight=start-end+1+8;
	white=0;
	in=0;
	num=0;
	x=0;
	uline=0;
	for(i=0;i<239;i++)
	{
		for(j=astart-4;j<aend+4;j++)
		{
			if(dis_sobel1[j][i]==31)	white=1;
			if((0==in)&&(1==white)) in=1;
			if((1==in)&&(1==white)) num++;
			if((1==in)&&(0==white)&&(num>=1)) 
			{
				in=0;
				x++;
				num=0;
			}
			white=0;
		}
		if(x>=1)
		{
			if(0==uline)
				start=i;
			uline++;
		}
		else
		{
			if(uline>=5)
			{
				end=i;
				bstart=start;
				bend=end;
				break;
			}
			start=0;
			uline=0;
		}
		x=0;
	}	
	POINT_COLOR=RED;  	
	LCD_DrawLine(0,bstart,319,bstart);
	POINT_COLOR=YELLOW;
	LCD_DrawLine(0,bend,319,bend);
	printf("astart=%d,aend=%d,mheight=%d,bstart=%d,bend=%d,uline=%d\t\n",astart,aend,mheight,bstart,bend,uline);	
	for(j=astart;j<aend;j++)
		for(i=bstart;i<bend;i++)
		{
			dis_sobel2[j][i]=dis_gray[j][i];
		}		
		
	  mwidth=bend-bstart+1;
		delay_ms(1000);
    LCD_Clear(WHITE);	 
		datashow(6);
		
	  aver_t1(dis_sobel2,320,240,0,0);
		delay_ms(1000);
    LCD_Clear(WHITE);	 
		datashow(6);
		
}
void small2big(u8 YL,u8 YH,u16 XL,u16 XH)
{
	u16 w1; 
	u16 h1;
	u8 w0,h0,j;
	u16 size0,size1,kk;
	vu16 i;
	float fw; 
	float fh;
	int y1,y2,x1,x2,x0,y0;
	float fx1,fx2, fy1,fy2;
	float s1,s2,s3,s4;
	int rd, ld, lu, ru;
	int pix;
	
	u8 *ipDIBBITS=0,*pTemp;
	
	w0=YH-YL+1;	   
	h0=(XH-XL)+1; 
	w1=90;
	h1=180;
	mheight=h1;
	mwidth=w1;
	fw=(float)(w0-1)/(w1-1);
	fh=(float)(h0-1)/(h1-1);
	size0=(w0)*(h0);
	size1=(w1)*(h1);
	ipDIBBITS=mymalloc(0,size0);
	pTemp=mymalloc(0,size1);
	
	datashow(6);
	for(i=XL;i<XH+1;i++)
	{
		for(j=YL;j<YH+1;j++)
		{	
			kk=(i-XL)*(w0)+(j-YL);
			ipDIBBITS[kk]=dis_sobel2[i][j];
		}
	}
	    
	
	for(i=0; i<h1;i++)
	{
		y0 = i*fh;
		y1=(int)(y0);
		if(y1 == h0-1) y2 = y1;
		else y2 = y1 + 1;
		fy1 = y1-y0; 
		fy2 = 1.0f - fy1;
		for(j=0; j<w1;j++)
		{
			x0 = j*fw;
			x1 = (int)(x0);
			if(x1 == w0-1)    
				x2 = x1;
			else
				x2 = x1+1;
			fx1=y1-y0;
			fx2=1.0f-fx1;
			s1 = fx1*fy1;
			s2 = fx2*fy1;
			s3 = fx2*fy2;
			s4 = fx1*fy2;
			rd=y1*(w0)+x1;
			ld=y2*(w0)+x1;
			ru=y2*(w0)+x2;
			lu=y1*(w0)+x2;
			pix=i*(w1)+j;
			pTemp[pix]=ipDIBBITS[ru]*s1+ipDIBBITS[lu]*s2+ipDIBBITS[rd]*s3+ipDIBBITS[ld]*s4; 
		}
	}
	
	
	for(i=0;i<h1;i++)
	{
		for(j=0;j<w1;j++)
		{	
			kk=(i)*(w1)+(j);
			dis_sobel2[i][j]=pTemp[kk];
		}
	}  
	myfree(0,ipDIBBITS);	
	myfree(0,pTemp);
	datashow(6);
}
void big2small(u8 x1,u16 y1)
{
	u16 i,j;
	u8 flag_1,flag_2,flag_3,flag_4,fp=1,count;
	vu8 m,n;
	u8 s[5][5];

	
	while(fp)
	{
		fp=0;	
		for(j=y1;j<mheight+y1;j++)
		{
			for(i=x1;i<mwidth+x1;i++)
			{
				dis_sobel1[j][i]=31;
			}
		}
		for(j=y1+2;j<mheight+y1-2;j++)
		{
			for(i=x1+2;i<mwidth+x1-2;i++)
			{
				flag_1=0;
				flag_2=0;
				flag_3=0;
				flag_4=0;
				if(31==dis_sobel2[j][i])
					continue;
				for(m=0;m<5;m++)
				{
					for(n=0;n<5;n++)
					{
						s[m][n]=(31-dis_sobel2[(j+m-2)][(i+n-2)])/31;//白色为0,黑色为1
					}
				}
				
				count=s[1][1]+s[1][2]+s[1][3]+s[2][1]+s[2][3]+s[3][1]+s[3][2]+s[3][3];
				if((count>=2)&&(count<=6))
					flag_1=1;
				count=0;
				if((0==s[1][2])&&(1==s[1][1]))
					count++;
				if((0==s[1][1])&&(1==s[2][1]))
					count++;
				if((0==s[2][1])&&(1==s[3][1]))
					count++;
				if((0==s[3][1])&&(1==s[3][2]))
					count++;
				if((0==s[3][2])&&(1==s[3][3]))
					count++;
				if((0==s[3][3])&&(1==s[2][3]))
					count++;
				if((0==s[2][3])&&(1==s[1][3]))
					count++;
				if((0==s[1][3])&&(1==s[1][2]))
					count++;
				if(1==count)
					flag_2=1;
				if(0==s[1][2]*s[2][1]*s[2][3])
					flag_3=1;
				else
				{
					count=0;
					if((0==s[0][2])&&(1==s[0][1]))
						count++;
					if((0==s[0][1])&&(1==s[1][1]))
						count++;
					if((0==s[1][1])&&(1==s[2][1]))
						count++;
					if((0==s[2][1])&&(1==s[2][2]))
						count++;
					if((0==s[2][2])&&(1==s[2][3]))
						count++;
					if((0==s[2][3])&&(1==s[1][3]))
						count++;
					if((0==s[1][3])&&(1==s[0][3]))
						count++;
					if((0==s[0][3])&&(1==s[0][2]))
						count++;
					if(1!=count)
						flag_3=1;					
				}
				
				if(0==s[1][2]*s[2][1]*s[3][2])
					flag_4=1;
				else
				{
					count=0;
					if((0==s[1][1])&&(1==s[1][0]))
						count++;
					if((0==s[1][0])&&(1==s[2][0]))
						count++;
					if((0==s[2][0])&&(1==s[3][0]))
						count++;
					if((0==s[3][0])&&(1==s[3][1]))
						count++;
					if((0==s[3][1])&&(1==s[3][2]))
						count++;
					if((0==s[3][2])&&(1==s[2][2]))
						count++;
					if((0==s[2][2])&&(1==s[1][2]))
						count++;
					if((0==s[1][2])&&(1==s[1][1]))
						count++;
					if(1!=count)
						flag_4=1;					
				}
				if(flag_1*flag_2*flag_3*flag_4)
				{
					dis_sobel1[j][i]=31;
					fp=1;
				}
				else
				{
					dis_sobel1[j][i]=0;
				}				
			}
		}
		for(j=y1;j<mheight+y1;j++)
		{
			for(i=x1;i<mwidth+x1;i++)
			{
				dis_sobel2[j][i]=dis_sobel1[j][i];
			}
		}
		/**********/
	}
	for(j=y1;j<mheight+y1;j++)
	{
		for(i=x1;i<mwidth+x1;i++)
		{
			dis_sobel2[j][i]=dis_sobel1[j][i];					
		}
	}
	/***********/
	datashow(6);

}
u8 charcter_zoen()
{
	u8 j,x;
	u16 i,kk,number,flag;
	u8 *ipDIBBITS=0,*pTemp;
	u8 error[10];
	ipDIBBITS=mymalloc(1,16200);
	pTemp=mymalloc(1,16200);

		for(i=0;i<180;i++)
	{
		for(j=0;j<90;j++)
		{	
			 kk=(i)*90+(j);
			 ipDIBBITS[kk]=dis_sobel2[i][j];
		}
	}

	for(i=1;i<11;i++)
	{
		W25QXX_Read(pTemp,0+16200*i,16200);	 //取数模班
		number=0;
		flag=0;
		for(kk=0;kk<16200;kk++)
		{
      if(ipDIBBITS[kk]==0)
			{
			   number++;
				if(pTemp[kk]==0)
				{
					flag++;
				}
			}
			error[i-1]=number-flag;
		}
	}

	for(i=0,number=0;i<10;i++)
	{
	  if(error[i]<error[number])
			number=i;
	}
	printf("%d\r\n",number);
	myfree(0,ipDIBBITS);	
	myfree(0,pTemp);
	return number;
}


电路原理图:

在这里插入图片描述
)

四、结论

  本设计采用STM32作为主控芯片,利用ov7670进行数字识别、将LCD1602作为显示屏,通过光的反射影响AD采样值不同这一原理完成循迹。在按键输入取货码后,识别数字,按照程序设定,小车到达指定取货位置,停留5秒进行取件并由ov7670摄像头进行扫描确认快递无误后,再同样的循迹原理按照原路返回。
本设计主要实现的功能有:
⑴ 通过ov7670完成图像的获取;
⑵ 通过程序及stm32实现数字识别;
⑶ 根据已识别的数字准确找到目标快件。
本设计通过分析快递运输中丢件、错分的现象,提出使用自动取货的方案,完成了准确取件、快速取件的工作,进行了具体的方案设计,并且进行了实际验证。通过完成系统功能设计、硬件电路设计、软件编写、检验系统运行的工作,得出了系统设计符合锂电池管理系统的要求以及验证了各项设计符合工程应用的结论。

目录

目 录
摘 要 I
Abstract II
引 言 3
1 控制系统设计 6
1.1系统方案 6
1.2 系统工作原理 6
1.2.1 系统的工作原理 6
1.2.2 系统的结构 7
2 硬件电路设计 9
2.1主控模块的选择 9
2.1.1 单片机及其选型介绍 8
2.1.2 复位电路的介绍 9
2.2 电机驱动模块 10
2.3 ov7670模块电路 10
2.4 电源模块电路 11
2.5 其他电路介绍 12
2.5.1 显示电路介绍 12
2.5.2 按键电路介绍 12
3 软件设计 13
3.1系统主程序设计 13
3.2 数字识别子程序设计 14
3.2.1 灰度处理 14
3.2.2 二值化 14
3.2.3 图像分割 15
3.2.4 识别 15
3.3 按键模块子程序设计 15
3.4 电机驱动子程序设计 16
3.5 LCD1602显示子程序设计 17
4仿真与调试 18
4.1 实物展示 18
4.2 实验效果 19
4.2.1 循迹过程 19
4.2.2 显示模块 19
结 论 20
附录1 硬件仿真图 21
附录2 源程序清单 22
参考文献 37
致 谢 39

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于STM32的捡球小车是一种利用STM32微控制器作为核心控制器的智能小车。通过编程控制,小车可以识别并捡起地面上的球。 小车的硬件主要包括STM32微控制器、电机驱动模块、传感器模块、舵机模块等。STM32微控制器作为整个系统的核心,可以实现各个模块之间的通信和数据处理。电机驱动模块可以控制小车的运动,使其前进、后退、左转、右转等。传感器模块可以使用光电传感器、红外传感器等,用于检测和识别地面上的球。舵机模块可以实现机械臂的运动,用于捡起和放下球。 在软件方面,我们可以利用STM32的开发工具进行编程,通过编写程序实现小车的各种功能。首先,我们需要编写程序来控制电机驱动模块,根据传感器的检测结果,使小车朝着球的方向运动。然后,我们需要编写程序来控制舵机模块,使机械臂能够准确地捡起和放下球。 在工作过程中,小车会不断地检测周围的球,并通过计算机视觉算法来判断球的位置和方向,然后根据计算结果进行相应的控制动作。当小车检测到球时,它会向球所在的位置移动,并使用机械臂捡起球。当球被捡起后,小车会将球放到指定的位置,然后继续巡线寻找下一个球。 基于STM32的捡球小车可以应用于各种场景,比如自动化仓储、娱乐等。通过不断的优化和改进,可以使小车在复杂的环境中准确地捡起球,并具有更高的智能化和自主性。 ### 回答2: 基于STM32的捡球小车是一种利用STM32单片机控制系统的智能小车,用于捡拾地上的球体。该小车由底盘、球体检测装置、驱动装置和STM32单片机组成。 首先,底盘是小车的基础部件,通常由电机、轮子等组成。电机可以通过STM32单片机的PWM信号来控制旋转速度和方向。轮子的转动则依靠电机的带动,使小车能够自由移动和转向。 其次,球体检测装置是捡球小车的核心部件。通常采用传感器配合STM32单片机进行球体的识别和定位。利用红外传感器、超声波传感器或摄像头等传感器,可实现对球体位置的检测和距离的测量。当球体被检测到时,STM32单片机会根据算法计算球体的坐标,并发出相应的指令。 驱动装置是控制小车运动的关键。STM32单片机通过控制电机转速和方向,使小车能够根据球体的位置快速移动,准确到达目标位置。在球体被捡起后,STM32单片机会停止电机驱动,保持小车静止。 最后,STM32单片机作为整个系统的控制中心,负责数据的处理和决策。通过编写程序,实现与底盘、球体检测装置和驱动装置之间的通信和协调。根据球体的位置信息,STM32单片机能够智能地计算最佳路线,以最短的时间捡起球体。 总的来说,基于STM32的捡球小车是一种智能化的机器人系统,通过STM32单片机的精确控制和算法处理,实现了对地上球体的准确定位和快速捡。这种小车能够在需要捡球的场景中发挥重要的作用,提高工作效率和精度。 ### 回答3: 基于STM32的捡球小车是一种智能化的机器人车辆,旨在帮助人们在体育场馆等场所自动捡拾球类物品。 这款小车的核心控制器采用STM32微控制器,它拥有强大的处理能力和丰富的外设接口,可以实现小车的各种功能。 小车的机械结构主要由车身、轮子和机械臂组成。车身由坚固的材料制成,可以承受一定的重量。轮子采用齿轮驱动,可灵活移动和转向。机械臂由舵机驱动,可根据需要抓和释放球类物品。 在控制方面,通过STM32微控制器与各种传感器进行连接和通信。小车配备了红外传感器和摄像头,用于识别和跟踪球类物品的位置。通过STM32的编程控制,小车可以自动寻找和捡起散落的球类物品,同时避免与其他物体碰撞。控制程序还可以根据需要调整机械臂的角度和力度,以确保稳定抓球类物品。 此外,小车的电源系统采用可充电的锂电池,并具有充电管理功能,可确保小车长时间工作。 基于STM32的捡球小车不仅可以在体育场馆中实现自动捡球的功能,还具有广泛的应用前景。例如,在工厂生产线上,它可以代替人工进行物料搬运;在仓库中,它可以协助仓库管理人员收集物品。 总而言之,基于STM32的捡球小车充分利用了STM32微控制器的强大功能和灵活性,实现了自动捡球的智能化功能,为人们的生活和工作提供了便利和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值