基于STM32读取SBG Ellipse A型号惯导数据

2023-10-25 13:20

本文主要是介绍基于STM32读取SBG Ellipse A型号惯导数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前在飞控上用的都是mpu6050,但AUV在执行任务时主要在水下环境,收不到GPS信号,因此对INS的精度要求较高,在姿态解算时要考虑地球自转等因素,因此需要一款惯导器件能够感受到地球自转,经测量,SBG公司生产的Ellipse A并不能满足要求。下面介绍一下采集系统的软件架构。

组合导航系统需要同时采集多种传感器,进行多传感器融合,以提高导航系统精度。初步准备用SBG和GPS进行融合,将GPS的更新频率降低到1Hz以模拟USBL的水环境状况,本篇文章仅介绍读取SBG部分。

SBG传感器使用的接口是RS232,说到此惭愧不已,因为学术不精,最开始直接用USB转TTL线来读数据,结果在串口助手上看到的全是乱码。

虽然都是串口设备,RS-232的通讯电平:逻辑1是-15V~-3V,逻辑0是+3V~+15V,而TTL的通讯电平:逻辑1是2.4V~5V,逻辑0是0~0.5V。从电压等级也可以看出RS-232的远距离传输和抗干扰能力更强一些。

下面看一下sbg的协议格式

 除了帧头以外,协议规定了消息ID和消息类,简单的说,消息类用于区分消息内容是传感器数据还是需要执行的命令,消息ID中将数据进行了分类,我只需要加速度计测得的加速度值和陀螺仪测得的角速度值。

读取数据协议的策略是这样的,当传感器向stm32的串口发送数据时,就会使能相应的串口中断,每中断一次接收1个字节,因此在中断函数中需要一个预处理部分,将需要解读的一组完整的imu数据存入缓存区。中断函数如下:

void USART2_IRQHandler(void)
{uint8_t ch;if(USART_GetITStatus(USART2,USART_IT_RXNE)) {USART_ClearITPendingBit(USART2, USART_IT_RXNE);	ch=USART_ReceiveData(USART2);SBG_Data_Receive_Prepare(ch);}	 
}

最初我犯了一个低级错误,将读取数据分成了两部分,一部分是将数据存入缓存区,第二部分是将缓存区数据按协议解析。这本没有问题,但是我将第一部分放在了串口中断中,将第二部分放在了定时器中断中每5ms解析一次。虽听起来不错,但有个严重的问题,当协议解析的时候并不能保证缓存区中是一组完整的数据,这就导致了读出来的数每隔几十个就会有组极大值。

正确的做法是将两部分写在同一流程中,也就是一起放到串口中断中,待数组存放完全,再去解析,而定时器则每5ms调用一次解析出的数据进行融合等操作,这样就没有问题了~

下面为两部分的函数实现:

数据预处理

extern uint8_t SBG_Data[100];
u8 sbg_data_state = 0;
u16 _data_len = 0,_data_cnt = 0;
void SBG_Data_Receive_Prepare(u8 data)
{//static u16 _data_len = 0,_data_cnt = 0;//static u8 sbg_data_state = 0;if(sbg_data_state==0&&data==0xFF) {sbg_data_state=1;_data_cnt = 0;SBG_Data[_data_cnt]=data;//0_data_cnt++;//1}else if(sbg_data_state==1&&data==0x5A) {sbg_data_state=2;SBG_Data[_data_cnt]=data;//1_data_cnt++;//2}else if(sbg_data_state==2&&data==0x03) {sbg_data_state=3;SBG_Data[_data_cnt]=data;//2_data_cnt++;//3}else if(sbg_data_state==3&&data==0x00) {sbg_data_state=4;SBG_Data[_data_cnt]=data;//3_data_cnt++;//4}else if(sbg_data_state==4&&_data_cnt<67) {SBG_Data[_data_cnt]=data;_data_cnt++;if(_data_cnt==67) {GET_SBG_DATA(SBG_Data);}}elsesbg_data_state = 0;
}

 

union 
{float a;uint8_t b[4];
} hex_receive;
float hex2flo(uint8_t *buffer)
{int i = 0;for(i = 0; i < 4; i++) hex_receive.b[i] = *(buffer+i);return hex_receive.a;
}/*!
* Compute a CRC for a specified buffer.
* \param[in] pBuffer Read only buffer to compute the CRC on.
* \param[in] bufferSize Buffer size in bytes.
* \return The computed 16 bit CRC.
*/
u16 calcCRC(const void *pBuffer, u16 bufferSize)
{const u8 *pBytesArray = (const u8*)pBuffer;u16 poly = 0x8408;u16 crc = 0;u8 carry;u8 i_bits;u16 j;for (j =0; j < bufferSize; j++){crc = crc ^ pBytesArray[j];for (i_bits = 0; i_bits < 8; i_bits++){carry = crc & 1;crc = crc / 2;if (carry){crc = crc^poly;}}}return crc;
}
/******************»ñÈ¡SBGÊý¾Ý******************/u16 SBG_Cnt = 0;u32 TIME_STAMP; //Time since sensor is powered upu16 IMU_STATUS; //IMU Status bitmask
float ACCEL_X, ACCEL_Y, ACCEL_Z;   //Filtered Accelerometer - X axis
float GYRO_X, GYRO_Y, GYRO_Z;  //Filtered Gyroscope - X axis
float ACCEL_X_past, ACCEL_Y_past, ACCEL_Z_past;   //Filtered Accelerometer - X axis
float GYRO_X_past, GYRO_Y_past, GYRO_Z_past;  //Filtered Gyroscope - X axisu8    state_ins = 0;//0±íʾpastδ¸üÐÂ
float TEMP;  //Internal Temperature
float DELTA_VEL_X, DELTA_VEL_Y, DELTA_VEL_Z;  //Sculling output - X axis
float DELTA_ANGLE_X, DELTA_ANGLE_Y, DELTA_ANGLE_Z;   //Coning output - X axis
float ROLL, PITCH, YAW;
float Q0, Q1, Q2, Q3;
float MAG_X, MAG_Y, MAG_Z;u16 CRC_Num;u16 CRC_Receive;u16 Data_Len;
void GET_SBG_DATA(uint8_t *data_buf)//´«ÈëSBG_Data[0]
{/*IEEE754: 1λ·ûºÅ룬8λָÊý£¬23λβÊý(СÊý²¿·Ö)*/if(!(*(data_buf+0)==0xFF && *(data_buf+1)==0x5A)) return;Data_Len = ((vs16)(*(data_buf+5)<<8)|*(data_buf+4));if(*(data_buf+6+Data_Len+2)!=0x33) return;/******************************************************************************** @name    SBG_ECOM_LOG_IMU_DATA* @MSGid   0x03* @brief   Includes IMU status, acc., gyro, temp delta speeds and delta angles values* @ps      Just DATA, no CRC, ETX*******************************************************************************/if(*(data_buf+2)==0x03 && *(data_buf+3)==0x00) {CRC_Num       =  calcCRC((data_buf+6), Data_Len);CRC_Receive   =  ((vs16)(*(data_buf+65)<<8)|*(data_buf+64));//		if(CRC_Num == CRC_Receive) {TIME_STAMP    =  ((vs32)(*(data_buf+9)<<24)|(*(data_buf+8)<<16)|(*(data_buf+7)<<8)|(*(data_buf+6)));IMU_STATUS    =  ((vs16)(*(data_buf+11)<<8)|*(data_buf+10));ACCEL_X       =  hex2flo(data_buf+12);ACCEL_Y       =  hex2flo(data_buf+16);ACCEL_Z       =  hex2flo(data_buf+20);GYRO_X        =  hex2flo(data_buf+24);GYRO_Y        =  hex2flo(data_buf+28);GYRO_Z        =  hex2flo(data_buf+32);TEMP          =  hex2flo(data_buf+36);DELTA_VEL_X   =  hex2flo(data_buf+40);DELTA_VEL_Y   =  hex2flo(data_buf+44);DELTA_VEL_Z   =  hex2flo(data_buf+48);DELTA_ANGLE_X =  hex2flo(data_buf+52);DELTA_ANGLE_Y =  hex2flo(data_buf+56);DELTA_ANGLE_Z =  hex2flo(data_buf+60);}/******************************************************************************** @name    SBG_ECOM_LOG_EKF_EULER* @MSGid   0x06* @brief   Includes roll, pitch, yaw and their accuracies on each axis*******************************************************************************/else if(*(data_buf+2)==0x06 && *(data_buf+3)==0xFF) {//LEN:data_buf+4   data_buf+5 //TIME_STAMP = ((vs32)(*(data_buf+6)<<24)|(*(data_buf+7)<<16)|(*(data_buf+8)<<8)|(*(data_buf+9)));//IMU_STATUS = ((vs16)(*(data_buf+10)<<8)|*(data_buf+11));ROLL   =  hex2flo(data_buf+10);PITCH  =  hex2flo(data_buf+14);YAW    =  hex2flo(data_buf+18);}/******************************************************************************** @name    SBG_ECOM_LOG_EKF_QUAT* @MSGid   0x07* @brief   Includes the 4 quaternions values*******************************************************************************/else if(*(data_buf+2)==0x07 && *(data_buf+3)==0xFF) {Q0 = hex2flo(data_buf+10);Q1 = hex2flo(data_buf+14);Q2 = hex2flo(data_buf+18);Q3 = hex2flo(data_buf+22);}/******************************************************************************** @name    SBG_ECOM_LOG_MAG* @MSGid   0x04* @brief   Magnetic data with associated accelerometer on each axis*******************************************************************************/else if(*(data_buf+2)==0x04 && *(data_buf+3)==0xFF) {MAG_X = hex2flo(data_buf+12);MAG_Y = hex2flo(data_buf+16);MAG_Z = hex2flo(data_buf+20);}else {SBG_Cnt = 0;}}

值得注意的是,在解析时,我们应该注意大小端,即传感器先发送的字节是高8位还是低8位。第二个需要注意的点就是,SBG传输的float数据格式是IEEE754格式,因此并不能用位操作去直接合并,一个小技巧是使用union联合体,在联合体中定义一个float和一个有4个元素的字符数组,这样当我们把收到的字节依次传入数组中后,float变量就是我们要的值。

这篇关于基于STM32读取SBG Ellipse A型号惯导数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/282823

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X

pandas数据过滤

Pandas 数据过滤方法 Pandas 提供了多种方法来过滤数据,可以根据不同的条件进行筛选。以下是一些常见的 Pandas 数据过滤方法,结合实例进行讲解,希望能帮你快速理解。 1. 基于条件筛选行 可以使用布尔索引来根据条件过滤行。 import pandas as pd# 创建示例数据data = {'Name': ['Alice', 'Bob', 'Charlie', 'Dav

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者