自用:磁传感器数据解算

news2024/9/21 17:41:03

协议格式:

 

 

详细计算磁场如下:

3字节数据的格式为有符号整型数,数据为补码格式,最高位为符号位。需要先将补码格式的数据转化为10进制的实际值,方法如下:

当数据小于时为正数,实际值为本身;

当数据大于等于时为负数,实际值为本身值减去

例如:X通道数据为0x63FDC2 ,转化为十进制为6553026,小于8388607,所以它的实际值为它本身:6553026

又如:Y通道数据为0xDC54B2,转化为十进制为14439602,大于8388607,所以它的值为负数,实际值应为本身值减去;即:14439602 - = -2337614;

假设计算得到的数据实际值为data,最终磁场值为Mag,它们的关系为:

 (单位:nT)

其中:Vref为参考电压,本设备参考电压为2.5V;

       Kc为磁传感器的磁电系数Kc = 40nT/mV;

计算结果为负数时,说明磁场方向与参考方向相反。

#include <iostream>
#include <tuple>
#include <cstring>
#include <cstdint>
#include <memory>
#include <array>

// 定义单包内数据段个数
constexpr size_t data_one_package_num = 20;

struct data_receive_raw {
    [[maybe_unused]] uint8_t _head[2];            // 000C头部标志
    uint8_t _x_channel[3];                        // x通道磁场数据
    [[maybe_unused]] uint8_t _x_channel_count;    // x通道计数
    uint8_t _y_channel[3];                        // y通道磁场数据
    [[maybe_unused]] uint8_t _y_channel_count;    // y通道计数
    uint8_t _z_channel[3];                        // z通道磁场数据
    [[maybe_unused]] uint8_t _z_channel_count;    // z通道计数
    [[maybe_unused]] uint8_t _padding[6];         // CRC校验和,视作字节填充位
};

// 计算单包字节偏移量
constexpr size_t bytes_offset = sizeof(data_receive_raw);

// 编译期计算偏移量数组
constexpr std::array<size_t, data_one_package_num> calculate_offsets() {
    std::array<size_t, data_one_package_num> offsets{};
    for (size_t i = 0; i < data_one_package_num; ++i) {
        offsets[i] = 6 + i * bytes_offset;  // 6为包头丢弃部分
    }
    return offsets;
}

//  三通道磁场数据解算
std::tuple<double, double, double> cal_magnetic_nT(const data_receive_raw &raw_data) {
    // 磁传感器磁电系数
    constexpr static int Kc = 40;

    // 参考电压
    constexpr static float Vref = 2.5;

    // 量化台阶
    constexpr static int zoom = (1 << 23) - 1;

    // 整数回绕值
    constexpr static int odd = 1 << 24;

    auto convert_channel = [](const uint8_t* channel) {
        uint32_t data_raw = (channel[2] << 16) | (channel[1] << 8) | channel[0];
        int data = static_cast<int>(data_raw);
        data = (data >= zoom) ? data - odd : data;
        return static_cast<double>(data) * (Vref / zoom) * 1000 * Kc;
    };

    double mag_x = convert_channel(raw_data._x_channel);
    double mag_y = convert_channel(raw_data._y_channel);
    double mag_z = convert_channel(raw_data._z_channel);

    return std::make_tuple(mag_x, mag_y, mag_z);
}

int main() {
    uint8_t data[] = {70, 77, 144, 1, 116, 54, 0, 12, 39, 31, 247, 88, 23,
                      71, 22, 89, 156, 250, 58, 90, 130, 0, 0, 84, 117, 54,
                      0, 12, 0, 35, 247, 88, 54, 73, 22, 89, 197, 251, 58,
                      90, 119, 0, 0, 84, 118, 54, 0, 12, 160, 35, 247, 88,
                      45, 71, 22, 89, 156, 255, 58, 90, 72, 255, 255, 84, 119,
                      54, 0, 12, 183, 32, 247, 88, 251, 68, 22, 89, 94, 254,
                      58, 90, 30, 0, 0, 84, 120, 54, 0, 12, 190, 33, 247,
                      88, 51, 70, 22, 89, 54, 251, 58, 90, 136, 0, 0, 84,
                      121, 54, 0, 12, 235, 37, 247, 88, 157, 72, 22, 89, 202,
                      252, 58, 90, 135, 0, 0, 84, 122, 54, 0, 12, 14, 38,
                      247, 88, 86, 72, 22, 89, 219, 255, 58, 90, 67, 255, 255,
                      84, 123, 54, 0, 12, 35, 35, 247, 88, 119, 70, 22, 89,
                      99, 254, 58, 90, 38, 0, 0, 84, 124, 54, 0, 12, 174,
                      36, 247, 88, 31, 70, 22, 89, 222, 250, 58, 90, 126, 0,
                      0, 84, 125, 54, 0, 12, 85, 32, 247, 88, 28, 70, 22,
                      89, 102, 253, 58, 90, 245, 0, 0, 84, 126, 54, 0, 12,
                      95, 33, 247, 88, 169, 73, 22, 89, 5, 253, 58, 90, 141,
                      0, 0, 84, 127, 54, 0, 12, 83, 36, 247, 88, 163, 73,
                      22, 89, 26, 1, 59, 90, 231, 254, 255, 84, 128, 54, 0,
                      12, 94, 35, 247, 88, 235, 69, 22, 89, 196, 1, 59, 90,
                      42, 0, 0, 84, 129, 54, 0, 12, 83, 32, 247, 88, 60,
                      70, 22, 89, 217, 253, 58, 90, 210, 0, 0, 84, 130, 54,
                      0, 12, 95, 34, 247, 88, 204, 72, 22, 89, 248, 253, 58,
                      90, 125, 0, 0, 84, 131, 54, 0, 12, 27, 37, 247, 88,
                      52, 73, 22, 89, 254, 0, 59, 90, 240, 254, 255, 84, 132,
                      54, 0, 12, 195, 35, 247, 88, 32, 71, 22, 89, 130, 0,
                      59, 90, 192, 255, 255, 84, 133, 54, 0, 12, 131, 32, 247,
                      88, 192, 70, 22, 89, 25, 253, 58, 90, 102, 1, 0, 84,
                      134, 54, 0, 12, 210, 33, 247, 88, 234, 72, 22, 89, 78,
                      253, 58, 90, 142, 0, 0, 84, 135, 54, 0, 12, 56, 36,
                      247, 88, 153, 73, 22, 89, 202, 0, 59, 90, 221, 254, 255,
                      84, 13, 10, 13, 10, 70, 71, 64, 0, 181, 98, 1, 2,
                      28, 0, 232, 140, 23, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 152, 189, 255, 255, 255, 255, 255, 255,
                      0, 102, 134, 223, 196, 79, 181, 98, 1, 33, 20, 0, 232,
                      140, 23, 0, 255, 255, 255, 255, 0, 132, 215, 23, 228, 7,
                      3, 22, 0, 25, 43, 240, 103, 242, 13, 10, 13, 10, 170,
                      169, 13, 10, 72, 83, 224, 1};

    constexpr auto offsets = calculate_offsets();

    auto one_package = std::make_unique<data_receive_raw[]>(data_one_package_num);
    for (size_t i = 0; i < data_one_package_num; ++i) {
        std::memcpy(&one_package[i], data + offsets[i], bytes_offset);
    }

    for (size_t i = 0; i < data_one_package_num; ++i) {
        auto [x, y, z] = cal_magnetic_nT(one_package[i]);
        std::cout << "  X channel = " << x << "  Y channel = " << y << "  Z channel = " << z << std::endl;
    }

    return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1943583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mac中maven配置安装路径

Mac中maven配置安装路径 没有下载maven的可以先下载&#xff1a;&#xff08;这里建议maven版本不要下高了&#xff09; 如果你的bash_profile中没有配置JAVA_HOME路径&#xff0c;可以按照下面的命令配置一下 获取JAVA的安装路径&#xff1a; /usr/libexec/java_home -V …

Nest.js 实战 (三):使用 Swagger 优雅地生成 API 文档

什么是 Swagger ? Swagger 是一组围绕 OpenAPI 规范构建的开源工具&#xff0c;可以帮助您设计、构建、记录和使用 REST API。主要的 Swagger 工具 包括&#xff1a; Swagger Editor&#xff1a;基于浏览器的编辑器&#xff0c;您可以在其中编写 OpenAPI 定义Swagger UI&…

NSSCTF[堆][tcache]

1. [CISCN 2021 初赛]lonelywolf 题目地址&#xff1a;[CISCN 2021 初赛]lonelywolf | NSSCTF 思路&#xff1a; 修开tcache结构&#xff0c;伪造一个0x91的chunk&#xff0c;伪造0x91chunk的数量&#xff08;填满tcache&#xff09;&#xff0c;再将其释放free进入unsortedb…

Linux中,MySQL数据库基础

21 世纪&#xff0c;人类迈入了“信息爆炸时代”&#xff0c;大量的数据、信息在不断产生&#xff0c;伴随而来的就是如何安全、有效地存储、检索和管理它们。对数据的有效存储、高效访问、方便共享和安全控制已经成为信息时代亟待解决的问题。 数据库简介 使用数据库的必要性…

MATLAB--文件操作相关指令

文章目录 文件操作相关指令前言 M文件创建MATLAB文件操作指令MATLAB文件流控制 文件操作相关指令 前言 记录一下M文件创建、操作、获取信息等相关资料。   MATLAB的M文件是用来代替MATLAB命令行窗口输入指令的文件。因此所有的MATLAB指令都可以再MATLAB的M文件中调用. M文件…

算法力扣刷题记录 五十七【236. 二叉树的最近公共祖先】和【235. 二叉搜索树的最近公共祖先】

前言 公共祖先解决。二叉树和二叉搜索树条件下的最近公共祖先。 二叉树篇继续。 一、【236. 二叉树的最近公共祖先】题目阅读 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff…

Spring Bean介绍

目录 1.什么是bean 2.获取bean 3.bean的作用域 4.第三方bean 5.Bean的生命周期 6.Bean的种类 7.为什么使用Bean&#xff1f; 1.什么是bean Bean是Java世界中的一种组件&#xff0c;用于封装数据和逻辑&#xff0c;以便在应用程序中重用和维护。它不仅可以装在数据&#x…

Redis哨兵模式实践

本次环境为Centos7.6&#xff0c;redis-7.0.4 1&#xff1a;主备模式&#xff1a;即主节点的数据自动同步到从节点&#xff0c;但当主节点挂了&#xff0c;从节点需要手动设置为主节点&#xff0c;比较麻烦。 2&#xff1a;哨兵模式&#xff1a;当主节点挂了&#xff0c;自动投…

PCL-基于SAC_IA和NDT结合的点云配准算法

一、原理概述1.点云配准流程图2.快速点特征直方图FPFH3.采样一致性SAC_IA粗配准4.正态分布变换NDT精配准 二、实验代码三、实验结果四、总结五、参考 一、原理概述 1.点云配准流程图 2.快速点特征直方图FPFH 快速点特征直方图&#xff08;Fast Point Feature Histogram&#…

Oracle SQL:了解执行计划和性能调优

查询优化类似于制作完美食谱的艺术——它需要对成分&#xff08;数据&#xff09;、厨房&#xff08;数据库系统&#xff09;和使用的技术&#xff08;查询优化器&#xff09;有深入的了解。每个数据库系统都有自己的处理和运行 SQL 查询的方式&#xff0c;“解释”计划向我们展…

Mysql注意事项(一)

Mysql注意事项&#xff08;一&#xff09; 最近回顾了一下MySQL&#xff0c;发现了一些MySQL需要注意的事项&#xff0c;同时也作为学习笔记&#xff0c;记录下来。–2020年05月13日 1、通配符* 检索所有的列。 不建议使用 通常&#xff0c;除非你确定需要表中的每个列&am…

每日刷题记录(codetop版)

7.21 7.22 7.23 复习7.21和7.22

每日OJ_牛客DD1 连续最大和

目录 牛客DD1 连续最大和 解析代码 牛客DD1 连续最大和 连续最大和_牛客题霸_牛客网 解析代码 本题是一个经典的动规问题&#xff0c;简称dp问题&#xff0c;但这个问题是非常简单的dp问题&#xff0c;而且经常会考察&#xff0c;所以一定要把这个题做会。本题题意很简单&am…

探寻安全新时代:叉车AI智能影像防撞系统,守护生命之光

在繁忙的工业现场&#xff0c;叉车司机常常面临着视线受阻的困境&#xff0c;那些被货物遮挡的盲区&#xff0c;仿佛隐藏着无法预知的危险。然而&#xff0c;这样的隐患在一次惨痛的事故中暴露无遗&#xff0c;一名无辜的行人因叉车司机的视线受阻而不幸被撞身亡。这起悲剧让我…

机械设计基础B(学习笔记)

绪论 机构&#xff1a;是一些具备各自特点的和具有确定的相对运动的基本组合的统称。 组成机构的各个相对运动部分称为构件。构件作为运动单元&#xff0c;它可以是单一的整体&#xff0c;也可以是由几个最基本的事物&#xff08;通常称为零件&#xff09;组成的刚性结构。 构件…

python·数据分析基础知识

numpy 一个数值计算包 python列表与numpy矩阵区别 python中修改列表元素和列表相加 for循环 &#xff1a;[x1 for x in a] 多个元素需要用zip捆绑&#xff1a;[xy for(x,y) in zip(a,b)] numpy矩阵自动进行相应元素计算 np.array()1各元素1 ab各元素相加 a*b矩阵相乘或者是…

爬虫学习4:爬取王者荣耀技能信息

爬虫&#xff1a;爬取王者荣耀技能信息&#xff08;代码和代码流程&#xff09; 代码 # 王者荣耀英雄信息获取 import time from selenium import webdriver from selenium.webdriver.common.by import By if __name__ __main__:fp open("./honorKing.txt", "…

C++的UI框架和开源项目介绍

文章目录 1.QT2.wxWidgets3.Dear ImGui 1.QT QT的开源项目&#xff1a;QGIS&#xff08;地理信息系统&#xff09; https://github.com/qgis/QGIS?tabreadme-ov-file 2.wxWidgets wxWidgets的开源项目&#xff1a;filezilla https://svn.filezilla-project.org/svn/ wxWidg…

Matplotlib折线图绘制秘籍:让你的数据线条比过山车还刺激!

1. Matplotlib_折线图 折线图&#xff08;line chart&#xff09;是我们日常工作中经常使用的一种图表&#xff0c;它可以直观的反应数据的变化趋势 # 导包 import numpy as np import pandas as pd import matplotlib.pyplot as plt# 如果浏览器不显示图片&#xff0c;就需要…

面试场景题系列--(1)如果系统的 QPS 突然提升 10 倍该怎么设计?--xunznux

1. 如果系统的 QPS 突然提升 10 倍该怎么设计&#xff1f; 1.1 硬件的扩展微服务的拆分 如果所有的业务包括交易系统、会员信息、库存、商品等等都夹杂在一起&#xff0c;当流量一旦起来之后&#xff0c;单体架构的问题就暴露出来了&#xff0c;机器挂了所有的业务就全部无法…