沉寂了挺久,积攒了一些东东,今天分享给大家。————ANO Tech 匿名四轴
最近真的是被忙坏了,吸取前两次套件的经验,做出了这次算是已经硬件定型的微型四轴。PCB进行优化,更“瘦小”,更简洁。而且为了对所选材料进行甄别,还特意买了小电子称和转速仪,这次挑选的电机为7*16空心杯,但在同等电压下同7*20空心杯转速相差无几(转速仪测试),但重量减轻好多(7*20:3.3g,我们的7*16:2.3g),电池更换为400mah25C动力电池,重量为11.1g,整体重量由之前的44.2g减少到现在的34.2g,所以飞机的机动性更高,飞起来更“暴力”。
无线仍然采用NRF24L01,不同的是在飞机上和遥控板上都增加了PA芯片,增加无线功率,电感电容全部采用进口村田,而且遥控板采用增益天线,飞机也舍弃原来的PCB天线,采用外接超轻的2.4G天线,信号更好。无线的稳定性和距离都提高很多,完全满足小四轴需要。(经验:大家在无线相关设计时,还是不要考虑成本,选用高精度的材料吧。别不舍得。。)
完善各个模块的代码,特别是上位机,相比以前增加了很多功能,根据网友的要求,加入了波形保存、读取等功能。。。
随着新套件的完成,编写了一系列针对新套件的程序,可以直接下载运行,废话少说,上程序。本工程测试LED,下载后飞控板上电,可看到飞控中心板四周4个LED不停闪动.
源程序.zip
(405.39 KB, 下载次数: 70)
1.1_LED_TEST.zip
此工程为套件基本LED闪动演示
2.2_UART_TEST.zip
此工程为套件串口演示
3.3_SPI_NRF_TEST.zip
此工程为套件SPI和NRF24L01相关功能测试
4.4_TIMER_TEST.zip
次工程为套件定时器演示
5.5_IIC_6050_TEST.zip
此工程为套件IIC和6050相关演示,其中IIC为硬件IIC,下面有IIC库提供给大家
6.6_WAVE_3D_TEST.zip
此工程为测试上位机通过无线接收飞控数据,并3D显示姿态,画传感器数据曲线图的相关演示
7.7_HIGH_SPEED_TEST.zip
此工程为套件高速通信测试,串口工作在500K,1ms向上位机发送32字节传感器数据,上位机分析数据并实时画出曲线
8.8_DMP_TEST.zip
此工程是为本套件移植好的DMP工程,使用的是官方库
9.综合测试
此工程为套件的综合测试,包括无线通信、无线调整PID、无线调整传感器零点、数据FLASH区保存、波形显示、3D姿态显示、键盘鼠标控制、飞控解锁、飞控锁定、电机PWM显示、电压监控等功能
10. PPM采集
此工程为套件遥控板采集PPM信号的工程
下面给大家分享我自己写的硬件IIC驱动,使用硬件中断模式,至今运行一直正常。
因为程序太多,还请大家移步下载,地址在上位机里有.
因为很多人基础不同,所以演示工程弄得详细了一点,高手请略过。四轴用到的相关模块相关程序可以说以上工程里都包含了。
以上工程中,NRF24L01都采用ACK With payload 模式实现双向数据通信,不用手动切换收发状态,NRF24L01自动完成收发切换。
下面给大家分享我自己写的硬件IIC驱动,使用硬件中断模式,至今运行一直正常。
下面是相关资料和原理图:
不思--相关芯片资料及SWD_gerber文件.zip
(6.61 MB, 下载次数: 40)
下面是最新的上位机,相比以前发布的功能完善很多,波形显示,3D姿态显示,遥控数据显示,电机PWM显示,电压监控,PID无线调整,零偏无线调整等等,就不具体讲用法了,相关功能请打开上位机按F12查看帮助文件,如果有问题请联系我
上位机界面:
下载:
::::::::
ANO_Tech匿名四轴上位机_v2.3.zip
(1.57 MB, 下载次数: 90)
新旧对比:
新飞机:
遥控板:
swd调试器:
PS:我在这里开源所有的资料,是希望大家一起来玩,方便大家,可是有些人。。。拿我开源的资料去卖钱,唉。。。
大家在淘宝搜 四轴 资料,有好几个,里面的资料都是我以前开源的,连介绍都是copy我的。。。。无语了
不过,咱的创意和想法他们copy不走的!
硬件弄好了,以后就要专心调试软件了,目前姿态已经算稳定了,就差一个好用的PID了,不少人也要拿到套件了,大家在这里多多交流软件和调试经验,争取早日飞稳了。
- #include "MPU6050.h"
- #include "ANO_Tech_STM32F10x_I2C.h"
- #include "tim.h"
- u8 mpu6050_buffer[14]; //iic读取后存放数据
- S_INT16_XYZ GYRO_OFFSET,ACC_OFFSET; //零漂
- u8 GYRO_OFFSET_OK = 1;
- u8 ACC_OFFSET_OK = 1;
- S_INT16_XYZ MPU6050_ACC_LAST,MPU6050_GYRO_LAST; //最新一次读取值
- void Delay_ms_mpu(u16 nms)
- {
- u8 delay_cnt = TIM3_IRQCNT;
- while((delay_cnt+(nms*2)) > TIM3_IRQCNT);
- }
- /**************************实现函数********************************************
- //将iic读取到得数据分拆,放入相应寄存器
- *******************************************************************************/
- void MPU6050_Dataanl(void)
- {
- MPU6050_ACC_LAST.X=((((int16_t)mpu6050_buffer[0]) << 8) | mpu6050_buffer[1]) - ACC_OFFSET.X;
- MPU6050_ACC_LAST.Y=((((int16_t)mpu6050_buffer[2]) << 8) | mpu6050_buffer[3]) - ACC_OFFSET.Y;
- MPU6050_ACC_LAST.Z=((((int16_t)mpu6050_buffer[4]) << 8) | mpu6050_buffer[5]) - ACC_OFFSET.Z;
- //跳过温度ADC
- MPU6050_GYRO_LAST.X=((((int16_t)mpu6050_buffer[8]) << 8) | mpu6050_buffer[9]) - GYRO_OFFSET.X;
- MPU6050_GYRO_LAST.Y=((((int16_t)mpu6050_buffer[10]) << 8) | mpu6050_buffer[11]) - GYRO_OFFSET.Y;
- MPU6050_GYRO_LAST.Z=((((int16_t)mpu6050_buffer[12]) << 8) | mpu6050_buffer[13]) - GYRO_OFFSET.Z;
-
- if(!GYRO_OFFSET_OK)
- {
- static int32_t tempgx=0,tempgy=0,tempgz=0;
- static uint8_t cnt_g=0;
- // LED1_ON;
- if(cnt_g==0)
- {
- GYRO_OFFSET.X=0;
- GYRO_OFFSET.Y=0;
- GYRO_OFFSET.Z=0;
- tempgx = 0;
- tempgy = 0;
- tempgz = 0;
- cnt_g = 1;
- return;
- }
- tempgx+= MPU6050_GYRO_LAST.X;
- tempgy+= MPU6050_GYRO_LAST.Y;
- tempgz+= MPU6050_GYRO_LAST.Z;
- if(cnt_g==200)
- {
- GYRO_OFFSET.X=tempgx/cnt_g;
- GYRO_OFFSET.Y=tempgy/cnt_g;
- GYRO_OFFSET.Z=tempgz/cnt_g;
- cnt_g = 0;
- GYRO_OFFSET_OK = 1;
- // EE_SAVE_GYRO_OFFSET();//保存数据
- return;
- }
- cnt_g++;
- }
- if(!ACC_OFFSET_OK)
- {
- static int32_t tempax=0,tempay=0,tempaz=0;
- static uint8_t cnt_a=0;
- // LED1_ON;
- if(cnt_a==0)
- {
- ACC_OFFSET.X = 0;
- ACC_OFFSET.Y = 0;
- ACC_OFFSET.Z = 0;
- tempax = 0;
- tempay = 0;
- tempaz = 0;
- cnt_a = 1;
- return;
- }
- tempax+= MPU6050_ACC_LAST.X;
- tempay+= MPU6050_ACC_LAST.Y;
- //tempaz+= MPU6050_ACC_LAST.Z;
- if(cnt_a==200)
- {
- ACC_OFFSET.X=tempax/cnt_a;
- ACC_OFFSET.Y=tempay/cnt_a;
- ACC_OFFSET.Z=tempaz/cnt_a;
- cnt_a = 0;
- ACC_OFFSET_OK = 1;
- // EE_SAVE_ACC_OFFSET();//保存数据
- return;
- }
- cnt_a++;
- }
- }
- /**************************实现函数********************************************
- //将iic读取到得数据分拆,放入相应寄存器,更新MPU6050_Last
- *******************************************************************************/
- void MPU6050_Read(void)
- {
- ANO_Tech_I2C1_Read_Int(devAddr,MPU6050_RA_ACCEL_XOUT_H,14,mpu6050_buffer);
- }
- /**************************实现函数********************************************
- *函数原型: u8 IICwriteBit(u8 dev, u8 reg, u8 bitNum, u8 data)
- *功 能: 读 修改 写 指定设备 指定寄存器一个字节 中的1个位
- 输入 dev 目标设备地址
- reg 寄存器地址
- bitNum 要修改目标字节的bitNum位
- data 为0 时,目标位将被清0 否则将被置位
- 返回 成功 为1
- 失败为0
- *******************************************************************************/
- void IICwriteBit(u8 dev, u8 reg, u8 bitNum, u8 data){
- u8 b;
- ANO_Tech_I2C1_Read_Buf(dev, reg, 1, &b);
- b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
- ANO_Tech_I2C1_Write_1Byte(dev, reg, b);
- }
- /**************************实现函数********************************************
- *函数原型: u8 IICwriteBits(u8 dev,u8 reg,u8 bitStart,u8 length,u8 data)
- *功 能: 读 修改 写 指定设备 指定寄存器一个字节 中的多个位
- 输入 dev 目标设备地址
- reg 寄存器地址
- bitStart 目标字节的起始位
- length 位长度
- data 存放改变目标字节位的值
- 返回 成功 为1
- 失败为0
- *******************************************************************************/
- void IICwriteBits(u8 dev,u8 reg,u8 bitStart,u8 length,u8 data)
- {
-
- u8 b,mask;
- ANO_Tech_I2C1_Read_Buf(dev, reg, 1, &b);
- mask = (0xFF << (bitStart + 1)) | 0xFF >> ((8 - bitStart) + length - 1);
- data <<= (8 - length);
- data >>= (7 - bitStart);
- b &= mask;
- b |= data;
- ANO_Tech_I2C1_Write_1Byte(dev, reg, b);
- }
- /**************************实现函数********************************************
- *函数原型: void MPU6050_setClockSource(uint8_t source)
- *功 能: 设置 MPU6050 的时钟源
- * CLK_SEL | Clock Source
- * --------+--------------------------------------
- * 0 | Internal oscillator
- * 1 | PLL with X Gyro reference
- * 2 | PLL with Y Gyro reference
- * 3 | PLL with Z Gyro reference
- * 4 | PLL with external 32.768kHz reference
- * 5 | PLL with external 19.2MHz reference
- * 6 | Reserved
- * 7 | Stops the clock and keeps the timing generator in reset
- *******************************************************************************/
- void MPU6050_setClockSource(uint8_t source){
- IICwriteBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);
-
- }
- /** Set full-scale gyroscope range.
- * @param range New full-scale gyroscope range value
- * @see getFullScaleRange()
- * @see MPU6050_GYRO_FS_250
- * @see MPU6050_RA_GYRO_CONFIG
- * @see MPU6050_GCONFIG_FS_SEL_BIT
- * @see MPU6050_GCONFIG_FS_SEL_LENGTH
- */
- void MPU6050_setFullScaleGyroRange(uint8_t range) {
- IICwriteBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
- }
- /**************************实现函数********************************************
- *函数原型: void MPU6050_setFullScaleAccelRange(uint8_t range)
- *功 能: 设置 MPU6050 加速度计的最大量程
- *******************************************************************************/
- void MPU6050_setFullScaleAccelRange(uint8_t range) {
- IICwriteBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
- }
- /**************************实现函数********************************************
- *函数原型: void MPU6050_setSleepEnabled(uint8_t enabled)
- *功 能: 设置 MPU6050 是否进入睡眠模式
- enabled =1 睡觉
- enabled =0 工作
- *******************************************************************************/
- void MPU6050_setSleepEnabled(uint8_t enabled) {
- IICwriteBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled);
- }
- /**************************实现函数********************************************
- *函数原型: void MPU6050_setI2CMasterModeEnabled(uint8_t enabled)
- *功 能: 设置 MPU6050 是否为AUX I2C线的主机
- *******************************************************************************/
- void MPU6050_setI2CMasterModeEnabled(uint8_t enabled) {
- IICwriteBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled);
- }
- /**************************实现函数********************************************
- *函数原型: void MPU6050_setI2CBypassEnabled(uint8_t enabled)
- *功 能: 设置 MPU6050 是否为AUX I2C线的主机
- *******************************************************************************/
- void MPU6050_setI2CBypassEnabled(uint8_t enabled) {
- IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled);
- }
- void MPU6050_setDLPF(uint8_t mode)
- {
- IICwriteBits(devAddr, MPU6050_RA_CONFIG, MPU6050_CFG_DLPF_CFG_BIT, MPU6050_CFG_DLPF_CFG_LENGTH, mode);
- }
- /**************************实现函数********************************************
- *函数原型: void MPU6050_initialize(void)
- *功 能: 初始化 MPU6050 以进入可用状态。
- *******************************************************************************/
- void MPU6050_Init(void)
- {
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x19,0x07);//1khz
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x1a,0x03);//44hz滤波
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x1b,0x00);//gyro 250du/s
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x1c,0x08);//acc +-4g
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x24,13);//400khz
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x6a,0x00);//mst_en=0
- ANO_Tech_I2C1_Write_1Byte(0xd2,0x6b,0x00);//sleep=0
- // MPU6050_setSleepEnabled(0); //进入工作状态
- // Delay_ms_mpu(200);
- // MPU6050_setClockSource(MPU6050_CLOCK_PLL_XGYRO); //设置时钟 0x6b 0x01
- // Delay_ms_mpu(50);
- // MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_500);//陀螺仪最大量程 +-500度每秒
- // Delay_ms_mpu(50);
- // MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_4); //加速度度最大量程 +-4G
- // Delay_ms_mpu(50);
- // MPU6050_setDLPF(MPU6050_DLPF_BW_42);
- // Delay_ms_mpu(50);
- // MPU6050_setI2CMasterModeEnabled(0); //不让MPU6050 控制AUXI2C
- // Delay_ms_mpu(50);
- // MPU6050_setI2CBypassEnabled(1); //主控制器的I2C与 MPU6050的AUXI2C 直通。控制器可以直接访问HMC5883L
- // Delay_ms_mpu(50);
- }
复制代码
|