精华内容
下载资源
问答
  • STM32智能小车

    2018-03-15 20:25:25
    本资料可以用于许多初学者,可以很好的用于智能车测试,以及代码调试。
  • ST M32智能小车视频教程 ST M32 GPIO工作原理 基于慧净STM32智能小车讲解 目录 1 GPIO基本结构和工作方式 2 GPIO寄存器说明 3 STM32F10x GPIO引脚说明 GPIO基本结构 n 参考资料 p STM32F1xx官方资料 STM32 中文参考...
  • STM32智能小车视频教程
  • stm32智能小车程序

    2018-02-24 11:46:57
    stm32智能小车避障与2.4g无线遥控程序运用pwm控制四驱遥控手柄控制
  • STM32 智能小车源代码

    2018-07-19 17:51:07
    STM32智能小车的源代码分享,包括launch文件,src中含有激光slam的源文件,不需要编译,可以直接用
  • 电路CAD-STM32智能小车控制板设计.ppt
  • HL-1 STM32智能小车教程 传感器主板接线 ,看完后,可以自己安装一台32位智能小车。
  • STM32 智能小车底盘安装教程 ,看完后,可以自己安装一台32位智能小车
  • 基于stm32智能小车,已经实现功能:红外巡线,超声波避障,红外避障,HC05蓝牙遥控等。注释详细,对于新手是较好的电子设计入门项目。
  • STM32 开发板 烧写器安装课件 HL-1 STM32智能小车教程 烧写器驱动安装
  • STM32智能小车(广西科技大学2017毕业设计)功能:语音控制+蓝牙控制+自动寻迹
  • stm32智能小车之路之小车启动

    万次阅读 多人点赞 2014-10-20 23:33:00
    stm32智能小车之---小车启动

           首先,安装完小车后最激动的还是想让他跑动,那么就开始吧。写个简单的程序测试下电机是否正常。打开keil软件新建一个工程,具体简历keil工程不会的请百度,或者call我,我有简历Keil工程的文档,保证你会的。

          第一初始化管脚,来进行控制电机,输出高低电平,方可让电机转动。

    /*******************************************************************************
    * 函数名字  : GPIO_Configuration(void)
    * 描述      : 初始化PE7~PE8为输出口.并使能这两个口的时钟	
    							Motor(电机输出引脚) IO初始化
    * 输入      : 无
    * 输出      : 无
    * 返回值    : 无
    *******************************************************************************/
    void GPIO_Configuration(void)
    {
    	//PE.7~PE.8  小车后轮控制引脚
    	//PE.9!PE.10	风扇控制引脚
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);	                //使能PE端口时钟
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;	//Motor-->PE.7 ...  Motor-->PE.10 端口配置
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 			  	//推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 				//IO口速度为50MHz
    	GPIO_Init(GPIOE, &GPIO_InitStructure);					 				//根据设定参数初始化GPIOE
    	GPIO_ResetBits(GPIOE,GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10);					 				//PE.7.....PE10 输出低电平
    	
    }
    
    
            带代码中都做了详细的介绍,我就不过多的介绍了。不会的可以问我。主要是管脚的配置,都是直接调用的库 函数,这可比51简单多了,不用直接和寄存器打交道,直接和库函数交流就行,太方便了。

         主函数里面直接初始化下管脚就行:

        

    GPIO_Configuration(void);
    int main(void)
    {
       while(1);
    }

    ok!一切打工高成,用J-Link 或者通过串口下到核心板中去,连接上线,就ok了。

    关于连线问题,这个非常重要,我当初就是没有将线接对,导致高了半天,电机也不转,我用的电机驱动模块是L198N的。


    贴上电路原理图:


             相信大家都能看懂,不懂的看看模电、数电稍微懂点电路常识应该都懂吧。嘿嘿……

            可以看到小车跑的很快,速度应该很快的。不过不是我们想要的效果,下一篇介绍,怎样控制小车的速度……

    电机驱动模块注意不要接反了,容易烧坏,我就烧坏了一个大哭大哭

           上面接线的时候注意电机驱动模块使能端的跳线帽不要拿下来,否则不起作用,下一篇在调节小车速度的时候会将跳线帽拿下来,然后接根线进行控制速度,及PWM调速法。

          怎么样,不难吧……成功是属于那些勇于追逐。永不放弃的人的。加油……

           


    展开全文
  • stm32智能小车循迹

    2014-09-26 16:46:14
    基于stm32智能小车循迹,采用pid算法,通过pwm控制
  • Arduino/stm32 智能小车设计(一)

    千次阅读 2019-09-22 19:26:04
    Arduino/stm32 智能小车设计(一)智能小车原理图设计智能小车原理图组件包括:模块设计一、控制模块二、供电模块三、充电管理模块四、电机驱动模块五、红外寻迹及红外避障模块六、其它模块七、流水灯模块 智能小车...

    智能小车原理图设计

    智能小车原理图组件包括:

    1、处理器:我这里用的是Arduino UNO控制板;
    2、电机驱动芯片:L293DD贴片式封装;
    3、稳压芯片:AMS1117 5.0V;
    4、四路运放:LM324;
    5、两个红外对管和两个RPR220寻迹对管;
    6、四个50K 0932电位器分别对应四个红外对管,作为红外对管灵敏度调节;
    7、按键、LED、蓝牙模块PH2.45 4P排母座子、超声波模块PH2.45 4P排母座子、RGB指示灯;
    8、红外遥控器接收头:HS0038;
    9、充电模块:EUP8207充电芯片;
    以上所有器件淘宝都能买到。

    模块设计

    一、控制模块

    在这里插入图片描述
    功能:控制单元,编写代码对所有外设进行逻辑控制。
    这里用的Arduino UNO模块,为了方便用户理解,原理图上的IO口定义,严格按照UNO端口定义,如上图,我的智能小车把所有IO口占用完了。右下角为RGB模式指示灯。

    二、供电模块

    在这里插入图片描述
    功能:对所有外设及控制单元供电。
    这里采用AMS1117 5.0V稳压芯片,输出5.0V电压给外设及Arduino模块供电,K1为开关、U5为两节14500电池串联的电池盒。

    三、充电管理模块

    在这里插入图片描述
    功能:给电池充电。
    如图:X1:为适配器12V输入端口、采用EUP8207充电管理芯片输出2A电流给电池充电。

    四、电机驱动模块

    在这里插入图片描述
    功能:驱动两个电机正反转。
    如图所示,当IO口8输出高电平、5输出低电平时,J2电机电流从 2->1;
    当IO口8输出低电平、5输出高电平时,J2电机电流从 1->2;
    当两个IO口都给低电平是,电机停止运动。
    当然也可以对两个IO口进行PWM控制,实现电机调速功能。对J1的控制方法与J2一样。

    五、红外寻迹及红外避障模块

    在这里插入图片描述
    功能:实现红外避障和黑线寻迹的功能。
    如图所示,小车采用四路运放LM324正好对应四个红外对管,先看R16、D24 是左避障红外对管和灵敏度调节器。当旋转R16时,IN1+端口电压随之改变,IN1-端口电压由红外接收管探测到红外线光强而变。
    对比INI+、IN1-两个端口的电压、当IN1+ > IN1-是OUT1输出高,否则输出低电平(输出低电平时,D30亮灯,方便用户调试),通过控制单元采集A5的高/低电平,判断小车左边是否有障碍物。右避障同理!
    寻迹RPR220原理,如果探测到黑线或者白纸,接收管接收到的红外线光强变化,从而引起运放IN4-电压变化,电位器电压变化通过旋转0932电位器调节,从而实现灵敏度调节。

    六、其它模块

    在这里插入图片描述
    如图、蜂鸣器、按键、蓝牙、超声波、HS0038红外遥控接收头、RGB指示灯在前面已经有了。
    超声波和蓝牙模块只需要一个PH2.54 4P排母座子即可,相关模块可以从淘宝购买。
    相关原理,在以后代码讲解时,进行叙述!!!

    七、流水灯模块

    在这里插入图片描述
    功能:小车外围装饰灯。
    这部分功能相对简单,采用淘宝定制流水灯芯片,当IO口13给低电平时,LED灯实现流水灯效果。

    到此为止、所有原理图奉上。
    转载请标明出处,谢谢!!
    Arduino/stm32智能小车群:916385027
    如果找不到群:可加QQ:971312944

    展开全文
  • 智能小车STM32原理图
  • STM32智能小车(广西科技大学2017毕业设计)(注意:52积分下载)
  • stm32智能小车的代码

    2018-04-20 16:44:30
    智能小车的基本全部分代码,超声波避障,红外线控制
  • stm32智能小车设计

    千次阅读 多人点赞 2019-07-31 20:27:52
    自己在32的学习中还不够仔细深入,只是浅面的学习,当真正做一个项目时,暴露的问题就太多了。这次在小车的制作的过程中,遇到了各种各样的问题,软件,硬件,各式各样的问题迎面而来,真的好几次心态崩了。不过还好...

    提前说说

    博主是用寄存器写的驱动

    历时两周,总算把小车弄好了,总体上来说做的太慢了。自己在32的学习中还不够仔细深入,只是浅面的学习,当真正做一个项目时,暴露的问题就太多了。这次在小车的制作的过程中,遇到了各种各样的问题,软件,硬件,各式各样的问题迎面而来,真的好几次心态崩了。不过还好小车这个项目不只是我一个人在搞,组里的其他成员也在一直在考虑问题,想办法,不断地解决解决,总归小车终于做好了,下面是小车完成图:

    在这里插入图片描述
    在这里插入图片描述
    是有点灵魂接线(·<·)。

    模块清单:

    1.stm32f103C8T6开发板
    2.HC-SR04超声波测距模块X3
    3.TB6612FNG 电机驱动模块X2
    4.HC-05主从一体无线蓝牙模块X1
    5.智能小车底盘 4WD小车循迹/避障小车 底盘X1
    6.LM2596S DC-DC降压电源模块X1
    7.电源模块3.3V 5V 12V多路输出 电压转换模块DC-DC 12V转3.3V 5V X1
    8.12V电池X1
    9.杜邦线 Xn
    10.转串口模块X1
    11.ST-linkX1
    12.面包板X1

    完成功能:1.超声波避障 2.蓝牙控制 3.走矩形

    各个模块就不再介绍了,具体介绍大家可以自行百度或者看一下我的前几篇Arduino智能小车博客,里面有简单的介绍。

    小车的所有详细代码和成品演示在我的资源中,大家可以下载提取(包括代码,引脚图,效果演示):https://download.csdn.net/download/nidie508/11458242

    那么,开始吧。

    准备工作:

    1.首先配置好keil5 c8t6模板(温馨提示:多看看模板的核心驱动,包括sys.h delay.h usart.h等,这些核心文件一定要保证准确无误!)
    2.了解开发板和确保开发板无误
    3.熟悉怎么用转串口模块和st-link将驱动下载到开发板上
    下图示为c8t6开发板的引脚图
    在这里插入图片描述

    1.超声波避障功能

    我们设计的思路如下,用三个超声波来避障。为什么用三个超声波呢?我们想的是如果用舵机的话,小车在行进过程中并不好判断,只能将车停下,舵机转动来检测哪个方向无障碍物,而用3个超声波不仅可以在行进中判断,也可以让小车没有停下的动作,显得整个过程比较流畅。这就是我们使用三个超声波的原因了。

    我们使用的是定时器二的通道一,通道二,通道三来进行输入捕获的,那么,第一个问题就来了。

    我们在写超声波代码时,用一个超声波先测试,发现超声波测试的并没有问题 ,串口显示的数据也并没有问题。但是,但是,在用三个超声波同时测试是,却发现数据显示的总有问题,输出的数据总是毫无规律,且数字都非常大,我们就在想是什么问题。
    下面是三个超声波控制的代码:

    //main.c
    #include "sys.h"
    #include "usart.h"		
    #include "delay.h"	
    #include "led.h"  
    #include "dianji.h"
    #include "hcsr.h"
    u32 DIS_Init(u8 STA,u16 VAL)
    {
    		u32 temp;
    		u32 lenth;
    	  if((*STA)&0X80)//成功捕获到了一次高电平
        {
            temp=STA&0X3F;
            temp*=65536;               //溢出时间总和
            temp+=VAL; //得到总的高电平时间
            lenth=temp*0.017;           //计算长度
            STA=0;     //开启下一次捕获
        }
    		return lenth;
    }
    
    extern u8 TIM2CH2_CAPTURE_STA; //输入捕获状态
    extern u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值
    
    extern u8 TIM2CH3_CAPTURE_STA; //输入捕获状态
    extern u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值
    
    extern u8 TIM2CH4_CAPTURE_STA; //输入捕获状态
    extern u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值
    
    int main(void)
    {		
    	u32 temp=0;
      u32 length1;
    	u32 length2;
    	u32 length3; 	
    	Stm32_Clock_Init(9); //系统时钟设置
    	delay_init(72);	     //延时初始化
    	uart_init(72,9600);  //串口初始化 	  	 //初始化与LED连接的硬件接口
    	TIM_PWM1_Init();//10000-1,36-1);//不分频。PWM频率=72M/(0.036M)=2Khz
    	Echo1=0;
    	Echo2=0;
    	Echo3=0;
    	HCSR04_Init(0XFFFF,72-1);//以1Mhz的频率计数
    	/*while(1)
    	{
    		
    	}*/
    	while(1)
    	{
    		Echo3=1;
    		delay_us(20);
    		Echo3=0;
    		length1=DIS_Init(&TIM2CH4_CAPTURE_STA,TIM2CH4_CAPTURE_VAL);
    		delay_ms(1000);
    		Echo1=1;
    		delay_us(20);
    		Echo1=0;
    		length2=DIS_Init(&TIM2CH2_CAPTURE_STA,TIM2CH2_CAPTURE_VAL);
    		delay_ms(1000);
    		Echo2=1;
    		delay_us(20);
    		Echo2=0;
    		length3=DIS_Init(&TIM2CH3_CAPTURE_STA,TIM2CH3_CAPTURE_VAL);
    		printf("%d %d %d\r\n",length1,length2,length3);
    	//	GO();
    		delay_ms(500);
    	}
    }
    
    hcsr.c
    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "hcsr.h"
    void HCSR04_Init(u16 arr,u16 psc)
    {
        RCC->APB1ENR|=1<<0;    //TIM2时钟使能
        RCC->APB2ENR|=1<<2;    //使能PORTA时钟
    		RCC->APB2ENR|=1<<3;		 //使能PORTB时钟
        GPIOA->CRL&=0XFFFF000F;//PA1 清除之前设置
        GPIOA->CRL|=0X00008880;//PA1输入
    //		GPIOA->ODR|=0<<0;
        GPIOA->ODR|=0<<1;      //PA1下拉
    		GPIOA->ODR|=0<<2;
    		GPIOA->ODR|=0<<3;
    	
        GPIOB->CRL&=0X000FFFFF;//PB7清除之前设置
        GPIOB->CRL|=0X33300000;//PB7推挽输出
        GPIOB->ODR|=1<<7;      //PB7 输出高
    		GPIOB->ODR|=1<<6;
    		GPIOB->ODR|=1<<5;
    	
        TIM2->ARR=arr;         //设定计数器自动重装值
        TIM2->PSC=psc;         //预分频器
    	
        TIM2->CCMR1|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
        TIM2->CCMR1|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR1|=0<<10;    //IC2PS=00 配置输入分频,不分频
    	
        TIM2->CCER|=0<<5;      //CC2P=0 上升沿捕获
        TIM2->CCER|=1<<4;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
    		
    		TIM2->CCMR2|=1<<0;     //CC2S=01 选择输入端IC1映射到TI1
        TIM2->CCMR2|=1<<4;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR2|=0<<2;    //IC2PS=00 配置输入分频,不分频
    	
        TIM2->CCER|=0<<9;      //CC2P=0 上升沿捕获
        TIM2->CCER|=1<<8;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
    		
    		TIM2->CCMR2|=1<<8;     //CC2S=01 选择输入端IC1映射到TI1
        TIM2->CCMR2|=1<<12;     //IC2F=0001 配置滤波器 以Fck_int采样,两个事件后有效
        TIM2->CCMR2|=0<<10;    //IC2PS=00 配置输入分频,不分频
    	
        TIM2->CCER|=0<<13;      //CC2P=0 上升沿捕获
        TIM2->CCER|=1<<12;      //CC2E=1 允许捕获计数器的值到捕获寄存器中
    		
        TIM2->DIER|=1<<2;      //允许捕获中断
    		TIM2->DIER|=1<<3;      //允许捕获中断
    		TIM2->DIER|=1<<4;      //允许捕获中断
        TIM2->DIER|=1<<0;      //允许更新中断
        //TIM2->CR1|=0X01;       //使能定时器2
        MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2
    }
    
    u8 TIM2CH1_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH1_CAPTURE_VAL;  //输入捕获值
    
    u8 TIM2CH2_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH2_CAPTURE_VAL;  //输入捕获值
    
    u8 TIM2CH3_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH3_CAPTURE_VAL;  //输入捕获值
    
    u8 TIM2CH4_CAPTURE_STA=0; //输入捕获状态
    u16 TIM2CH4_CAPTURE_VAL;  //输入捕获值
    
    //定时器2中断服务程序
    void TIM2_IRQHandler(void)
    {
        u16 tsr;
        tsr=TIM2->SR;
    	
    		if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH4_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH4_CAPTURE_STA++;
                }
            }
            if(tsr&0x10)//捕获1发生捕获事件
            {
                if(TIM2CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH4_CAPTURE_VAL=TIM2->CCR4;//获取当前的捕获值
                    TIM2->CCER&=~(1<<13);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH4_CAPTURE_VAL=0;
                    TIM2CH4_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;             //计数器清空
    					//		TIM2CH4_CAPTURE_VAL=TIM2->CCR4;
                    TIM2->CCER|=1<<13;        //CC1P=1 设置为下降沿捕获
    							TIM2->CR1|=0x01;
                }
            }
        }
        if((TIM2CH2_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH2_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH2_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH2_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH2_CAPTURE_STA++;
                }
            }
            if(tsr&0x04)//捕获1发生捕获事件
            {
                if(TIM2CH2_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH2_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH2_CAPTURE_VAL=TIM2->CCR2;//获取当前的捕获值
                    TIM2->CCER&=~(1<<5);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH2_CAPTURE_VAL=0;
                    TIM2CH2_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;             //计数器清空
                    TIM2->CCER|=1<<5;        //CC1P=1 设置为下降沿捕获
    							TIM2->CR1|=0x01;
                }
            }
        }
    		
    		if((TIM2CH3_CAPTURE_STA&0X80)==0)//还未成功捕获
        {
            if(tsr&0X01)//溢出
            {
                if(TIM2CH3_CAPTURE_STA&0X40)//已经捕获到高电平了
                {
                    if((TIM2CH3_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
                    {
                        TIM2CH3_CAPTURE_STA|=0X80;//标记成功捕获了一次
                        TIM2CH3_CAPTURE_VAL=0XFFFF;
                    }else TIM2CH3_CAPTURE_STA++;
                }
            }
            if(tsr&0x08)//捕获1发生捕获事件
            {
                if(TIM2CH3_CAPTURE_STA&0X40) //捕获到一个下降沿
                {
                    TIM2CH3_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
                    TIM2CH3_CAPTURE_VAL=TIM2->CCR3;//获取当前的捕获值
                    TIM2->CCER&=~(1<<9);    //CC1P=0 设置为上升沿捕获
                }else                       //还未开始,第一次捕获上升沿
                {
                    TIM2CH3_CAPTURE_VAL=0;
                    TIM2CH3_CAPTURE_STA=0X40; //标记捕获到了上升沿
                    TIM2->CNT=0;  
    						//		TIM2CH3_CAPTURE_VAL=TIM2->CCR3;							//计数器清空
                    TIM2->CCER|=1<<9;        //CC1P=1 设置为下降沿捕获
    							TIM2->CR1|=0x01;
                }
            }
    	}
    		
    				
        TIM2->SR=0;//清除中断标志位
    		
    }
    
    hcsr.h
    #ifndef __HSCR04_H
    #define __HSCR04_H
    #include "sys.h"
    
    #define Echo1 PBout(7) // PB7
    #define Echo2 PBout(6) // PB7
    #define Echo3 PBout(5) // PB7
    
    void HCSR04_Init(u16 arr,u16 psc);
    
    #endif
    
    

    最后发现,输入捕获代码中,中断服务函数中,TIM2->CNT不能清零,因为初始化中,用的是同一个定时器的通道2,3,4。如果每一次中断函数的某个通道函数将TIM2->CNT清0,那么其他通道的记录的TIM2->CNT的值就发生变化,从而导致了各种各样的情况。

    问题二就是从串口读取数据,当时挺崩溃的。首先是keil5模板问题,当时串口怎么都显示不出来数据,我们当时都很疑惑。一直反复的看代码,考虑各种情况,但还是显示不出来数据。一开始我们以为是超声波接受的反馈的数据不满足某个条件,所以没有显示。到后面查来查去,又在想是开发板并没有给电压?超声波集体歇B?最终发现,usart.c文件写的串口不是我们接线串口所对应的。当时心态挺炸的,改了之后终于可以测试数据了。

    问题三是我们在没接电机驱动之前,超声波接收的数据无论准不准确,最起码能接收到,可是接了电机驱动却发现每次返回的值都是0。我们当时并没有找到原因,又在猜想是不是电机用到的定时器对超声波的定时器有影响?又在想是不是外部电子设备把信号影响了?又在想各种各样的问题?

    最终解决的方法是,串口模块给的电压不够。。。(我也不知道这样形容的对不对,但感觉就是)。为什么这样说呢?当时一开始我想的是,超声波的模块在用转串口模块给其供电时,是不是超声波模块的VCC和GND引脚并没有电压,从而导致信号发射不出去。于是我用万用表测试两侧电压,发现是5V没错。又在想是不是发出信号并没有发去,于是我让TRIG引脚一直为1,测试TRIG电压发现为2.6v左右。在此之后,我又用12v的电池降压给开发板供电,发现TRIG电压为3.3V左右。我想验证,是不是电压问题而导致的接收数据为零。所以我想用电池给开发板供电,然后打开串口监视器看数据。但是要想启用串口监视器,必须要用串口给开发板供电。最后我们选用了蓝牙模块,从手机的接收器来观察数据。终于,果然是电压的问题,数据成功出现了!!!(哭了)

    2.用PWM调控电机速度

    这一过程能稍微简单一些,就是一开始还是电压的问题,四个轮子根本带不起来。反复查看代码后并没有太多问题,可是轮子还是不转,但是发现电机嗡嗡响,去掉一个电机后,将速度调大,发现两个轮子缓缓的动了。验证时,我们将轮子速度调小,发现轮子不转,证明了代码并无问题。

    pwm控制部分代码:

    #include "dianji.h"
    #include "sys.h"
    #include "delay.h"
    
    void TIM_PWM1_Init(u16 arr,u16 psc)
    {		 					 
    	//此部分需手动修改IO口设置
    	RCC->APB1ENR|=1<<1; 	//TIM3时钟使能    
    	RCC->APB2ENR|=1<<2;		//GPIOA使能
    	RCC->APB2ENR|=1<<3;   //GPIOB使能
    	RCC->APB2ENR|=1<<4;
    	GPIOA->CRL&=0X00FFFFFF;	//PA(7)PA(6)做复用,PA(3)是BIN1 PA(4)BIN2 PA(5)STBY
    	GPIOA->CRL|=0XBB000000;
    	//GPIOA->ODR|=1<<7;
    	//GPIOA->ODR|=1<<6;
    	GPIOC->CRH&=0X000FFFFF;
    	GPIOC->CRH|=0X33300000;
    	GPIOB->CRL&=0XFFFFF000; //PB(0)是AIN1 PB(1)是AIN2
    	GPIOB->CRL|=0X00000333;
    	TIM3->ARR=arr;			//设定计数器3自动重装值 
    	TIM3->PSC=psc;			//预分频器设置
      
    	TIM3->CCMR1|=6<<4;  	//CH1 PWM2模式		 
    	TIM3->CCMR1|=1<<3; 		//CH1预装载使能	 
    	TIM3->CCMR1|=6<<12;  	//CH2 PWM2模式		 
    	TIM3->CCMR1|=1<<11; 		//CH2预装载使能	
    	
     	TIM3->CCER|=1<<0;   	//OC1 输出使能
    	TIM3->CCER|=1<<4;   	//OC1 输出使能	
    //	TIM3->BDTR|=1<<15;   	//MOE 主输出使能	   
    
    	TIM3->CR1=0x0080;   	//ARPE使能 
    	TIM3->CR1|=0x01;    	//使能定时器3 
    
    	RCC->APB2ENR|=1<<11; //TIM1定时器使能
    	GPIOA->CRH&=0XFFFF0FF0;
    	GPIOA->CRH|=0X0000B00B;
    	//GPIOA->ODR|=1<<8;
    	//GPIOA->ODR|=1<<11;
    	
    	GPIOB->CRH&=0X0000FFFF;
    	GPIOB->CRH|=0X33330000;
    	
    	TIM1->ARR=arr;			//设定计数器自动重装值 
    	TIM1->PSC=psc;			//预分频器设置
    	
    	TIM1->CCMR1|=6<<4;  	//CH1 PWM2模式		 
    	TIM1->CCMR1|=1<<3; 		//CH1预装载使能	 
    	TIM1->CCMR2|=6<<12;  	//CH4 PWM2模式		 
    	TIM1->CCMR2|=1<<11; 		//CH4预装载使能	
    	
    	TIM1->CCER|=1<<0;   	//OC1 输出使能
    	TIM1->CCER|=1<<12;   	//OC4 输出使能	
    	TIM1->BDTR|=1<<15;   	//MOE 主输出使能	   
    
    	TIM1->CR1=0x0080;   	//ARPE使能 
    	TIM1->CR1|=0x01;    	//使能定时器1 
    	
    	STBY=1;
    	STBY1=1;
    }
    
    void GO(u16 a,u16 b)
    {
    	AIN1=0;     //AIN1,BIN1,AIN2,BIN2控制轮子方向
    	AIN2=1;
    	BIN1=0;
    	BIN2=1;
    	AIN3=1;
    	AIN4=0;
    	BIN3=1;
    	BIN4=0;	
    	
    	TIM3->CCR1=a;//右上,控制速度
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    	//delay_ms(2000);
    }
    
    void STOP(void)
    {
    	AIN1=0;
    	AIN2=0;
    	BIN1=0;
    	BIN2=0;
    	AIN3=0;
    	AIN4=0;
    	BIN3=0;
    	BIN4=0;	
    }
    
    void BACK(u16 a,u16 b)
    {
    	AIN1=1;
    	AIN2=0;
    	BIN1=1;
    	BIN2=0;
    	AIN3=0;
    	AIN4=1;
    	BIN3=0;
    	BIN4=1;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    //	delay_ms(1000);
    }
    
    void RIGHT(u16 a,u16 b)
    {
    	AIN1=1;
    	AIN2=0;
    	BIN1=0;
    	BIN2=1;
    	AIN3=0;
    	AIN4=1;
    	BIN3=1;
    	BIN4=0;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    //	delay_ms(1000);
    }
    
    void LEFT(u16 a,u16 b)
    {
    	AIN1=0;
    	AIN2=1;
    	BIN1=1;
    	BIN2=0;
    	AIN3=1;
    	AIN4=0;
    	BIN3=0;
    	BIN4=1;	
    	
    	TIM3->CCR1=a;//右上
    	TIM3->CCR2=b;//左上
    	TIM1->CCR1=a;//右下
    	TIM1->CCR4=b;//左下
    //	delay_ms(1000);
    }
    

    3.蓝牙控制

    蓝牙控制这一内容是小伙伴写的,大概内容和串口一章内容相似,就是多做出了判断,即没通过蓝牙输入数据来改变小车此时的模式,在蓝牙控制模式下,也可以相对应用蓝牙控制小车的方向。我们用的仍是串口一来控制蓝牙,为什么这样做?一是方便,二是就如前面所说,电机和超声波的分压严重,在电脑上上的串口监视器得出的数据并不准确,所以还不如用蓝牙来看数据,于是我们直接用了串口一来和蓝牙连接。初始化问题并不需要要修改,直接调用uart()函数即可,在中断控制代码下加入接收数据而触发的各种就好了。

    蓝牙控制部分代码:

    void USART1_IRQHandler(void)
    {
    	char res;	
    	if(USART1->SR&(1<<5))
    	{		
    		res=USART1->DR;
    		printf("\r\n%d",res);		
    		if(res==50)                                              //输入2为前进
    		{	
    			GO(300,300);
    			printf("\r\nGo Stright");
    		}
    		else if(res==56)										   //输入8为后退
    		{
    			BACK(300,300);
    			printf("\r\nGo Back");
    		}
    		else if(res== 52)								//输入4为左转
    		{
    			LEFT(300,300);
    			printf("\r\nTurn Left");			
    		}
    		else if(res==54)								//输入6为右转
    		{
    			RIGHT(300,300);
    			printf("\r\nTurn Right");
    		}
    		else if(res==53)								//输入5为停止
    		{
    			STOP();
    			printf("\r\nStop");
    		}
    		else if(res=='9')								//进入超声波避障模式
    		{
    			opq=0;
    		}
    	}
    } 
    

    总的来说蓝牙控制这块并没有踩多少坑(大概这不是我写的吧^ _ ^,感谢小伙伴)

    3.走矩形

    走矩形功能也是小伙伴写的,设计思路大致是通过蓝牙输入长和宽,小车通过接受的数据进行矩形运动。在这唯一遇到的问题就是小车的速度问题和转向时间。这个是他们弄得,自我感觉还是很不好调的,因为要考虑电池可供电压,小车行驶的惯性,不同地面的摩擦程度等等。考虑的方面比较多,根据不同的情况可能还要修改小车的速度和转向时间。我们就是在光滑地砖上测得,摩擦力应该是比较小的。

    走矩形代码:

    void Juxing()//小车的矩形运动函数
    {
    	u8 chang,kuan,x,y;//chang、kuan分别是小车要走矩形的长和宽的值
    	delay_ms(200);
    	printf("Chang:\r\n");
    	while(1)
    	{
    		printf("Input Chang:\r\n");
    		delay_ms(200);
    		if(USART1->SR&(1<<5))//当串口接收到消息后跳出循环
    		{
    			chang=USART1->DR-'0';//将字符型的数据转换为整型数据
    			break;
    		} 
    	}
    	printf("长:%d\r\n",chang);//打印串口接收到的数据
    	USART1->SR=0;//串口的接收标志位清零,为下一次接收宽度数据做准备
    	while(1)
    	{
    		printf("Input Kuan:\r\n");
    		delay_ms(200);
    		if(USART1->SR&(1<<5))
    		{
    			kuan=USART1->DR-'0';//当串口接收到数据后跳出循环
    			break;
    		}
    	}
    	printf("宽:%d\r\n",kuan);//打印宽度数据
    	//当前小车速度为0.25米每秒则小车每走1cm要用40ms所以以1cm为单位每走1cm耗时40ms用for函数驱动小车运动
    	for(x=0;x<chang*10;x++)//直走长
    	{
    		GO(300,300);
    		delay_ms(40);
    	}
    	RIGHT(300,300);//右拐
    	delay_ms(785);
    	for(y=0;y<kuan*10;y++)//直走宽
    	{
    		GO(300,300);
    		delay_ms(40);
    	}
    	RIGHT(300,300);//右拐
    	delay_ms(785);
    	for(x=0;x<chang*10;x++)//直走长
    	{
    		GO(300,300);
    		delay_ms(40);
    	}
    	RIGHT(300,300);//右拐
    	delay_ms(785);
    	for(y=0;y<kuan*10;y++)//直走宽
    	{
    		GO(300,300);
    		delay_ms(40);
    	}
    	RIGHT(300,300);//右拐
    	delay_ms(785);
    	STOP();
    
    

    我的想法:

    1.自己所学的东西并没有所有吸收,有些东西可能单个实验看着并不重要,一旦做项目了,有些东西起着至关重要的作用。比如,delay_ms()函数,当时我写的一句代码是delay_ms(2000),本想着意思是延迟2s,但是代码并不可行,因为delay_ms()函数设定的参数是小于1864,而2000显然已经超过了这个范围,在串口监视器显示的速度是不准确的。这里就是一个很细微的东西,但是自己并不知道,导致了一系列的错误。

    2.和Arduino板子不同的是,不,应该说库函数和寄存器的区别其实还挺大的。起初在学32时,我觉得库函数和寄存器其实没多大的区别,感觉两者都不是和复杂,唯一的就是一些初始化函数,库函数可以直接调用而寄存器你得自己配置,反而成为一个很繁琐的过程。但是小车项目的整个过程彻底改变了我的想法,首先就是四个输入捕获通道问题,我不清楚库函数有没有,但是用寄存器配置时,我真的学的了一些东西。这些东邪可能不只是知识层面上的,更多的是一个训练总体观的过程,即要考虑任何东西。我相信如果只是调用那些已经封装好的函数,可能你应该思考的东西人家已经帮你弄好了,错失了关键点。

    3.全面的考虑所有问题。学嵌入式可能和纯软不同,它既要考虑软件代码,又要考虑硬件搭建和硬件的可用,这是一个挺繁琐的过程。在做小车时,真正体会到了这点,从软件一步步排除,再到硬件逐个逐个测电压,一直在排除排除找的真真的解决方法。突然想起几个月前,实验室面试时,我问学长在测试过程中你们应该如何解决问题,他说第一方向是确保软件无误后,接下来开始看硬件。现在我觉得,我能体会到一点了。一定要先排查出软件,接下来入手硬件。

    4.沟通与合作。真的随着年龄的增长,自己感觉自己变化挺大的。还记得初中时那种盛气凌人的状态,现在想想真的是井底之蛙那时候得我。现在我有了自己的队友,在遇到问题时,可以相互交流,相互讨论,考虑问题更加全面,学到的东西也更多,弥补自己的短处(感觉真的好讽刺啊,小学就在写,直到大学才真正明白。。。)而且最重要的一点是,我能慢慢听的进去和听懂他人的想法(意思)了,在高中时,一直都在想和那些逻辑思维强的人差距在哪儿,现在我觉得不仅是天赋,强理解力也是非常重要的一点。

    5.保持良好的心态。中间有两天,心态真的炸了,小车进度一直被卡,shilian,感觉自己好废物。我还是没有做到,做事认真,乐观,这个我还得好好锻炼吧,以后还有很多的事,这就是冰山一角。
    6.我错了,小淳。我还是太任性了,对不起,我很想你。

    展开全文
  • 基于STM32智能小车.zip

    2020-06-29 13:47:18
    也该写点什么来回馈给大家了前不久接触了单片机,想提前进行实践一下所以有想法做一个实体出来,想来想去难的怕自己搞不定,但是还好找到了志同道合的王同学,一起搞一个智能小车.新手上路,多多指教
  • stm32智能小车资料.zip

    2020-03-14 22:32:07
    买回来的智能小车学习实验,里面红外循迹,超声波避障,蓝牙(好像有),和其它一些控制的部分有分开的源码,方便独立学习,分享给大家,最近比较忙,QQ就不留了。。。
  • Arduino/stm32 智能小车设计(二) 本节进行Arduino智能小车的代码讲解。 一、I/O口定义与初始化函数 如下图RGB指示灯用到10、11、12三个I/O口,分别对应蓝色、红色、绿色。当给对应的I/O口低电平时,对应颜色的灯亮...

    Arduino/stm32 智能小车设计(二)

    本节进行Arduino智能小车的代码讲解。

    一、I/O口定义与初始化函数

    如下图RGB指示灯用到10、11、12三个I/O口,分别对应蓝色、红色、绿色。当给对应的I/O口低电平时,对应颜色的灯亮。也可以用PWM进行调色,实现不同的颜色。这里先把控制端的原理图粘贴上来以便后面原理说明。
    在这里插入图片描述
    Arduino封装了很多底层的细节,使得学习者不需要太多的关注底层电路的原理。
    Arduino一共有14个数字I/O口,分别为0-13,定义与初始化看代码;6个模拟I/O口,分别为A0-A5,定义与初始化看代码。
    已下是所有I/O端口定义:

    //0:TDX蓝牙  	1:RXD蓝牙  		2:DATA红外遥控
    //3:蜂鸣器   	4:按键     		5:IN2左电机  
    //6:IN3右电机 	7:IN4右电机     8:IN1左电机 
    //9:悬空      	10:RGB_B     	11:RGB_R
    //12:RGB_G     				13:流水灯
    //A0:Echo超声波回声脚       		A1:Trig超声波触发脚  
    //A2:左循迹输入   			    A3:右循迹输入
    //A4:右壁障输入   				A5:左壁障输入
    
    //I/O口 0、1 是Arduino唯一的一组串口通信口(代码里无需定义)。用于蓝牙数据的接发,具体串口通信的知识可以看我的另外一篇博客了解。链接:
    https://blog.csdn.net/weixin_43729724/article/details/101287363
    //数字端口定义
    int DATA= 2;		//红外数据输入端口
    int BEEP=3;        	//蜂鸣器输出 
    int KEY=4;         	//按键输入  
    int IN2=5;          //左电机
    int IN3=6;          //右电机 
    int IN4=7;         	//右电机
    int IN1=8;        	//左电机
             			//9脚悬空,不需要定义
    int RGB_B=10;       //RGB蓝色 
    int RGB_R=11;		//RDB红色
    int RGB_G=12;  		//RGB绿色     
    int Water_L=13;     //流水灯I/O
    //模拟I/O口定义
    int Trig =A0;  			//Trig 触发脚输出
    int Echo = A1;  		//Echo回声脚输入
    int XunJi_R = A3;     	//右寻迹输入
    int XunJi_L = A2;     	//左寻迹输入
    int BiZhang_R = A4;   	//右红外避障输入
    int BiZhang_L = A5;     //左红外避障输入
    
    /************************************************************************
      * @描述:  Arduino初始化函数
      * @参数:  None
      * 功能:	定义I/O口模式,并赋初值
      * @返回值: None
    **********************************************************************/
    void setup()
    {
    	  Serial.begin(9600);	//波特率9600 (蓝牙通讯设定波特率)
    	  pinMode(DATA,INPUT);
    	  pinMode(BEEP,OUTPUT); 
    	  pinMode(KEY,INPUT); 
    	  pinMode(IN2,OUTPUT);
    	  pinMode(IN3,OUTPUT);
    	  pinMode(IN4,OUTPUT);
    	  pinMode(IN1,OUTPUT);  
    	  pinMode(RGB_B,OUTPUT);
    	  pinMode(RGB_R,UTPUT); 
    	  pinMode(RGB_G,UTPUT); 
    	  pinMode(Water_L,OUTPUT);
    	  pinMode(Trig,OUTPUT); 
    	  pinMode(Echo,INPUT);
    	  pinMode(XunJi_R,INPUT);
    	  pinMode(XunJi_L,INPUT);
    	  pinMode(BiZhang_R,INPUT);
    	  pinMode(BiZhang_L,INPUT);
    	  
    	  digitalWrite(BEEP,LOW);  
    	  digitalWrite(RGB_B,HIGH);
    	  digitalWrite(RGB_R,HIGH); 
    	  digitalWrite(RGB_G,HIGH); 
    	  digitalWrite(Water_L,HIGH);
    }
    

    二、前进、后退、左转、右转、左旋转、右旋转API函数

    原理图如下:在这里插入图片描述
    电机驱动原理:L293DD是一款专用的电机驱动芯片,因为I/O口驱动电流受限,而电机运转需要高电流驱动。当8高5低时,电流从OUT1->OUT2驱动做电机正转,反之亦凡。I/O口6、7驱动右电机运动。
    代码如下:

    /************************************************************************
      * @描述:  
      * @参数:  speed:控制速度0-255
      * 功能:	小车前进
      * @返回值: None
    **********************************************************************/
    void run(int speed) 
    {
      analogWrite(IN1,speed);//PWM比例0~255调速,左右轮差异略增减
      digitalWrite(IN2,LOW);
      analogWrite(IN4,speed);//PWM比例0~255调速,左右轮差异略增减
      digitalWrite(IN3,LOW); 
    }
    /************************************************************************
      * @描述:  
      * @参数:  None
      * 功能:	刹车
      * @返回值: None
    **********************************************************************/
    void brake() 
    {
      digitalWrite(IN1,LOW);
      digitalWrite(IN2,LOW);
      digitalWrite(IN3,LOW);
      digitalWrite(IN4,LOW);
    }
    /************************************************************************
      * @描述:  左转(左轮不动,右轮前进)
      * @参数:  speed:控制速度0-255
      * 功能:	小车左转
      * @返回值: None
    **********************************************************************/
    void left(int speed)
    {
      digitalWrite(IN1,LOW);
      digitalWrite(IN2,LOW);
      analogWrite(IN4,speed);//PWM比例0~255调速,右轮前进
      digitalWrite(IN3,LOW); 
    }
    /************************************************************************
      * @描述:  左旋转(左轮后退,右轮前进)
      * @参数:  speed:控制速度0-255
      * 功能:	小车左旋转
      * @返回值: None
    **********************************************************************/
    void spin_left(int speed) 
    {
      digitalWrite(IN1,LOW);
      analogWrite(IN2,speed);
      analogWrite(IN4,speed);
      digitalWrite(IN3,LOW); 
    }
    /************************************************************************
      * @描述:  右转(左轮前进,右轮不动)
      * @参数:  speed:控制速度0-255
      * 功能:	小车右转
      * @返回值: None
    **********************************************************************/
    void right(int speed) 
    {
      analogWrite(IN1,speed);
      digitalWrite(IN2,LOW);
      digitalWrite(IN4,LOW);
      digitalWrite(IN3,LOW); 
    }
    /************************************************************************
      * @描述:  右旋转(左轮前进,右轮后退)
      * @参数:  speed:控制速度0-255
      * 功能:	小车右旋转
      * @返回值: None
    **********************************************************************/
    void spin_right(int speed)
    {
      analogWrite(IN1,speed);
      digitalWrite(IN2,LOW);
      digitalWrite(IN4,LOW);
      analogWrite(IN3,speed); 
    }
    /************************************************************************
      * @描述:  
      * @参数:  speed:控制速度0-255
      * 功能:	小车后退
      * @返回值: None
    **********************************************************************/
    void back(int speed) 
    {
      digitalWrite(IN1,LOW);
      analogWrite(IN2,speed);
      digitalWrite(IN4,LOW);
      analogWrite(IN3,speed);  
    }
    

    三、红外避障与红外寻迹API函数

    红外避障原理:如图红外对管D24由一个发射管和一个接收管组成,发射管发出红外线,当遇到障碍物时反射红外线由接收管接收,使运放IN1-端口电压变化,当调节R16电位器使IN1+电压变化,当IN1+ 的电压大于IN1-的电压时,OUT1输出高电平,被A5接收。
    红外寻迹原理:如图红外对管U8由一个发射管和一个接收管组成,发射管发出红外线,当没有探测到黑线时,一直反射红外线被接收管接受,IN4-端口输入固定电压,当探测到黑线时,红外线被吸收,接受管接受不到红外线,IN4-电压降低,对比IN4-、IN4+两端电压,OUT4输出高低电平,被A2接收。
    在这里插入图片描述
    代码如下:

    int BiZhang_L_S;    //左红外传感器状态
    int BiZhang_R_S;    //右红外传感器状态
    /************************************************************************
      * @描述:  当没有探测到障碍物时,A4、A5为高电平,当探测到高电平时为低电平
      * @参数:  speed:控制速度0-255
      * 功能:	红外避障
      * @返回值: None
    **********************************************************************/
    void Infrared_Avoid(int speed)
    {
        //有信号为LOW  没有信号为HIGH
        BiZhang_R_S = digitalRead(BiZhang_R);
        BiZhang_L_S = digitalRead(BiZhang_L);
        if (BiZhang_L_S == HIGH && BiZhang_R_S == HIGH)
        	run(speed);
        else if (BiZhang_L_S == HIGH & BiZhang_R_S == LOW)
            left(speed);
        else if (BiZhang_R_S == HIGH & BiZhang_L_S == LOW)
          	right(speed);
        else // 都是有障碍物
          	spin_right(speed);
    }
    int XunJi_L_S;    	//左循迹红外传感器状态
    int XunJi_R_S;    	//右循迹红外传感器状态
    /************************************************************************
      * @描述:  当没有探测到黑线时,A4、A5为高电平
      * @参数:  speed:控制速度0-255
      * 功能:	红外寻迹
      * @返回值: None
    **********************************************************************/
    void Find_Tracking(int speed)
    { 
    	XunJi_R_S = digitalRead(XunJi_R);
    	XunJi_L_S = digitalRead(XunJi_L);
    	if (XunJi_R_S ==LOW && XunJi_L_S == LOW)
    		run(speed); 
    	else if (XunJi_L_S == LOW & XunJi_R_S == HIGH)
    		right(speed);
    	else if (XunJi_R_S == LOW & XunJi_L_S ==  HIGH) 
    		left(speed);
    	else
    		brake();
    }
    

    四 、超声波测距原理

    超声波模块如图:
    在这里插入图片描述
    产品特色:
    1、典型工作用电压:5V。
    2、超小静态工作电流:小于2mA。
    3、感应角度:不大于15 度。
    4、探测距离:2cm-400cm
    5、高精度:可达0.3cm。
    6、盲区(2cm)超近。
    超声波时序如图:
    在这里插入图片描述
    原理图如下:
    在这里插入图片描述
    代码如下:

    /************************************************************************
      * @描述:  
      * @参数:  None
      * 功能:	量出前方距离
      * @返回值: int:距离(单位:CM)
    **********************************************************************/
    int Ultrasonic_Distance() 
    {
      digitalWrite(Trig, LOW);   //给触发脚低电平2μs
      delayMicroseconds(2);
      digitalWrite(Trig, HIGH);  //给触发脚高电平12μs,这里至少是10μs
      delayMicroseconds(12);
      digitalWrite(Trig, LOW);   //持续给触发脚低电
      float Time = pulseIn(Echo, HIGH);  //读取高电平时间(单位:微秒)
      return Time/58; //公式:us/58 = CM
    }  
    

    五、蓝牙控制原理

    由于蓝牙通信用的是 0、1两个通用串行通信I/O口,Arduino官方提供了,串口通信的专用API函数供用户使用,这里我们用的是Serial.available()
    函数说明见链接:https://www.arduino.cc/reference/en/language/functions/communication/serial/available/
    手机APP或者电脑上位机通过蓝牙发送字符串给给蓝牙模块(蓝牙模块就相当于是一个中转站),Arduino控制板用过0、1串行端口读取到来自蓝牙的数据。然后,我们根据来自APP或者上位机的字符串来判断功能。比如,手机发送:0X00代表前进、0X01 代表后退等等。这样我们只需要用一个switch语句实现蓝牙API函数。
    我的代码如下:

    int speed = 150;	//小车运动速度
    /************************************************************************
      * @描述:  
      * @参数:  None
      * 功能:	蓝牙控制
      * @返回值: int:距离(单位:CM)
    **********************************************************************/
    void Bluetooth_Control() 
    {     
        if (Data_Received)
        {
        	switch(IN_String[1])
          	{
            	case '1':	run(speed);
            				break;
            	case '2': 	back(speed);
            				break;
            	case '3':   left(speed);
            				break;
    	        case '4':   right(speed);
    	        			break;
    	        case '0':  	brake();
    	        			break;
    	        default:	brake();
    	        			break;
           }
           if(IN_String[3] == '1')  //旋转
           {
              	spin_left();
           }
           else if(IN_String[3] == '2')  //旋转
           {
              	spin_right();
           }
           if(IN_String[5] == '1')  //鸣笛0.5S
           {
              	digitalWrite(BEEP,HIGH);//发声音
          		delay(500);
    	      	digitalWrite(BEEP,LOW);//不发声音
           }
           if(IN_String[7] == '1')  //加速
           {
              	speed +=50;
              	if(speed > 255)  speed = 255;
           }
           if(IN_String[9] == '1')  //减速
           {
              	speed -= 50;
              	if(speed < 50)	speed = 100;
           }           
     	   IN_String = "";   // clear the string
           Data_Received = false;    
         }  
    }
    int Bluetooth_Data; 			//接收蓝牙的数据
    String IN_String = "";  		//用来储存接收到的内容
    boolean Start_flag = false;		//数据开始接收的状态标志
    boolean Data_Received = false; 	//接收数据结束标志
    /************************************************************************
      * @描述:  串口中断函数
      * @参数:  None
      * 功能:	接收来自蓝牙模块的数据
      * @返回值: None
    **********************************************************************/
    void serialEvent()
    {
      while (Serial.available()) 
      {    
        Bluetooth_Data= Serial.read();
        if(Bluetooth_Data== '$')
        {
          Start_flag = true;
        }
        if(Start_flag == true)
        {
           IN_String += (char) Bluetooth_Data;
        }  
        if (Bluetooth_Data== '#') 
        {
           Data_Received = true; 
           Start_flag = false;
        }
      }
    }
    
    

    还有红外遥控的代码不想敲了,个人感觉蓝牙遥控更加方便实用。
    接下来写一个综合例程:

    #define KEYMODE_1   1  // 定义模式1
    #define KEYMODE_2   2  // 定义模式2
    #define KEYMODE_3   3  // 定义模式3
    #define KEYMODE_4   4  // 定义模式4
    int keyMode = 1; 
    /************************************************************************
      * @描述:  按键模式切换
      * @参数:  None
      * 功能:	按键子程序
      * @返回值: None
    **********************************************************************/
    void KeyScanTask()
    {
    	static u8 keypre = 0;
    	if((keypre == 0 ) && !digitalRead(KEY))
    	{
    		keypre = 1; //置1,避免持续按下按键时再次进入此函数。
    		switch(keyMode)
    		{
    			case KEYMODE_1:keyMode = KEYMODE_2; break;
    			case KEYMODE_2:keyMode = KEYMODE_3; break;
    			case KEYMODE_3:keyMode = KEYMODE_4; break;
    			case KEYMODE_4:keyMode = KEYMODE_1; break;
    			default: break;
    		}
    	}
    	if(digitalRead(KEY))  //按键被放开
    	{
    		keypre = 0;//置0,允许再次切换LED模式
    	}
    }
    /************************************************************************
      * @描述: 模式处理函数
      * @参数:  None
      * 功能:	任务程序
      * @返回值: None
    **********************************************************************/
    void LEDTask()
    {
    	switch(keyMode)
    	{
    		case KEYMODE_1:	digitalWrite(RGB_B,LOW);
    			  			digitalWrite(RGB_R,HIGH); 
    	  					digitalWrite(RGB_G,HIGH);
    						Infrared_Avoid(200); //红外避障
    			  			break;
    		case KEYMODE_2:	digitalWrite(RGB_B,HIGH);
    			  			digitalWrite(RGB_R,LOW); 
    	  					digitalWrite(RGB_G,HIGH);
    						Find_Tracking(200); //红外寻迹
    			  			break;
    		case KEYMODE_3:	digitalWrite(RGB_B,HIGH);
    			  			digitalWrite(RGB_R,HIGH); 
    	  					digitalWrite(RGB_G,LOW);
    						Bluetooth_Control(); //红外寻迹
    			  			break;
    		case KEYMODE_4:	digitalWrite(RGB_B,LOW);
    			  			digitalWrite(RGB_R,LOW); 
    	  					digitalWrite(RGB_G,LOW);
    						 //红外寻迹,此处可以写一个超声波避障的API 
    			  			break;
    			default:
             break;
    		}
    }
    /************************************************************************
      * @描述: 
      * @参数:  None
      * 功能:	loop函数相当于 Arm的main函数
      * @返回值: None
    **********************************************************************/
    void loop()
    { 
    	KeyScanTask();
    	LEDTask();
    }
    
    展开全文
  • STM32开发板 智能小车程序烧写方法
  • 题目: 基于STM32智能小车 摘 要 STM32属于微控制器,自带了很多常用的通信接口(UART、IIC、SPI),可以接非常多的传感器,可以控制很多的设备。本次项目就是基于STM32F103芯片制作的智能小车,通过对于通用...
  • 主控芯片stm32 M3,超声波测距避障,利用数组控制小车路径,更方便对小车路径的控制,可以控制小车在地面跑出一个字母或者数字。
  • 为了提高车载视频导航控制子系统的准确度,本文介绍一种基于STM32的视觉导航系统。该系统使用USB摄像头采集周围环境信息,视频通过编码后由无线路由传送到上位机,在上位机的MATLAB中利用现有的灰度和二值化的方法对...
  • STM32智能小车之 循迹

    万次阅读 多人点赞 2014-11-15 23:49:31
    stm32实现循迹小车
  • STM32智能小车控制板打样了

    千次阅读 2020-11-17 20:06:05
    参加竞赛,总结资料,打样一个以属于我的智能小车控制板。 采用STM32F103VGT6主控芯片, 板上集成带有4路直流电机驱动,电机可带编码器口, 板上集成带有8路PWM口,可带舵机, 板上集成PS2手柄接收器座,方便...
  • stm32智能小车之路

    万次阅读 多人点赞 2014-10-20 22:47:53
    手动制作自己的小车(stm32)
  • 大家收到小车包裹后,想必都已经跃跃欲试了,接下来关注我们的系列教程,教你从零搭建一辆STM32F103智能小车,本教程面向零基础(当然基本的单片机知识和C语言知识还是需要具备的,相关学习教程可以查看前面的博客哈...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 608
精华内容 243
关键字:

stm32智能小车