第四章 PX4-Pixhawk-MPU6000传感器驱动解析

2023-05-16

第四章MPU6000传感器驱动解析

         Mpu6000是一个3轴加速度和3轴陀螺仪传感器,这一章节我们将对MPU6000这个传感器进行解析,依照这个解析步骤同样可以对L3GD203轴陀螺仪)、HMC58833轴磁力计)、MS5611(气压高度计)程序进行阅读理解,应为这几个传感器同样都是采用SPI协议,这个可以查看硬件图,待会我们也会贴出来。

         首先我们当然是找到驱动的入口,这个我们很容易找到驱动的入口就是

这个函数。至于这个函数我们可以查看到初始化这个几个参数是这个,这里我们对他进行分析一下,busid就是说明是哪个总线协议,可以看到这个枚举型是有5个数的都是关于内部SPI,外部SPI,内部IIC,外部IIC,这里的外部内部的意思是板上的传感器和自己外加的传感器,这个要理解清楚哦。Device_type是设备类型,external就是定义是内部V2硬件的传感器还自己外接的传感器,旋转角度其实就是跟传感器的摆放位置相关,加速度范围是8G,即为+-4G


然后就是这个函数了

这个其实就是解析了启动传感器的判断了,还记得


这些就是在这里解析了,这里说明一下前面是对照找这个参数,然后接个冒号就是找这个参数值,比如我们来对照mpu6000 –X –R 4 start这个就是首先解析到-X就是

然后找到-R 然后找到这个参数后是4就是rotation4也就是yaw旋转180°,接着获取start参数

,这个介绍完了,我们来查找我们V2硬件的mpu6000的启动吧。我们找到rc.sensors中有

这里就是启动了,如果不知道怎么找,那就去仔细阅读RCS那一章节了,然后再仔细阅读rc.sensors了。这里可以看得出不会进入该函数了

接着进入到函数

这里的参数是,这里我不妨贴出来这个函数实际运行的就是进入到start中这里就会对驱动去循环查询然后运行

,这里我们不对这个做详细说明,有兴趣的可以去看看,这里我们知道V2的硬件板就是使用的内部板载传感器。然后我们对start_bus说明,这个函数是启动总线协议了。这些个参数是进入函数

这里就是对函数协议的控制了。这里我们先找到设备总线的选择,针对MPU6000我们选择的是

看到没这里我们选择的是


这个函数哦bus.busnum这个参数我们到


中去找发现是

device_type参数是6000external还是0

         进入到函数MUP6000_SPI_interfaceexternal=0我们进入到else中,由于我们在板子的配置中并没有定义PX4_SPIDEV_ICM,所以cs=PX4_SPIDEV_MPU=4。现在进入到

注:,这里是一个构造函数,C++中的new其实就是类似于C语言中的初始化。


看到没这里就开始对SPI的配置进行说明了,这里SPI的进行选择了哦,这里的bus=1了哦注意。Device变成了cs=4哦,然后就是模式和速率了。


这里对SPI的选择模式和配置就完成了。然后回到mpu6000.cpp中的下一步就是

初始化协议了,这里用到了虚函数的概念哦,这里不懂也没关系,最好是了解一下这些概念,应为这个系统会有很多都用到了虚函数,这里告诉你这个虚函数的就是SPI的初始化了。这里我们要找的就是SPI.ccp了,你可以查看到SPI的初始化了。这里我们就与刚才协议的驱动对接上了,

刚才说到这里的_bus=1,返回的值_dev=1,_device=cs=4


追踪到这里就是这个函数了,至于为什么开始是SPI_SELECT到后面变成了STM32_spi1selectspi驱动篇去看看。这里选择的执行时


,好了我们在来看看硬件图,看到没现在都对应起来了吧,spi选择的是SPI1cs选择的是PC2引脚


再回到mpu6000.cpp中接下来就该

这里就开始对mpu6000的相关设置和配置,这里我们不对它进行细说这里还是一个构造函数,只是对相关数据进行初始化。这里面有很多,就有对路径注册,滤波器初始化,参数的初始化等等。这里开始进入到驱动的数据读取端了。这里的初始化是重载了器件的init函数,也就是

这个函数就需要仔细去阅读了,这里主要是去MPUID 

,然后设备初始化开辟数据空间

进行复位相关配置等等,这里需要配合MPU6000的寄存器手册去看,这里不详细说明,如果有需要大家提出来,本人也是可以出一个文档进行说明,来教大家如何查看数据手册和编写底层驱动的。

这里的重头函数,这里面就有了数据的读取了。进入该函数,首先进行定义数据,真正的读取是函数

这个函数是read,至于为什么是read函数就需要有一点linux的常识了,这里的read是一个虚函数。这里后面到时候在做解释。

这里就开始组合数据帧了,得到原始的加速度,温度和陀螺仪数据。

得到数据后对这些数据的处理也比价多,有数据非0判断、数据交换、旋转、数据偏移纠正滤波。这些里面就涉及到了算法哦,比如原始数据的滤波器就用到了二阶滤波。算法这块我们暂时不去细讲,目前的文档比较适合应用,到时候也会出一些文档适合真正的高手,就是算法这块了。

数据相关处理完了之后就是nuttx 机制出马了需要发布数据。就是通过

这里也说一下,sensor_accelsensor_gyro这两个就是主题的名字,至于这个主题就是

这个文件夹下的.msg文件的名字了。打开这些文件你可以看到


这里面就有对数据的说明了,这里说一下.msg文件只是一个过渡文件,最终会通过系统工具转换为.h文件。如果自己要写新的主题数据也是一样的编写一个.msg文件然后再目录下的Cmakelists文件加入新的.msg文件就Ok了。在使用的时候加入头文件(对应的文件.h>就行了。这个生成的h文件是在目录下。发布数据后就差不多完事了。然后就是启动自动收集数据了。


。这样MPU6000的数据和驱动就打通了哦。

这里对nuttx的相关函数进行说明一下,自己去理解哦,这个并不难,也没必要知道函数怎么来的,只需要知道函数功能和使用就行了。

int poll(struct pollfd fds[], nfds_t nfds, int timeout)

功能:监控文件描述符(多个);

说明:timemout=0,poll()函数立即返回而不阻塞;timeout=INFTIM(-1),poll()会一直阻塞下去,直到检测到return > 0

参数:

    fds:struct pollfd结构类型的数组;

    nfds:用于标记数组fds中的结构体元素的总数量;

    timeout:poll函数调用阻塞的时间,单位:毫秒;

返回值:

    >0:数组fds中准备好读、写或出错状态的那些socket描述符的总数量;

    ==0:poll()函数会阻塞timeout所指定的毫秒时间长度之后返回;

    -1:poll函数调用失败;同时会自动设置全局变量errno

int orb_subscribe(const struct orb_metadata *meta)

功能:订阅主题(topic;

说明:即使订阅的主题没有被公告,但是也能订阅成功;但是在这种情况下,却得不到数据,直到主题被公告;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

返回值:

    错误则返回ERROR;成功则返回一个可以读取数据、更新话题的句柄;如果待订阅的主题没有定义或声明则会返回-1,然后会将errno赋值为ENOENT;

eg:

    int fd = orb_subscribe(ORB_ID(topicName));

int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)

功能:从订阅的主题中获取数据并将数据保存到buffer中;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

    handle:订阅主题返回的句柄;

    buffer:从主题中获取的数据;

返回值:

    返回OK表示获取数据成功,错误返回ERROR;否则则有根据的去设置errno;

eg:

    struct sensor_combined_s raw;

    orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw);

orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)

功能:公告发布者的主题;

说明:在发布主题之前是必须的;否则订阅者虽然能订阅,但是得不到数据;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

    data:指向一个已被初始化,发布者要发布的数据存储变量的指针;

返回值:错误则返回ERROR;成功则返回一个可以发布主题的句柄;如果待发布的主题没有定义或声明则会返回-1,然后会将errno赋值为ENOENT;

eg:

    struct vehicle_attitude_s att;

    memset(&att, 0, sizeof(att));

    int att_pub_fd = orb_advertise(ORB_ID(vehicle_attitude), &att);

int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)

功能:发布新数据到主题;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

    handle:orb_advertise函数返回的句柄;

    data:指向待发布数据的指针;

返回值:OK表示成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    orb_publish(ORB_ID(vehicle_attitude), att_pub_fd, &att);

int orb_set_interval(int handle, unsigned interval)

功能:设置订阅的最小时间间隔;

说明:如果设置了,则在这间隔内发布的数据将订阅不到;需要注意的是,设置后,第一次的数据订阅还是由起初设置的频率来获取,

参数:

    handle:orb_subscribe函数返回的句柄;

    interval:间隔时间,单位ms;

返回值:OK表示成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    orb_set_interval(sensor_sub_fd, 1000);

orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)

功能:设备/驱动器的多个实例实现公告,利用此函数可以注册多个类似的驱动程序;

说明:例如在飞行器中有多个相同的传感器,那他们的数据类型则类似,不必要注册几个不同的话题;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

    data:指向一个已被初始化,发布者要发布的数据存储变量的指针;

    instance:整型指针,指向实例的ID(从0开始);

    priority:实例的优先级。如果用户订阅多个实例,优先级的设定可以使用户使用优先级高的最优数据源;

返回值:

    错误则返回ERROR;成功则返回一个可以发布主题的句柄;如果待发布的主题没有定义或声明则会返回-1,然后会将errno赋值为ENOENT;

eg:

    struct orb_test t;

    t.val = 0;

    int instance0;

    orb_advert_t pfd0 = orb_advertise_multi(ORB_ID(orb_multitest), &t, &instance0, ORB_PRIO_MAX);

int orb_subscribe_multi(const struct orb_metadata *meta, unsigned instance)

功能:订阅主题(topic;

说明:通过实例的ID索引来确定是主题的哪个实例;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

    instance:主题实例ID;实例ID=0orb_subscribe()实现相同;

返回值:

    错误则返回ERROR;成功则返回一个可以读取数据、更新话题的句柄;如果待订阅的主题没有定义或声明则会返回-1,然后会将errno赋值为ENOENT;

eg:

    int sfd1 = orb_subscribe_multi(ORB_ID(orb_multitest), 1);

int orb_unsubscribe(int handle)

功能:取消订阅主题;

参数:

    handle:主题句柄;

返回值:

    OK表示成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    ret = orb_unsubscribe(handle);

int orb_check(int handle, bool *updated)

功能:订阅者可以用来检查一个主题在发布者上一次更新数据后,有没有订阅者调用过ob_copy来接收、处理过;

说明:如果主题在在被公告前就有人订阅,那么这个API将返回“not-updated”直到主题被公告。可以不用poll,只用这个函数实现数据的获取。

参数:

    handle:主题句柄;

    updated:如果当最后一次更新的数据被获取了,检测到并设置updatedture;

返回值:

    OK表示检测成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    if (PX4_OK != orb_check(sfd, &updated)) {

        return printf("check(1) failed");

    }

    if (updated) {

        return printf("spurious updated flag");

    }

    //or

    bool updated;

    struct random_integer_data rd;

   

    orb_check(topic_handle, &updated);

    if (updated) {

       

        orb_copy(ORB_ID(random_integer), topic_handle, &rd);

        printf("Random integer is now %d\n", rd.r);

    }

int orb_stat(int handle, uint64_t *time)

功能:订阅者可以用来检查一个主题最后的发布时间;

参数:

    handle:主题句柄;

    time:存放主题最后发布的时间;0表示该主题没有发布或公告;

返回值:

    OK表示检测成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    ret = orb_stat(handle,time);

int orb_exists(const struct orb_metadata *meta, int instance)

功能:检测一个主题是否存在;

参数:

    meta:uORB元对象,可以认为是主题id,一般是通过ORB_ID(主题名)来赋值;

    instance:ORB 实例ID;

返回值:

    OK表示检测成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    ret = orb_exists(ORB_ID(vehicle_attitude),0);

int orb_priority(int handle, int *priority)

功能:获取主题优先级别;

参数:

    handle:主题句柄;

    priority:存放获取的优先级别;

返回值:

    OK表示检测成功;错误返回ERROR;否则则有根据的去设置errno;

eg:

    ret = orb_priority(handle,&priority);

数据流程使用如下图:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第四章 PX4-Pixhawk-MPU6000传感器驱动解析 的相关文章

随机推荐

  • VLC加载插件失败原因及解决

    最近做视频播放的程序 xff0c 找到了VLC开源库 在windows 43 vs2013 43 QT5 3环境下进行调试 出现了在调用libvlc new时提示不能找到插件 加载libvlc失败的问题 原因及解决方法如下 xff1a 1
  • logcat的使用

    参考链接 log信息级别 以下优先级从上往下排序 xff1a V xff1a verbose 显示全部信息 最低优先级 xff0c 对应Log v String tag String msg D xff1a debug 显示调试信息 xff
  • 物联网架构实例—解决Linux(Ubuntu)服务器最大TCP连接数限制

    1 前言 xff1a 在对物联网网关进行压测的时候 xff0c 发现在腾讯云部署网关程序 xff0c 设备接入数量只能达到4000多个长连接 xff0c 之后就再也无法接入终端了 之前在阿里云部署的时候明明可以到达2万左右 xff0c 而且
  • Prometheus从入门到跑路

    1 prometheus框架结构 2 prometheus组件介绍 2 1 Prometheus Server 这是Prometheus的服务端 xff0c 也就是核心 Prometheus本身是一个以进程方式启动 xff0c 之后以多进程
  • ucos-ii学习笔记1 创建任务&&任务调度

    span style font family none font size 12px background color rgb 255 255 255 span span 最近在学习嵌入式系统 xff0c 听说ucos ii是使用最广 xf
  • ucos ii学习笔记2 邮箱&&信息量

    上一篇说了ucos ii的大致运行原理 xff0c 这一篇主要用来说明不同任务之间的数据传递的 有人会说 xff1a 不同任务间的数据传递直接用全局变量不就好了 xff0c 我一开始也有这种疑惑 xff0c 也在简单程序中实验过没什么问题
  • ucos ii学习笔记4 软件定时器

    span span p span style font size 18px span span ucos ii从V2 83版本以后加入了软件定时器 xff0c 软件定时器的最快时钟节拍就等于ucos ii的系统时钟节拍 xff0c 由一个单
  • 时钟源关系初解

    最近发现自己对时钟的各种关系不是很清晰 xff0c 所以在这里初步的顺一下 以STM32F4为例 xff0c 大概都差不多 STM32F4有5个时钟源 xff0c 分别是HSI HSE LSI LSE PLL 从名字上看出HSI和HSE是高
  • up-board

    安装ubuntu16 04 安装board内核 http www eeboard com bbs thread 59222 1 1 html 对管脚的控制 http www eeboard com bbs thread 59257 1 1
  • 【嵌入式软件实习】找实习和电话面试记录与总结

    前言 前一段时间就是非常想找实习 xff0c 这次是接到了一家还算是比较大的公司的面试通知和实习offer 做一下简单的记录给在找实习的大家一个参考吧 主要内容为 xff1a 三连即可提高学习效率0 0 x1f9d1 x1f3fb 作者简介
  • Ubuntu更换apt镜像源

    原文 xff1a Ubuntu更换apt镜像源 在ubuntu中 xff0c 默认使用 ubuntu 的官方源http archive ubuntu com xff0c 但是这个官方源在国内下载的速度太慢 xff0c 甚至只有几十k 于是考
  • JS 闭包 详细说明(教程)

    首先 xff0c 闭包是一个高阶函数 xff0c 高阶函数除了可以接受函数作为参数外 xff0c 还可以把函数作为结果值返回 xff08 不知道高阶函数是啥 xff0c 点击链接 xff09 先通过一个例子来了解一下如何把函数作为结果值返回
  • STVP烧录程序

    STVP介绍 STVD xff1a ST Visual Develop xff0c 可视化开发工具STVP xff1a ST Visual Programmer xff0c 可视化编程工具 xff0c stvp主要打开一些固件 hex s1
  • 传感器标定系列——Kalibr工具

    文章目录 Kalibr介绍安装资源 Kalibr介绍 Kalibr is a toolbox that solves the following calibration problems 多相机标定 Multi Camera Calibra
  • TCP传输图片及多线程

    最终效果图 xff1a 注意 xff1a 图片发送大体流程同 Qt网络编程 TCP IP 一 只是在发送时这里采用 的 数据流QDataStream形式 因为使用摄像进行监控时也是对一帧一帧的图片进 行处理 xff0c 因此掌握了如何用Qt
  • GCC编译过程及基本命令总结

    一 GCC简介 GCC即GNU Compiler Collection xff0c 原本只是针对C语言的编译工具 xff0c 现在已经变成了一个工具集 xff0c 包含了C C 43 43 JAVA等语言的集合体 管理和维护 xff1a 由
  • 第一章 PX4-Pixhawk-程序编译过程解析

    第一章 PX4程序编译过程解析 PX4 是一款软硬件开源的项目 xff0c 目的在于学习和研究 其中也有比较好的编程习惯 xff0c 大家不妨可以学习一下国外牛人的编程习惯 这个项目是苏黎世联邦理工大学的一个实验室搞出来的 该方案是基于 N
  • 第二章 PX4-Pixhawk-RCS启动文件解析

    第二章 PX4 RCS 启动文件解析 RCS 的启动类似于 linux 的 shell 文件 xff0c 如果不知道 shell 文件是什么东西可以理解成是为程序的流程框 xff0c 它是告诉处理器应该怎么样去运行 xff0c 前一章介绍的
  • 第三章 PX4-Pixhawk-SPI底层驱动解析

    第三章 PX4 SPI 底层驱动解析 这一章节我们会对 PX4 的底层驱动进行解析 xff0c 我们这里主要解析的是 SPI 协议 xff0c 因为这个协议是所有传感器的一个协议 xff0c 至于 IIC 和串口就可以类似的读写一下 xff
  • 第四章 PX4-Pixhawk-MPU6000传感器驱动解析

    第四章MPU6000传感器驱动解析 Mpu6000 是一个 3 轴加速度和 3 轴陀螺仪传感器 xff0c 这一章节我们将对 MPU6000 这个传感器进行解析 xff0c 依照这个解析步骤同样可以对 L3GD20 xff08 3 轴陀螺仪