聚丰项目 > 基于AB32VG1的姿态检测
本项目基于中科蓝汛AB32VG1开发板,制作了一个姿态检测系统。维特智能的高精度姿态传感器JY901S模块,该集成高精度的陀螺仪、加速度计、地磁场传感器,采用高性能的微处理器和先进的动力学解算与卡尔曼动态滤波算法,能够快速求解出模块当前的实时运动姿态。模块支持IIC和串口两种数字接口,本设计应用串口接口完成姿态传感器与开发板的通信。显示屏选择0.96寸IIC通信的OLED屏,对读取到的姿态角度进行显示。
ELECFANS_WYC

ELECFANS_WYC
团队成员
ELECFANS_WYC 电子爱好者
1、OLED:PE3--OLED_SCL、PE2--OLED_SDA、电源引脚;

2、JY901S(九轴姿态传感器)
2.1 引脚说明:PA3--JY_TX、PA4--JY_RX、电源引脚。


2.2、性能参数
电压:3.3V~5V;电流:<25mA;
测量维度:加速度-3维,角速度-3维,磁场-3维;
量程:加速度:±2/4/8/16g,角速度:±250/500/1000/2000°/s,角度X、Z轴±180°,Y轴±90°。磁场:30Gauss;
稳定性:加速度:0.01g,角速度0.05°/s。
姿态测量稳定度:0.01°。
软件框架:软件部分使用到了板卡的USART1和IIC两种通信,首先对两个模块初始化,然后开启按协议接收串口数据线程和OLED显示线程。流程图如下所示。

软件流程图
USART1配置:

协议说明:
角度输出
| 0x55 | 0x53 | RollL | RollH | PitchL | PitchH | YawL | YawH | VL | VH | SUM |
| 帧头 | 功能 | data1L | data1H | data2L | data2H | data3L | data3H | VersionH | VersionL | 校验和 |
计算方法:
俯仰角(y轴)Pitch=((PitchH<<8)|PitchL)/32768*180(°)
Version=(VH<<8)|VL
Sum=0x55+0x53+RollH+RollL+PitchH+PitchL+YawH+YawL+VH+VL
姿态传感器向上位机传输数据使用了基于串口的特定协议,一帧数据中包含帧头、功能字节、数据字节、版本信息和校验字节。因此编写串口读取程序时应按照如下逻辑:首先寻找帧头,然后匹配功能字节来判断此帧数据为什么内容,接着接收接下来的若干字节数据,最后根据校验字节校验数据是否接收正确。流程如下图所示:

串口读取协议流程图
串口1数据读取(含JY901S串口数据读取协议):
//串口1数据读取线程入口
static void serial_thread_entry(void *parameter)
{
uint8_t Res_U3;
uint8_t Sum_U3=0,i_U3;
while (1)
{
/* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
while (rt_device_read(serial, -1, &Res_U3, 1) != 1)
{
/* 阻塞等待接收信号量,等到信号量后再次读取数据 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/* 读取到的数据输出 */
//rt_kprintf("%c",Res_U3);
if((USART3_REC_STA&0x8000)==0)//接收未完成
{
if((USART3_REC_STA&0x00FF)>11)//数据长度出错
{
USART3_REC_STA=0;////接收错误,重新接收
//rt_kprintf("->1\n");
}
else
{
if((USART3_REC_STA&0x4000)==0)//未接收到帧头
{
if(Res_U3==0x55) //本字节为帧头
{
USART3_REC_STA |= 0x4000;
USART3_REC_BUF[USART3_REC_STA&0x00FF]=Res_U3;
USART3_REC_STA++;
//rt_kprintf("->2\n");
}
else {
//rt_kprintf("->3\n");
}
}
else//已接收到帧头
{
if((USART3_REC_STA&0x2000)==0)//未接收到标识字节
{
if((Res_U3==0x53)||(0))//本字节为标识字节 (Res_U3==0x54)
{
USART3_REC_STA |= 0x2000;
USART3_REC_BUF[USART3_REC_STA&0x00FF]=Res_U3;
USART3_REC_STA++;
//rt_kprintf("->4\n");
}
else
{
USART3_REC_STA=0;//接收错误,重新接收
//rt_kprintf("->5 Res_U3=%X\n",Res_U3);
}
}
else//已接收到标识字节
{
if((USART3_REC_STA&0x00FF)<11)//
{
USART3_REC_BUF[USART3_REC_STA&0x00FF]=Res_U3;
USART3_REC_STA++;
//rt_kprintf("->6\n");
if((USART3_REC_STA&0x00FF)==11)
{
//求和
Sum_U3=0;//清零
for(i_U3=0;i_U3<10;i_U3++)
{
Sum_U3=(uint8_t)(Sum_U3+USART3_REC_BUF[i_U3]);
}
//校验和
if(Sum_U3==USART3_REC_BUF[10])
{
USART3_REC_STA |= 0x8000;//校验和成功,接收完成
//rt_kprintf("rec success!\n");
}
else
{
USART3_REC_STA=0;//校验和失败,重新接收
//rt_kprintf("->7\n");
}
}
}
else {
//rt_kprintf("->8\n");
}
}
}
}
}
}
}
姿态传感器数据分析:
//数据分析函数
void Data_analysis(uint8_t fun_byte)
{
uint8_t DataH,DataL;
if((USART3_REC_STA&0x8000)==0) return;
switch(fun_byte)
{
case 0x53:
{
Roll_X= ((short)((USART3_REC_BUF[3]<<8)|USART3_REC_BUF[2]))/32768.0*180;
Pitch_Y=((short)((USART3_REC_BUF[5]<<8)|USART3_REC_BUF[4]))/32768.0*180;
Yaw_Z= ((short)((USART3_REC_BUF[7]<<8)|USART3_REC_BUF[6]))/32768.0*180;
}break;
default :USART3_REC_STA=0;break;
}
}
IIC OLED配置:



OLED姿态数据显示:
static void thread_usart1_recsho(void *parameter)
{
while(1)
{
if(USART3_REC_STA&0x8000)//接收完成
{
Data_analysis(USART3_REC_BUF[1]);
sprintf((char*)print_str,"%3.1f",Roll_X);
ssd1306_SetCursor(66,8);
ssd1306_WriteString(print_str,Font_11x18,White);
sprintf((char*)print_str,"%3.1f",Pitch_Y);
ssd1306_SetCursor(66,8+18);
ssd1306_WriteString(print_str,Font_11x18,White);
sprintf((char*)print_str,"%3.1f",Yaw_Z);
ssd1306_SetCursor(66,8+18+18);
ssd1306_WriteString(print_str,Font_11x18,White);
ssd1306_UpdateScreen();
/*
sprintf((char*)print_str,"Roll_X:%3.1f\n",Roll_X);
rt_kprintf("%s",print_str);
sprintf((char*)print_str,"Pitch_Y:%3.1f\n",Pitch_Y);
rt_kprintf("%s",print_str);
sprintf((char*)print_str,"Yaw_Z:%3.1f\n",Yaw_Z);
rt_kprintf("%s",print_str);*/
USART3_REC_STA=0;
}
rt_thread_mdelay(10);
}
}
效果演示:
代码见附件。
(11.74 MB)下载
幽幽鹿鸣: 代码缩水,没用
回复
ELECFANS_WYC: 好的亲,我改改。
回复