九轴陀螺仪ICM20948磁力计校准

九轴陀螺仪ICM20948磁力计校准

ICM20948九轴传感器目前应用广泛,是非常适合用于智能手机,平板电脑,可穿戴式传感器,物联网和应 用的全球功耗最低的9轴MotionTracking设备。其融合了3轴陀螺仪,3轴加速度计,3轴磁力计和数字运动处理器。其封装小,功耗低便于集成,融合了磁力计及内置DMP使其运动性能较MPU6050六轴传感器有很大提升。

在使用ICM20948的过程中发现使用磁力计后效果反而不如不使用好,于是决定把磁力计数据分析一下

采集数据

下位机代码

		OutData[0] = 0xB5;  //帧头,用于判断一组数据
		OutData[1] = rawData[7] & 0x00ff;  //低八位
		OutData[2] = rawData[7] >> 8;      //高八位
		OutData[3] = rawData[8] & 0x00ff;
		OutData[4] = rawData[8] >> 8;
		OutData[5] = rawData[9] & 0x00ff;
		OutData[6] = rawData[9] >> 8;			
		OutPut_Data(OutData);
        for(i=0; i<7; i++)
        {
            USART_SendData(USART3,OutData[i]);
            while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
        }
		
		

串口助手接收数据

在这里插入图片描述

将数据存到txt中
在这里插入图片描述

matlab处理数据

提取数据

[FileName,PathName] = uigetfile('*.txt','Select the Txt files');  %选择要处理的文件
fid=fopen([PathName FileName],'r');                               %读取文件
if fid == -1  
    ( 'Error opening the file'); end 
    
myword = textscan(fid, '%s');
array_num = numel(myword{1});
aim_num = zeros(1,8000);   %提前分配内存
dataFromMF = zeros(1000,7);
dataFromMFIndex = 1 ;
dataFromMFIndex_group = 1 ;
dataFromMFReadyFlag = 0 ;
x = zeros(1,1000);
y = zeros(1,1000);
z = zeros(1,1000);

for i = 1 : array_num
    aim_num(i) = hex2dec(myword{1,1}{i,1});
    switch dataFromMFIndex
			case 1
                if aim_num(i) == 181
                        dataFromMF(dataFromMFIndex_group,dataFromMFIndex)=aim_num(i);
                        dataFromMFIndex = dataFromMFIndex + 1;
                end
			case 7
                        dataFromMF(dataFromMFIndex_group,dataFromMFIndex)=aim_num(i);
                        dataFromMFIndex_group = dataFromMFIndex_group + 1;
                        dataFromMFIndex=1;
        otherwise
                        dataFromMF(dataFromMFIndex_group,dataFromMFIndex)=aim_num(i);
                        dataFromMFIndex = dataFromMFIndex + 1;
    end
                
end


在这里插入图片描述

发现每几组数据就会有一组异常值,于是把这些数据过滤掉,初步判断问题可能出在了这里,但是其他数据的分析还是要做滴

由于单片机中负数以补码的形式存储,所以需要把数据再处理一下


for i = 1 : (dataFromMFIndex_group - 1)
    x(i) = dataFromMF(i,2) + dataFromMF(i,3) * 256;
    y(i) = dataFromMF(i,4) + dataFromMF(i,5) * 256;
    z(i) = dataFromMF(i,6) + dataFromMF(i,7) * 256;    
end
for i = 1 : (dataFromMFIndex_group - 1)
    if x(i) >= 32786
        a = x(i);
        x(i) = bitcmp (uint16(a));    %转换成十进制
        x(i) = -x(i);
    end
    if y(i) >= 32786
        b = y(i);
        y(i) = bitcmp (uint16(b));
        y(i) = -y(i);
    end
    if z(i) >= 32786
        a = z(i);
        z(i) = bitcmp (uint16(a));
        z(i) = -z(i);
    end    
    if x(i)>1024 || y(i)>1024 || z(i)>1024 ||x(i)<-1024 || y(i)<-1024 || z(i)<-1024  %过滤掉不正常的值
        x(i) = 0;
        y(i) = 0;
        z(i) = 0;
    end

end

绘制三维图

scatter3(x,y,z);

在这里插入图片描述

发现并不是一个球体,建立x-y 、 x-z 、y-z坐标系再观察观察

cftool  %命令行下使用工具cftool

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

圆心不在坐标轴原点,和想象中差别有点大,因为觉得这个传感器挺贵的

校准

取每个轴的最大值最小值,相加除以2

x_dif =( max(x)+ min(x)) /2;
y_dif = ( max(y)+ min(y)) /2;
z_dif = ( max(z)+ min(z)) /2;
for i = 1 : (dataFromMFIndex_group - 1)
    x(i) =  x(i) - x_dif;
    y(i) =  y(i) - y_dif;
    z(i) =  z(i) - z_dif;
end

在这里插入图片描述

处理完之后发现圆心回到了坐标轴原点,但是还是个椭圆

等比例缩放

for i = 1 : (dataFromMFIndex_group - 1)
    x(i) =  x(i) ;
    y(i) =  y(i) * (max(x) - min(x)) / (max(y) - min(y));
    z(i) =  z(i) * (max(x) - min(x)) / (max(z) - min(z));
end

在这里插入图片描述

发现变成了一个圆,此时再绘制三维图

在这里插入图片描述

发现它比之前规则了很多,校准完成

之后就要解决数据突变的问题了,下次再说

  • 19
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
ICM-20948是一款集成了三轴加速度计、三轴陀螺仪和三轴地磁计的惯性测量单元(IMU)。它可以通过I2C或SPI接口与主控制器通信。 在ICM-20948中,磁力计是由三轴地磁计组成的。地磁计可以测量地球的磁场,因此可以用于导航和方向控制。 磁力计的读数可以通过I2C或SPI接口读取。在I2C模式下,可以通过以下代码获取磁力计读数: ``` Wire.beginTransmission(0x68); // ICM-20948的I2C地址为0x68 Wire.write(0x49); // 寄存器地址为0x49,对应磁力计X轴低8位 Wire.endTransmission(false); Wire.requestFrom(0x68, 6, true); // 读取磁力计X、Y、Z轴低8位和高8位,共6个字节 int16_t mx = Wire.read() | (Wire.read() << 8); // 拼接低8位和高8位,得到磁力计X轴数值 int16_t my = Wire.read() | (Wire.read() << 8); // 拼接低8位和高8位,得到磁力计Y轴数值 int16_t mz = Wire.read() | (Wire.read() << 8); // 拼接低8位和高8位,得到磁力计Z轴数值 ``` 在SPI模式下,可以通过以下代码获取磁力计读数: ``` digitalWrite(CS_PIN, LOW); // 使能SPI从设备 SPI.transfer(0x49); // 寄存器地址为0x49,对应磁力计X轴低8位 int16_t mx = SPI.transfer(0) | (SPI.transfer(0) << 8); // 拼接低8位和高8位,得到磁力计X轴数值 int16_t my = SPI.transfer(0) | (SPI.transfer(0) << 8); // 拼接低8位和高8位,得到磁力计Y轴数值 int16_t mz = SPI.transfer(0) | (SPI.transfer(0) << 8); // 拼接低8位和高8位,得到磁力计Z轴数值 digitalWrite(CS_PIN, HIGH); // 禁用SPI从设备 ``` 需要注意的是,ICM-20948的磁力计读数需要进行校准才能得到准确的结果。一般的校准方法是在不受干扰的环境下,将IMU在六个方向上旋转并记录磁力计读数,然后通过线性变换得到校准参数。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值