第一次写博客,之前也看过好多博客,我认为写博客不仅可以理清思路,还可以打开思路。废话不多说,进入正题!
既然是掌控车,车身一定不能超过手掌长度,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 | 复用 | 外界设备 |
PA8 | TIM1_CH1 | TB6612左PWMA |
PA9 | TIM1_CH2 | TB6612左PWMB |
PA10 | TIM1_CH3 | TB6612右PWMA |
PA11 | TIM1_CH4 | TB6612右PWMB |
PB3 | 无 | TB6612左AIN1 |
PB4 | 无 | TB6612左AIN2 |
PB5 | 无 | TB6612左BIN1 |
PB6 | 无 | TB6612左BIN2 |
PB7 | 无 | TB6612右AIN1 |
PB8 | 无 | TB6612右AIN2 |
PB9 | 无 | TB6612右BIN1 |
PB12 | 无 | TB6612右BIN2 |
PB10 |
I2C2_SCL
| OLED-SCL |
PB11 |
I2C2_SDA
| OLED-SDA |
PA0 | 无 | 温湿度DAT |
PA4 | 无 | NRF24L01_CE |
PC14 | 无 | NRF24L01_CSN |
PA5 | 无 | NRF24L01_SCK |
PA7 | SPI1_MOSI | NRF24L01_MOSI |
PA6 | SPI1_MISO | NRF24L01_MISO |
PA1 | 无 | NRF24L01_IRQ |
手掌控制(发射端)IO分配(VCC,GND不再赘述)
PA4 | 无 | NRF24L01_CE |
PC14 | 无 | NRF24L01_CSN |
PA5 | 无 | NRF24L01_SCK |
PA7 | SPI1_MOSI | NRF24L01_MOSI |
PA6 | SPI1_MISO | NRF24L01_MISO |
PA1 | 无 | NRF24L01_IRQ |
PB10 |
I2C2_SCL
| OLED-SCL |
PB11 |
I2C2_SDA
| OLED-SDA |
PB6 | 软件IIC | MPU6050_SCL |
PB7 | 软件IIC | MPU6050_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;
}
}
}
}
效果展示