掌控麦轮车设计实现

 第一次写博客,之前也看过好多博客,我认为写博客不仅可以理清思路,还可以打开思路。废话不多说,进入正题!

 

既然是掌控车,车身一定不能超过手掌长度,so我决定车身长(算上麦克纳姆轮)不超过18cm,车宽不超过20cm。下面介绍一下所用元件吧!

①麦克纳姆轮*4,我选的麦轮直径是60mm的

②N20电机*4,电压12V,转速300r/min

③N20电机座*4

④mpu6050传感器(放在手套上,用于获取手的姿态信息,控制小车全方位移动)

⑤2.4G无线通信模块*2,车上一个,手套上一个,将手部的姿态信息或者遥控信息发送到小车上

⑥Maix DOCK(声源定位)手头上有一个,其实想用ESP-CAM实现远程监控的

⑦oled

首先制作小车的底板,最下面一层是亚克力底板,用于固定小车电机,第二层为电路板,为了节约空间,采用电路板,第三层板用于二次开发,还有手套上的一个电路板!

使用CAD制作小车底板,我定制的是亚克力板,淘宝上很多定制的

 下面就是第二层了,核心层,实现很多的功能,因为手头上又一些模块,自己画板子还要买耗材,太贵了。。。。画板子我是小白,只能画简单的板子,复杂的就要多学习了!废话不多说,开始!!!

注意:

nrf24l01的供电电压不能超过3.6V,所以降压到3.3V就可以了

小车(接收端)IO分配(VCC,GND不再赘述)

主控GPIO复用外界设备
PA8TIM1_CH1TB6612左PWMA
PA9TIM1_CH2TB6612左PWMB
PA10TIM1_CH3TB6612右PWMA
PA11TIM1_CH4TB6612右PWMB
PB3TB6612左AIN1
PB4TB6612左AIN2
PB5TB6612左BIN1
PB6TB6612左BIN2
PB7TB6612右AIN1
PB8TB6612右AIN2
PB9TB6612右BIN1
PB12TB6612右BIN2
PB10
I2C2_SCL
OLED-SCL
PB11
I2C2_SDA
OLED-SDA
PA0温湿度DAT
PA4NRF24L01_CE
PC14NRF24L01_CSN
PA5NRF24L01_SCK
PA7SPI1_MOSINRF24L01_MOSI
PA6SPI1_MISONRF24L01_MISO
PA1NRF24L01_IRQ

手掌控制(发射端)IO分配(VCC,GND不再赘述)

PA4NRF24L01_CE
PC14NRF24L01_CSN
PA5NRF24L01_SCK
PA7SPI1_MOSINRF24L01_MOSI
PA6SPI1_MISONRF24L01_MISO
PA1NRF24L01_IRQ
PB10
I2C2_SCL
OLED-SCL
PB11
I2C2_SDA
OLED-SDA
PB6软件IICMPU6050_SCL
PB7软件IICMPU6050_SDA
PB5中断引脚MPU6050_INT

接收端电路板设计

原理图

 PCB

 

发射端电路板设计

原理图

 PCB

 代码实现

发射端(main.c)

#include "stm32f10x.h"
#include "bsp_led.h"
#include "delay.h" 
#include "oled.h"
#include "24l01.h"
#include "spi.h"
#include "exti.h"
#include "mpu6050.h"
#include "mpuiic.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"

float pitch,roll,yaw; 			//欧拉角(姿态角)-----俯仰角 翻滚角 偏航角
short aacx,aacy,aacz;		    //加速度传感器原始数据
short gyrox,gyroy,gyroz;		//陀螺仪原始数据
u8 txbuf[5]={'t'};
int main(void)
{
		
	LED_GPIO_Config();
	delay_init();
	NVIC_Configuration();//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级        
	uart_init(115200);	 	//串口初始化为115200
	OLED_Init();
	OLED_Clear();
	SPI_GPIO_Init();
	SPI1_Init();
	NRF24L01_Init();    		//初始化NRF24L01
	MPU_Init();					    			 //=====初始化MPU6050
	mpu_dmp_init();								 //=====初始化MPU6050的DMP模式	
	MPU6050_EXTI_Init();					 //=====MPU6050 5ms定时中断初始化
	while(NRF24L01_Check())
	{
		OLED_ShowString(0,0,"Check Error",12);
	}
	OLED_Clear();
	OLED_ShowString(0,0,"Check OK",12);
	OLED_ShowString(0,1,"NRF24L01 TX_Mode",12);
	NRF24L01_TX_Mode();
	while(1)
	{
			OLED_ShowString(0,4,"pitch:",12);	
			OLED_ShowString(0,5,"yaw:",12);	
			OLED_ShowString(0,6,"roll:",12);	
			OLED_Float(4,48,pitch,3);	 //显示角度
			OLED_Float(5,48,yaw,3);	 //显示角度
			OLED_Float(6,48,roll,3);	 //显示角度
		
			if(pitch>25&&pitch<50&&roll>-10&&roll<25)              txbuf[0]='f';//前进
			else if(pitch<-25&&pitch>-50&&roll>-10&&roll<25)       txbuf[0]='b';//后退
			else if(pitch<25&&pitch>-10&&roll>25&&roll<50)         txbuf[0]='y';//右平移
			else if(pitch<25&&pitch>-10&&roll<-25&&roll>-50)       txbuf[0]='z';//左平移
			else if(pitch<25&&pitch>-10&&roll>50)                  txbuf[0]='r';//右转
			else if(pitch<25&&pitch>-10&&roll<-50)                 txbuf[0]='l';//左转
			else if(pitch>25&&pitch<50&&roll>25&&roll<50)          txbuf[0]='q';//斜右前
			else if(pitch>25&&pitch<50&&roll<-25&&roll>-50)        txbuf[0]='w';//斜左前
			else if(pitch<-25&&pitch>-50&&roll>25&&roll<50)        txbuf[0]='e';//斜右后
			else if(pitch<-25&&pitch>-50&&roll<-25&&roll>-50)      txbuf[0]='t';//斜左后
			else txbuf[0]='s';
			
			if(NRF24L01_TX_Packet(txbuf)==TX_OK)
			{
				OLED_ShowString(0,2,"Send OK",12);
				OLED_ShowString(0,3,txbuf,12);			
			}
			else if((NRF24L01_TX_Packet(txbuf)==MAX_TX))
			{
				OLED_ShowString(0,2,"MAX_TX",12);
			}
			else if((NRF24L01_TX_Packet(txbuf)==0XFF))
			{
				OLED_ShowString(0,2,"Send Error",12);
			}
			
	}
}

接收端代码(main.c)

#include "stm32f10x.h"
#include "delay.h"
#include "bsp_led.h"
#include "oled.h"
#include "motor.h"
#include "pwm.h"             
#include "24l01.h"
#include "spi.h"

int main(void)
{
	u8 rxbuf[5]={'0','0','0','0','0'};	 
	delay_init();
	 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	LED_GPIO_Config();                                                                          
	OLED_Init();
	OLED_Clear();
	SPI_GPIO_Init();
	SPI1_Init();
	NRF24L01_Init();    		//初始化NRF24L01  
	TIM1_PWM_Init(7199,0);
	Motor_Config();	
	while(NRF24L01_Check())
	{
		OLED_ShowString(0,0,"Check Error",12);
	}
	OLED_Clear();
	OLED_ShowString(0,0,"Check OK",12);
	OLED_ShowString(0,1,"NRF24L01 RX_Mode",12);
	NRF24L01_RX_Mode();
	while(1)
	{
		if(NRF24L01_RX_Packet(rxbuf)==1)
		{
			OLED_ShowString(0,2,"Recieve Error",12);	
		}
		else if(NRF24L01_RX_Packet(rxbuf)==0)
		{
			OLED_ShowString(0,2,"Recieve OK",12);	
			OLED_ShowString(0,3,rxbuf,12);
			switch(rxbuf[0])
			{
				case 's':stop();break;
				case 'f':front();break;
				case 'b':back();break;
				case 'y':right_ping();break;
				case 'z':left_ping();break;
				case 'r':right();break;
				case 'l':left();break;
				case 'q':youqian();break;
				case 'w':zuoqian();break;
				case 'e':youhou();break;
				case 't':zuohou();break;
			}
		}
		
	}

}

效果展示

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
鼠标由发射板和接收板组成,发射板主要包括stm32,MPU6050NRF24l01,相信我不用说明大家都知道他们分别是干什么的了吧。 接收板主要包括stm32和NRF24l01,接收板通过USB接口和电脑连接,USB驱动是STM32的官方例程。另外,cpu使用的是stm32f103c8t6 这个芯片有两个优点,一个是小,另外一个是便宜,统计下来做一个鼠标刨去PCB的成本,大概60元左右。 这个空中飞鼠的原理大概讲一下,就是读取MPU6050中X和Z轴上的角速度值,然后通过NRF24l01发送给接收板,接收板通过NRF24l01 接收到数据后,通过stm32内部自带的USB模块将数据发送给电脑,而USB部分的东西基本不用去深入研究,使用的时候只要知道那个鼠标 数据的接口函数就可以了。 视频: 视频中只有发射板,我将发射板做成跟18650电池大小差不多,这样就直接可以放到移动电源里了,这样移动电源就不仅可以充电,还可以 当鼠标使用。怎么样实际的使用效果还可以吧? 下面是空中鼠标的图片细节。 这是发射板的PCB,MPU6050NRF24l01都是直接使用的现成模块,方便了焊接并且提高了制作成功率。 这是装好后的实物图,也许你会奇怪后面为什么要用那么长的两个按键?这是因为我要把板子放到移动电源的电池仓内,所以需要很长的按键, 我也懒得再去研究怎么装按键会更好看,所以就用了这种懒办法。 这是接收板的PCB板和实物图,电路其实很简单,我做了两点优化,一个是双USB接口,这样不仅可以直接插到电脑上,而且可以在调试程序的时候 使用USB线来连接,另一个是将IO口全部引出,这样接收板还可以当做开发板使用,对于我这种电子爱好屌丝来说无疑是一个很省成本的方案。 上图是发射板放在移动电源中,移动电源最好选用内部是18650的,这样方便改造。只要将线连接好,将板子固定住,在盖子上打好洞就行, 我用的LDO是一个低压差的,座椅无论你使用移动电源出来的5V或者直接连接18650都是可以正常工作的。 最后,附上原理图和程序,没有太多注释,因为程序我自己写的部分很简单,其他部分都是官方或者战舰开发板上现成的例程,现在我的程序, 除了控制方向,鼠标左右键外,还增加了两个按键同时按下开启滚轮功能,期望有人能在我的基础上继续优化程序,因为我对算法这边实在了 解的不多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值