【电子DIY作品】跌倒告警 Ai-M61-32su + MPU6050

[复制链接]
查看1622 | 回复14 | 2023-12-18 11:22:45 | 显示全部楼层 |阅读模式
本帖最后由 lazy 于 2023-12-20 08:55 编辑

设计之初想的是,在不能关照老人与小孩儿的时候,可能会存在老人或小孩儿摔倒的情况。如果摔倒不及时处置可能造成比较严重的伤害。这个小作品主要就是,跌倒提醒的功能,网上也有类似的作品。这里使用Ai-M61-32su复刻一下。如果有跌倒状态,亮红灯,默认绿灯。还可以增加蜂鸣器等。

        摔倒检测算法可以通过检测加速度和角速度的变化来判断物体是否发生了摔倒。在实现MPU6050摔倒检测算法时,首先需要读取MPU6050传感器的原始数据。然后,通过计算加速度和角速度的变化率来判断物体是否摔倒。通常,可以通过设置一个阈值来判断加速度和角速度是否超过了正常范围。如果超过了阈值,则可认为物体发生了摔倒。另外,还可以使用一些机器学习算法来提高摔倒检测的准确性。通过对大量的摔倒和非摔倒状态的数据进行训练,可以建立一个模型来判断物体是否发生了摔倒。这种方法可以更好地适应不同物体和环境的情况,并提高摔倒检测的灵敏度和准确性。

_cgi-bin_mmwebwx-bin_webwxgetmsgimg__&MsgID=5016448173872425861&skey=@crypt_3423.jpg


下面对设备所使用的主要硬件进行介绍
对于 MPU6050网上有很多博主的介绍,这里【转载】知乎鱼芯工作室的文章

MPU6050简介 - 鱼芯工作室的文章 - 知乎
https://zhuanlan.zhihu.com/p/346764320

内容如下,可以更好的理解 MPU6050
一、MPU6050简介
MPU-60X0 是全球首例9 轴运动处理传感器。它集成了3 轴MEMS 陀螺仪,3 轴MEMS加速度计,以及一个可扩展的数字运动处理器DMP(Digital Motion Processor),可用I2C接口连接一个第三方的数字传感器,比如磁力计。扩展之后就可以通过其I2C 或SPI 接口输出一个9 轴的信号(SPI 接口仅在MPU-6000 可用)。MPU-60X0 也可以通过其I2C 接口连接非惯性的数字传感器,比如压力传感器。
MPU-60X0 对陀螺仪和加速度计分别用了三个16 位的ADC(0~65535),将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为±250,±500,±1000,±2000°/秒(dps),加速度计可测范围为±2,±4,±8,±16g。
芯片尺寸4×4×0.9mm,采用QFN 封装(无引线方形封装),可承受最大10000g 的冲击,并有可编程的低通滤波器。
MPU6050的内部框图如下图所示:
v2-84bdb3f880952ac3f0514107afce0fd7_720w.png
其中,需要了解的引脚有:SCL和 SDA是连接MCU的 IIC接口,MCU通过这个IIC 接口来控制MPU6050,另外还有一个 IIC 接口:AUX_CL和AUX_DA ,这个接口可用来连外部从设备比如磁力计,这样就可以组成一个九轴传感器。VLOGIC是IO口电压,该引脚最低可以到1.8V电压, 我们一般直接连VDD即可。AD0是从IIC 接口(接 MCU)的地址控制引脚,该引脚控制的是IIC 地址的最低位。如果接 GND ,则 MPU6050的IIC地址是:0X68,如果接VDD,则是0X69。需要注意的是:这里的地址0x68和0x69是不包含用于数据传输的最低位的,因此并不是八位数据,如0x68表示的是110 1000,0x69表示的则是110 1001,通常最低位用于表示IIC主机的读取数据/写数据模式。self test为自检,自检的作用是可用来测试传感器的机械和电气结构。也就是说通过自检来测试芯片是否损坏。自检启动后,电路会使传感器工作并且产生输出信号。关于自检的具体说明,官方芯片手册里有详细描述。如下:
  • Gyroscope Self-Test
    When self-test is activated, the on-board electronics will actuate the appropriate sensor. This actuation will move the sensor’s proof masses over a distance equivalent to a pre-defined Coriolis force. This proof mass displacement results in a change in the sensor output, which is reflected in the output signal. The output signal is used to observe the self-test response.
    The self-test response is defined as follows:
    Self-test response = Sensor output with self-test enabled – Sensor output without self-test enabledThe self-test limits for each gyroscope axis is provided in the electrical characteristics tables of the MPU-6000/MPU-6050 Product Specification document. When the value of the self-test response is within the min/max limits of the product specification, the part has passed self test. When the self-test response exceeds the min/max values specified in the document, the part is deemed to have failed self-test.
  • Accelerometer Self-Test
    When self-test is activated, the on-board electronics will actuate the appropriate sensor. This actuation simulates an external force. The actuated sensor, in turn, will produce a corresponding output signal. The output signal is used to observe the self-test response.
    The self-test response is defined as follows:
    Self-test response = Sensor output with self-test enabled – Sensor output without self-test enabledThe self-test limits for each accelerometer axis is provided in the electrical characteristics tables of the MPU-6000/MPU-6050 Product Specification document. When the value of the self-test response is within the min/max limits of the product specification, the part has passed self test. When the self-test response exceeds the min/max values specified in the document, the part is deemed to have failed self-test.
二、MPU6050相关寄存器
MPU6050官方的寄存器手册上共介绍了40个寄存器的内容和功能,在此我只选取一些常用的和重要的寄存器作为了解。
1.采样分频寄存器 Sample Rate Divider
v2-c51ecf12063a4c278ff7dfeef545659e_720w.png

说明:该寄存器指定陀螺仪输出速率的分频器,用于为MPU-60X0生成采样速率。
传感器寄存器输出,FIFO输出,DMP采样,运动检测,静止检测和自由落体检测都基于这个采样频率。
采样频率=陀螺仪输出频率/(1+SMPLRT_DIV)
当 DLPF(数字低通滤波器,见寄存器Configuration)禁用时(DLPF_CFG=0 or 7),陀螺输出频率=8kHz;当 DLPF 使能,陀螺仪输出频率=1KHz。注意:加速度计输出频率为 1KHz。这意味着,当采样频率大于1KHZ时,同个加速度计采样得到的数据,可能不止一次输出到FIFO、DMP、传感器寄存器。

2.配置寄存器 Configuration
屏幕截图 2023-12-18 105733.png
说明:该寄存器为陀螺仪和加速度计配置外部帧同步(FSYNC) 管脚的采样和数字低通滤波(DLPF)设置。
其中,数字低通滤波器DLPF由DLPF_CFG配置。根据下表所示的DLPF_CFG值对加速度计和陀螺仪进行滤波。

v2-ad78f1fe43d6e16bdd783a2d11289c1c_720w.png
其中,FS为陀螺仪输出频率。SMPLRT_DIV由预设定的采样频率根据上述的公式计算得出。一般情况下,DPLF滤波频率为采样频率的一半,如设定采样频率为50Hz,由表可知当FS为1kHz,SMPLRT_DIV的值为1000/50-1=19。
3.陀螺仪配置寄存器 Gyroscope Configuration
v2-7008e45c6b032fb15fe5f90e8e4933e0_720w.png


说明:该寄存器是用来触发陀螺仪自检和配置陀螺仪的满量程范围。
其中,XG_ST、YG_ST、ZG_ST分别用来设置陀螺仪X轴、Y轴、Z轴自检,置0则不触发自检。FS_SEL[1:0]用于设置陀螺仪的满量程,如下表:

v2-079becc8c0e7b492b62dd1d91df2e414_720w.png


我们一般设置为3,即满量程为±2000°/s,由于采用16位ADC即0-65536,则灵敏度G=65536/4000=16.4LSB/(°/s),LSB表示最低有效位,即1°/s对应的数字量为16.4。最终即可将陀螺仪输出的数字量数据转化为角速度。

4.加速度计配置寄存器 Accelerometer Configuration v2-eb872f558610a4f2f427916419a66af1_720w.png
说明:该寄存器是用来触发加速度计自检和配置加速度计的满量程范围。同时这个寄存器也可以用于配置数字高通滤波器(DHPF)。
其中,XA_ST、YA_ST、ZA_ST分别用来设置加速度计X轴、Y轴、Z轴自检,置0则不触发自检。AFS_SEL[1:0]用于选择加速度计的满量程范围,如下表:]

v2-9e24c4d6ddb4e5259fcac1ded0d8a8c1_720w.png

我们一般设置为0,即满量程为±2g,由于采用16位ADC即0-65536,则灵敏度G=65536/4=16384LSB/(g),LSB表示最低有效位,即1g对应的数字量为16384。最终即可将加速度计输出的数字量数据转化为加速度。

5.加速度计测量值寄存器 Accelerometer Measurements
屏幕截图 2023-12-18 110037.png
说明:该寄存器存储最近加速度计的测量值。加速度计根据采样频率(由采样分频寄存器寄存器设定 )写入到这些寄存器。即采样频率为50Hz,写入数据的时间间隔为0.02s。加速度计测量值寄存器和温度测量值寄存器,陀螺仪测量值寄存器,外部传感器数据寄存器都是由两组寄存器构成:一个内部寄存器集和一个用于用户读取的寄存器集。
加速度计传感器的内部寄存器集合里的数据根据采样频率更新。以此同时,每当串行接口处于闲置状态,面向用户的读取寄存器集合会复制内部寄存器集合的数据值。这保证了突发读取时传感器寄存器可以读到相同的采样时刻的测量值。需要注意的是,如果没有突发读取,则用户负责通过检查数据就绪中断(Data Ready interrupt)来确保瞬时的一组单字节读取对应于单字节的采样数据。
参数:
ACCEL_XOUT :
由 2部分组成的 16位数值存储最近X 轴加速度计的测量值。
ACCEL_YOUT :
由 2部分组成的 16位数值存储最近Y 轴加速度计的测量值。
ACCEL_ZOUT :由 2部分组成的 16位数值存储最近Z 轴加速度计的测量值。
6.陀螺仪测量值寄存器 Gyroscope Measurements
v2-624c740b344993be98aa4377be2b1067_720w.png

说明:该寄存器存储最近加陀螺仪的测量值。大致构成与加速度计测量值寄存器相同,此处便不做叙述。参数分别为:GYRO_XOUT 、GYRO_YOUT 、GYRO_ZOUT 。
7.电源管理寄存器1 Power Management 1 v2-e1e72ed3c707d05a42df9c90b2d889bd_720w.png
说明:该寄存器允许用户配置电源模式和时钟源,还提供了复位整个设备和禁用温度传感器的位。当置SLEEP位为1时,MPU-60X0 可以进入低功耗睡眠模式。当SLEEP位禁用且 CYCLE位置 1时,MPU-60X0进入循环模式(CycleMode)。在循环模式下,设备在休眠模式和唤醒之间循环,以LP_WAKE_CTRL(由电源管理2寄存器配置)确定的速率从active sensors(此处不知如何翻译)获取单个数据样本。
该寄存器的最低三位用于设置系统的时钟源选择,默认值是0(内部8M RC振荡),不过一般设置为1,选择x轴陀螺PLL作为时钟源,以获得更高精度的时钟。同时,使能角速度传感器和加速度传感器,这两个操作通过电源管理寄存器2配置,设置对应位为0即可开启。
附英文手册原文片段:Upon power up, the MPU-60X0 clock source defaults to
the internal oscillator. However, it is highly recommended that the device be configured to use one of the gyroscopes (or an ext ernal clock source) as the clock reference for improved stability.
v2-3eff3cad2ae43a6d6608c3be8e42c538_720w.png

其他参数:
DEVICE_RESET
该位置 1,重启内部寄存器到默认值。复位完成后该位自动清0。
TEMP_DIS该位置 1,禁用温度传感器。
8.电源管理寄存器2 Power Management 2
v2-d2597159e93a8f546d248ac8a927e0f5_720w.png

说明:该寄存器允许用户在加速度计低功耗模式下配置唤醒频率。也允许用户让加速度计和陀螺仪的个别轴进入待机模式。
只让MPU-60X0的加速度计进入低功耗模式的步骤如下:
1.置 CYCLE位为 1
2.置 SLEEP位为 1
3.置 TEMP_DIS位为 1
4.置 STBY_XG,STBY_YG,STBY_ZG位为 1
在这种模式下,设备会关闭除了主 I2C接口外其他所有设备,加速度计只在固定的间隔唤醒并测量一次。唤醒的频率可以通过配置 LP_WAKE_CTRL实现如下:

v2-23025216044893e80cf4933930f8fa56_720w.png

参数:
LP_WAKE_CTRL :
2位无符号数值。指定加速度计在低功耗模式下的唤醒频率。
STBY_XA :
该位置 1,加速度计的 X轴进入待机模式。
STBY_YA :
该位置 1,加速度计的 Y轴进入待机模式。
STBY_ZA :
该位置 1,加速度计的 Z轴进入待机模式。
STBY_XG :
该位置 1,陀螺仪的 X轴进入待机模式。
STBY_YG :
该位置 1,陀螺仪的 Y轴进入待机模式。
STBY_ZG :该位置 1,陀螺仪的 Z轴进入待机模式。



对于MPU 6050 进行了简单的介绍,也对这个模块有了一些了解。
mpu6050.h

  1. #ifndef __MPU6050_H
  2. #define __MPU6050_H

  3. #include <stdlib.h>
  4. #include <stdbool.h>
  5. #include <stdarg.h>
  6. #include <stddef.h>
  7. #include <string.h>
  8. #include <math.h>
  9. #include <stdint.h>        //Added for uint_t
  10. #include <stdio.h>
  11. #include "bflb_mtimer.h"


  12. #define MPU6050_ADDRESS_AD0_LOW     0x68 // address pin low (GND), default for InvenSense evaluation board
  13. #define MPU6050_ADDRESS_AD0_HIGH    0x69 // address pin high (VCC)
  14. #define MPU6050_DEFAULT_ADDRESS     MPU6050_ADDRESS_AD0_LOW

  15. #define MPU6050_RA_XG_OFFS_TC       0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
  16. #define MPU6050_RA_YG_OFFS_TC       0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
  17. #define MPU6050_RA_ZG_OFFS_TC       0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
  18. #define MPU6050_RA_X_FINE_GAIN      0x03 //[7:0] X_FINE_GAIN
  19. #define MPU6050_RA_Y_FINE_GAIN      0x04 //[7:0] Y_FINE_GAIN
  20. #define MPU6050_RA_Z_FINE_GAIN      0x05 //[7:0] Z_FINE_GAIN
  21. #define MPU6050_RA_XA_OFFS_H        0x06 //[15:0] XA_OFFS
  22. #define MPU6050_RA_XA_OFFS_L_TC     0x07
  23. #define MPU6050_RA_YA_OFFS_H        0x08 //[15:0] YA_OFFS
  24. #define MPU6050_RA_YA_OFFS_L_TC     0x09
  25. #define MPU6050_RA_ZA_OFFS_H        0x0A //[15:0] ZA_OFFS
  26. #define MPU6050_RA_ZA_OFFS_L_TC     0x0B
  27. #define MPU6050_RA_XG_OFFS_USRH     0x13 //[15:0] XG_OFFS_USR
  28. #define MPU6050_RA_XG_OFFS_USRL     0x14
  29. #define MPU6050_RA_YG_OFFS_USRH     0x15 //[15:0] YG_OFFS_USR
  30. #define MPU6050_RA_YG_OFFS_USRL     0x16
  31. #define MPU6050_RA_ZG_OFFS_USRH     0x17 //[15:0] ZG_OFFS_USR
  32. #define MPU6050_RA_ZG_OFFS_USRL     0x18
  33. #define MPU6050_RA_SMPLRT_DIV       0x19
  34. #define MPU6050_RA_CONFIG           0x1A
  35. #define MPU6050_RA_GYRO_CONFIG      0x1B
  36. #define MPU6050_RA_ACCEL_CONFIG     0x1C
  37. #define MPU6050_RA_FF_THR           0x1D
  38. #define MPU6050_RA_FF_DUR           0x1E
  39. #define MPU6050_RA_MOT_THR          0x1F
  40. #define MPU6050_RA_MOT_DUR          0x20
  41. #define MPU6050_RA_ZRMOT_THR        0x21
  42. #define MPU6050_RA_ZRMOT_DUR        0x22
  43. #define MPU6050_RA_FIFO_EN          0x23
  44. #define MPU6050_RA_I2C_MST_CTRL     0x24
  45. #define MPU6050_RA_I2C_SLV0_ADDR    0x25
  46. #define MPU6050_RA_I2C_SLV0_REG     0x26
  47. #define MPU6050_RA_I2C_SLV0_CTRL    0x27
  48. #define MPU6050_RA_I2C_SLV1_ADDR    0x28
  49. #define MPU6050_RA_I2C_SLV1_REG     0x29
  50. #define MPU6050_RA_I2C_SLV1_CTRL    0x2A
  51. #define MPU6050_RA_I2C_SLV2_ADDR    0x2B
  52. #define MPU6050_RA_I2C_SLV2_REG     0x2C
  53. #define MPU6050_RA_I2C_SLV2_CTRL    0x2D
  54. #define MPU6050_RA_I2C_SLV3_ADDR    0x2E
  55. #define MPU6050_RA_I2C_SLV3_REG     0x2F
  56. #define MPU6050_RA_I2C_SLV3_CTRL    0x30
  57. #define MPU6050_RA_I2C_SLV4_ADDR    0x31
  58. #define MPU6050_RA_I2C_SLV4_REG     0x32
  59. #define MPU6050_RA_I2C_SLV4_DO      0x33
  60. #define MPU6050_RA_I2C_SLV4_CTRL    0x34
  61. #define MPU6050_RA_I2C_SLV4_DI      0x35
  62. #define MPU6050_RA_I2C_MST_STATUS   0x36
  63. #define MPU6050_RA_INT_PIN_CFG      0x37
  64. #define MPU6050_RA_INT_ENABLE       0x38
  65. #define MPU6050_RA_DMP_INT_STATUS   0x39
  66. #define MPU6050_RA_INT_STATUS       0x3A
  67. #define MPU6050_RA_ACCEL_XOUT_H     0x3B
  68. #define MPU6050_RA_ACCEL_XOUT_L     0x3C
  69. #define MPU6050_RA_ACCEL_YOUT_H     0x3D
  70. #define MPU6050_RA_ACCEL_YOUT_L     0x3E
  71. #define MPU6050_RA_ACCEL_ZOUT_H     0x3F
  72. #define MPU6050_RA_ACCEL_ZOUT_L     0x40
  73. #define MPU6050_RA_TEMP_OUT_H       0x41
  74. #define MPU6050_RA_TEMP_OUT_L       0x42
  75. #define MPU6050_RA_GYRO_XOUT_H      0x43
  76. #define MPU6050_RA_GYRO_XOUT_L      0x44
  77. #define MPU6050_RA_GYRO_YOUT_H      0x45
  78. #define MPU6050_RA_GYRO_YOUT_L      0x46
  79. #define MPU6050_RA_GYRO_ZOUT_H      0x47
  80. #define MPU6050_RA_GYRO_ZOUT_L      0x48
  81. #define MPU6050_RA_EXT_SENS_DATA_00 0x49
  82. #define MPU6050_RA_EXT_SENS_DATA_01 0x4A
  83. #define MPU6050_RA_EXT_SENS_DATA_02 0x4B
  84. #define MPU6050_RA_EXT_SENS_DATA_03 0x4C
  85. #define MPU6050_RA_EXT_SENS_DATA_04 0x4D
  86. #define MPU6050_RA_EXT_SENS_DATA_05 0x4E
  87. #define MPU6050_RA_EXT_SENS_DATA_06 0x4F
  88. #define MPU6050_RA_EXT_SENS_DATA_07 0x50
  89. #define MPU6050_RA_EXT_SENS_DATA_08 0x51
  90. #define MPU6050_RA_EXT_SENS_DATA_09 0x52
  91. #define MPU6050_RA_EXT_SENS_DATA_10 0x53
  92. #define MPU6050_RA_EXT_SENS_DATA_11 0x54
  93. #define MPU6050_RA_EXT_SENS_DATA_12 0x55
  94. #define MPU6050_RA_EXT_SENS_DATA_13 0x56
  95. #define MPU6050_RA_EXT_SENS_DATA_14 0x57
  96. #define MPU6050_RA_EXT_SENS_DATA_15 0x58
  97. #define MPU6050_RA_EXT_SENS_DATA_16 0x59
  98. #define MPU6050_RA_EXT_SENS_DATA_17 0x5A
  99. #define MPU6050_RA_EXT_SENS_DATA_18 0x5B
  100. #define MPU6050_RA_EXT_SENS_DATA_19 0x5C
  101. #define MPU6050_RA_EXT_SENS_DATA_20 0x5D
  102. #define MPU6050_RA_EXT_SENS_DATA_21 0x5E
  103. #define MPU6050_RA_EXT_SENS_DATA_22 0x5F
  104. #define MPU6050_RA_EXT_SENS_DATA_23 0x60
  105. #define MPU6050_RA_MOT_DETECT_STATUS    0x61
  106. #define MPU6050_RA_I2C_SLV0_DO      0x63
  107. #define MPU6050_RA_I2C_SLV1_DO      0x64
  108. #define MPU6050_RA_I2C_SLV2_DO      0x65
  109. #define MPU6050_RA_I2C_SLV3_DO      0x66
  110. #define MPU6050_RA_I2C_MST_DELAY_CTRL   0x67
  111. #define MPU6050_RA_SIGNAL_PATH_RESET    0x68
  112. #define MPU6050_RA_MOT_DETECT_CTRL      0x69
  113. #define MPU6050_RA_USER_CTRL        0x6A
  114. #define MPU6050_RA_PWR_MGMT_1       0x6B
  115. #define MPU6050_RA_PWR_MGMT_2       0x6C
  116. #define MPU6050_RA_BANK_SEL         0x6D
  117. #define MPU6050_RA_MEM_START_ADDR   0x6E
  118. #define MPU6050_RA_MEM_R_W          0x6F
  119. #define MPU6050_RA_DMP_CFG_1        0x70
  120. #define MPU6050_RA_DMP_CFG_2        0x71
  121. #define MPU6050_RA_FIFO_COUNTH      0x72
  122. #define MPU6050_RA_FIFO_COUNTL      0x73
  123. #define MPU6050_RA_FIFO_R_W         0x74
  124. #define MPU6050_RA_WHO_AM_I         0x75

  125. #define MPU6050_TC_PWR_MODE_BIT     7
  126. #define MPU6050_TC_OFFSET_BIT       6
  127. #define MPU6050_TC_OFFSET_LENGTH    6
  128. #define MPU6050_TC_OTP_BNK_VLD_BIT  0

  129. #define MPU6050_VDDIO_LEVEL_VLOGIC  0
  130. #define MPU6050_VDDIO_LEVEL_VDD     1

  131. #define MPU6050_CFG_EXT_SYNC_SET_BIT    5
  132. #define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
  133. #define MPU6050_CFG_DLPF_CFG_BIT    2
  134. #define MPU6050_CFG_DLPF_CFG_LENGTH 3

  135. #define MPU6050_EXT_SYNC_DISABLED       0x0
  136. #define MPU6050_EXT_SYNC_TEMP_OUT_L     0x1
  137. #define MPU6050_EXT_SYNC_GYRO_XOUT_L    0x2
  138. #define MPU6050_EXT_SYNC_GYRO_YOUT_L    0x3
  139. #define MPU6050_EXT_SYNC_GYRO_ZOUT_L    0x4
  140. #define MPU6050_EXT_SYNC_ACCEL_XOUT_L   0x5
  141. #define MPU6050_EXT_SYNC_ACCEL_YOUT_L   0x6
  142. #define MPU6050_EXT_SYNC_ACCEL_ZOUT_L   0x7

  143. #define MPU6050_DLPF_BW_256         0x00
  144. #define MPU6050_DLPF_BW_188         0x01
  145. #define MPU6050_DLPF_BW_98          0x02
  146. #define MPU6050_DLPF_BW_42          0x03
  147. #define MPU6050_DLPF_BW_20          0x04
  148. #define MPU6050_DLPF_BW_10          0x05
  149. #define MPU6050_DLPF_BW_5           0x06

  150. #define MPU6050_GCONFIG_FS_SEL_BIT      4
  151. #define MPU6050_GCONFIG_FS_SEL_LENGTH   2

  152. #define MPU6050_GYRO_FS_250         0x00
  153. #define MPU6050_GYRO_FS_500         0x01
  154. #define MPU6050_GYRO_FS_1000        0x02
  155. #define MPU6050_GYRO_FS_2000        0x03

  156. #define MPU6050_ACONFIG_XA_ST_BIT           7
  157. #define MPU6050_ACONFIG_YA_ST_BIT           6
  158. #define MPU6050_ACONFIG_ZA_ST_BIT           5
  159. #define MPU6050_ACONFIG_AFS_SEL_BIT         4
  160. #define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
  161. #define MPU6050_ACONFIG_ACCEL_HPF_BIT       2
  162. #define MPU6050_ACONFIG_ACCEL_HPF_LENGTH    3

  163. #define MPU6050_ACCEL_FS_2          0x00
  164. #define MPU6050_ACCEL_FS_4          0x01
  165. #define MPU6050_ACCEL_FS_8          0x02
  166. #define MPU6050_ACCEL_FS_16         0x03

  167. #define MPU6050_DHPF_RESET          0x00
  168. #define MPU6050_DHPF_5              0x01
  169. #define MPU6050_DHPF_2P5            0x02
  170. #define MPU6050_DHPF_1P25           0x03
  171. #define MPU6050_DHPF_0P63           0x04
  172. #define MPU6050_DHPF_HOLD           0x07

  173. #define MPU6050_TEMP_FIFO_EN_BIT    7
  174. #define MPU6050_XG_FIFO_EN_BIT      6
  175. #define MPU6050_YG_FIFO_EN_BIT      5
  176. #define MPU6050_ZG_FIFO_EN_BIT      4
  177. #define MPU6050_ACCEL_FIFO_EN_BIT   3
  178. #define MPU6050_SLV2_FIFO_EN_BIT    2
  179. #define MPU6050_SLV1_FIFO_EN_BIT    1
  180. #define MPU6050_SLV0_FIFO_EN_BIT    0

  181. #define MPU6050_MULT_MST_EN_BIT     7
  182. #define MPU6050_WAIT_FOR_ES_BIT     6
  183. #define MPU6050_SLV_3_FIFO_EN_BIT   5
  184. #define MPU6050_I2C_MST_P_NSR_BIT   4
  185. #define MPU6050_I2C_MST_CLK_BIT     3
  186. #define MPU6050_I2C_MST_CLK_LENGTH  4

  187. #define MPU6050_CLOCK_DIV_348       0x0
  188. #define MPU6050_CLOCK_DIV_333       0x1
  189. #define MPU6050_CLOCK_DIV_320       0x2
  190. #define MPU6050_CLOCK_DIV_308       0x3
  191. #define MPU6050_CLOCK_DIV_296       0x4
  192. #define MPU6050_CLOCK_DIV_286       0x5
  193. #define MPU6050_CLOCK_DIV_276       0x6
  194. #define MPU6050_CLOCK_DIV_267       0x7
  195. #define MPU6050_CLOCK_DIV_258       0x8
  196. #define MPU6050_CLOCK_DIV_500       0x9
  197. #define MPU6050_CLOCK_DIV_471       0xA
  198. #define MPU6050_CLOCK_DIV_444       0xB
  199. #define MPU6050_CLOCK_DIV_421       0xC
  200. #define MPU6050_CLOCK_DIV_400       0xD
  201. #define MPU6050_CLOCK_DIV_381       0xE
  202. #define MPU6050_CLOCK_DIV_364       0xF

  203. #define MPU6050_I2C_SLV_RW_BIT      7
  204. #define MPU6050_I2C_SLV_ADDR_BIT    6
  205. #define MPU6050_I2C_SLV_ADDR_LENGTH 7
  206. #define MPU6050_I2C_SLV_EN_BIT      7
  207. #define MPU6050_I2C_SLV_BYTE_SW_BIT 6
  208. #define MPU6050_I2C_SLV_REG_DIS_BIT 5
  209. #define MPU6050_I2C_SLV_GRP_BIT     4
  210. #define MPU6050_I2C_SLV_LEN_BIT     3
  211. #define MPU6050_I2C_SLV_LEN_LENGTH  4

  212. #define MPU6050_I2C_SLV4_RW_BIT         7
  213. #define MPU6050_I2C_SLV4_ADDR_BIT       6
  214. #define MPU6050_I2C_SLV4_ADDR_LENGTH    7
  215. #define MPU6050_I2C_SLV4_EN_BIT         7
  216. #define MPU6050_I2C_SLV4_INT_EN_BIT     6
  217. #define MPU6050_I2C_SLV4_REG_DIS_BIT    5
  218. #define MPU6050_I2C_SLV4_MST_DLY_BIT    4
  219. #define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5

  220. #define MPU6050_MST_PASS_THROUGH_BIT    7
  221. #define MPU6050_MST_I2C_SLV4_DONE_BIT   6
  222. #define MPU6050_MST_I2C_LOST_ARB_BIT    5
  223. #define MPU6050_MST_I2C_SLV4_NACK_BIT   4
  224. #define MPU6050_MST_I2C_SLV3_NACK_BIT   3
  225. #define MPU6050_MST_I2C_SLV2_NACK_BIT   2
  226. #define MPU6050_MST_I2C_SLV1_NACK_BIT   1
  227. #define MPU6050_MST_I2C_SLV0_NACK_BIT   0

  228. #define MPU6050_INTCFG_INT_LEVEL_BIT        7
  229. #define MPU6050_INTCFG_INT_OPEN_BIT         6
  230. #define MPU6050_INTCFG_LATCH_INT_EN_BIT     5
  231. #define MPU6050_INTCFG_INT_RD_CLEAR_BIT     4
  232. #define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT  3
  233. #define MPU6050_INTCFG_FSYNC_INT_EN_BIT     2
  234. #define MPU6050_INTCFG_I2C_BYPASS_EN_BIT    1
  235. #define MPU6050_INTCFG_CLKOUT_EN_BIT        0

  236. #define MPU6050_INTMODE_ACTIVEHIGH  0x00
  237. #define MPU6050_INTMODE_ACTIVELOW   0x01

  238. #define MPU6050_INTDRV_PUSHPULL     0x00
  239. #define MPU6050_INTDRV_OPENDRAIN    0x01

  240. #define MPU6050_INTLATCH_50USPULSE  0x00
  241. #define MPU6050_INTLATCH_WAITCLEAR  0x01

  242. #define MPU6050_INTCLEAR_STATUSREAD 0x00
  243. #define MPU6050_INTCLEAR_ANYREAD    0x01

  244. #define MPU6050_INTERRUPT_FF_BIT            7
  245. #define MPU6050_INTERRUPT_MOT_BIT           6
  246. #define MPU6050_INTERRUPT_ZMOT_BIT          5
  247. #define MPU6050_INTERRUPT_FIFO_OFLOW_BIT    4
  248. #define MPU6050_INTERRUPT_I2C_MST_INT_BIT   3
  249. #define MPU6050_INTERRUPT_PLL_RDY_INT_BIT   2
  250. #define MPU6050_INTERRUPT_DMP_INT_BIT       1
  251. #define MPU6050_INTERRUPT_DATA_RDY_BIT      0

  252. // TODO: figure out what these actually do
  253. // UMPL source code is not very obivous
  254. #define MPU6050_DMPINT_5_BIT            5
  255. #define MPU6050_DMPINT_4_BIT            4
  256. #define MPU6050_DMPINT_3_BIT            3
  257. #define MPU6050_DMPINT_2_BIT            2
  258. #define MPU6050_DMPINT_1_BIT            1
  259. #define MPU6050_DMPINT_0_BIT            0

  260. #define MPU6050_MOTION_MOT_XNEG_BIT     7
  261. #define MPU6050_MOTION_MOT_XPOS_BIT     6
  262. #define MPU6050_MOTION_MOT_YNEG_BIT     5
  263. #define MPU6050_MOTION_MOT_YPOS_BIT     4
  264. #define MPU6050_MOTION_MOT_ZNEG_BIT     3
  265. #define MPU6050_MOTION_MOT_ZPOS_BIT     2
  266. #define MPU6050_MOTION_MOT_ZRMOT_BIT    0

  267. #define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT   7
  268. #define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT   4
  269. #define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT   3
  270. #define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT   2
  271. #define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT   1
  272. #define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT   0

  273. #define MPU6050_PATHRESET_GYRO_RESET_BIT    2
  274. #define MPU6050_PATHRESET_ACCEL_RESET_BIT   1
  275. #define MPU6050_PATHRESET_TEMP_RESET_BIT    0

  276. #define MPU6050_DETECT_ACCEL_ON_DELAY_BIT       5
  277. #define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH    2
  278. #define MPU6050_DETECT_FF_COUNT_BIT             3
  279. #define MPU6050_DETECT_FF_COUNT_LENGTH          2
  280. #define MPU6050_DETECT_MOT_COUNT_BIT            1
  281. #define MPU6050_DETECT_MOT_COUNT_LENGTH         2

  282. #define MPU6050_DETECT_DECREMENT_RESET  0x0
  283. #define MPU6050_DETECT_DECREMENT_1      0x1
  284. #define MPU6050_DETECT_DECREMENT_2      0x2
  285. #define MPU6050_DETECT_DECREMENT_4      0x3

  286. #define MPU6050_USERCTRL_DMP_EN_BIT             7
  287. #define MPU6050_USERCTRL_FIFO_EN_BIT            6
  288. #define MPU6050_USERCTRL_I2C_MST_EN_BIT         5
  289. #define MPU6050_USERCTRL_I2C_IF_DIS_BIT         4
  290. #define MPU6050_USERCTRL_DMP_RESET_BIT          3
  291. #define MPU6050_USERCTRL_FIFO_RESET_BIT         2
  292. #define MPU6050_USERCTRL_I2C_MST_RESET_BIT      1
  293. #define MPU6050_USERCTRL_SIG_COND_RESET_BIT     0

  294. #define MPU6050_PWR1_DEVICE_RESET_BIT   7
  295. #define MPU6050_PWR1_SLEEP_BIT          6
  296. #define MPU6050_PWR1_CYCLE_BIT          5
  297. #define MPU6050_PWR1_TEMP_DIS_BIT       3
  298. #define MPU6050_PWR1_CLKSEL_BIT         2
  299. #define MPU6050_PWR1_CLKSEL_LENGTH      3

  300. #define MPU6050_CLOCK_INTERNAL          0x00
  301. #define MPU6050_CLOCK_PLL_XGYRO         0x01
  302. #define MPU6050_CLOCK_PLL_YGYRO         0x02
  303. #define MPU6050_CLOCK_PLL_ZGYRO         0x03
  304. #define MPU6050_CLOCK_PLL_EXT32K        0x04
  305. #define MPU6050_CLOCK_PLL_EXT19M        0x05
  306. #define MPU6050_CLOCK_KEEP_RESET        0x07

  307. #define MPU6050_PWR2_LP_WAKE_CTRL_BIT       7
  308. #define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH    2
  309. #define MPU6050_PWR2_STBY_XA_BIT            5
  310. #define MPU6050_PWR2_STBY_YA_BIT            4
  311. #define MPU6050_PWR2_STBY_ZA_BIT            3
  312. #define MPU6050_PWR2_STBY_XG_BIT            2
  313. #define MPU6050_PWR2_STBY_YG_BIT            1
  314. #define MPU6050_PWR2_STBY_ZG_BIT            0

  315. #define MPU6050_WAKE_FREQ_1P25      0x0
  316. #define MPU6050_WAKE_FREQ_2P5       0x1
  317. #define MPU6050_WAKE_FREQ_5         0x2
  318. #define MPU6050_WAKE_FREQ_10        0x3

  319. #define MPU6050_BANKSEL_PRFTCH_EN_BIT       6
  320. #define MPU6050_BANKSEL_CFG_USER_BANK_BIT   5
  321. #define MPU6050_BANKSEL_MEM_SEL_BIT         4
  322. #define MPU6050_BANKSEL_MEM_SEL_LENGTH      5

  323. #define MPU6050_WHO_AM_I_BIT        6
  324. #define MPU6050_WHO_AM_I_LENGTH     6

  325. #define MPU6050_DMP_MEMORY_BANKS        8
  326. #define MPU6050_DMP_MEMORY_BANK_SIZE    256
  327. #define MPU6050_DMP_MEMORY_CHUNK_SIZE   16

  328. // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];")
  329. #define I2CDEV_DEFAULT_READ_TIMEOUT     1000

  330. void MPU6050();
  331. // SMPLRT_DIV register
  332. uint8_t getRate();
  333. void setRate(uint8_t rate);
  334. uint8_t getClockSource();
  335. void setClockSource(uint8_t source);
  336. // GYRO_CONFIG register
  337. uint8_t getFullScaleGyroRange();
  338. void setFullScaleGyroRange(uint8_t range);
  339. uint8_t getFullScaleAccelRange();
  340. void setFullScaleAccelRange(uint8_t range);
  341. uint8_t getDHPFMode();
  342. void setDHPFMode(uint8_t mode);
  343. // PWR_MGMT_1 register
  344. void reset();
  345. bool getSleepEnabled();
  346. void setSleepEnabled(bool enabled);
  347. bool getTempSensorEnabled();
  348. void setTempSensorEnabled(bool enabled);

  349. uint8_t getMasterClockSpeed();
  350. void setMasterClockSpeed(uint8_t speed);
  351. int8_t writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
  352. int8_t writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
  353. int8_t writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
  354. int8_t writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
  355. int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data);
  356. int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
  357. int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data);
  358. int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data);
  359. int getState();
  360. // WHO_AM_I register
  361. uint8_t getDeviceID();
  362. void getAcceleration(int16_t* x, int16_t* y, int16_t* z);
  363. int16_t getAccelerationX();
  364. int16_t getAccelerationY();
  365. int16_t getAccelerationZ();

  366. // TEMP_OUT_* registers
  367. int16_t getTemperature();

  368. // GYRO_*OUT_* registers
  369. void getRotation(int16_t* x, int16_t* y, int16_t* z);
  370. int16_t getRotationX();
  371. int16_t getRotationY();
  372. int16_t getRotationZ();
  373. void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);

  374. #endif
复制代码
mpu6050.c
  1. #include "Wire.h"
  2. #include "MPU6050.h"
  3. #include "log.h"

  4. #define MPU6050_ADDR 0x68

  5. uint8_t buffer[14];

  6. int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data) {
  7.     beginTransmission(devAddr);
  8.     write_char(regAddr);
  9.     requestFrom(devAddr, length);
  10.     endTransmission();
  11.     int8_t count = 0;
  12.     while (available()) {
  13.       data[count] = readI2c();
  14.       count++;
  15.     }
  16.     LOG_E("=============================\r\n");
  17.     for (size_t i = 0; i < count; i++)
  18.     {
  19.         LOG_E("%2x data%d: %2x \r\n", regAddr, i, data[0]);
  20.     }
  21.     LOG_E("==============================\r\n");
  22.     return count;
  23. }


  24. int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data) {
  25.     return readBytes(devAddr, regAddr, 1, data);
  26. }

  27. /** Read a single bit from an 8-bit device register.
  28. * @param devAddr I2C slave device address
  29. * @param regAddr Register regAddr to read from
  30. * @param bitNum Bit position to read (0-7)
  31. * @param data Container for single bit value
  32. * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
  33. * @return Status of read operation (true = success)
  34. */
  35. int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data) {
  36.     uint8_t b;
  37.     uint8_t count = readByte(devAddr, regAddr, &b);
  38.     *data = b & (1 << bitNum);
  39.     return count;
  40. }

  41. /** Read multiple bits from an 8-bit device register.
  42. * @param devAddr I2C slave device address
  43. * @param regAddr Register regAddr to read from
  44. * @param bitStart First bit position to read (0-7)
  45. * @param length Number of bits to read (not more than 8)
  46. * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05)
  47. * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout)
  48. * @return Status of read operation (true = success)
  49. */
  50. int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data) {
  51.     // 01101001 read byte
  52.     // 76543210 bit numbers
  53.     //    xxx   args: bitStart=4, length=3
  54.     //    010   masked
  55.     //   -> 010 shifted
  56.     uint8_t count, b;
  57.     if ((count = readByte(devAddr, regAddr, &b)) != 0) {
  58.         uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
  59.         b &= mask;
  60.         b >>= (bitStart - length + 1);
  61.         *data = b;
  62.     }
  63.     return count;
  64. }

  65. int8_t writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) {
  66.     beginTransmission(devAddr);
  67.     write_char((uint8_t) regAddr); // send address
  68.     for (uint8_t i = 0; i < length; i++) {
  69.       write_char((uint8_t) data[i]);
  70.     }
  71.     endTransmission();
  72.     return 0;
  73. }

  74. int8_t writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
  75.     return writeBytes(devAddr, regAddr, 1, &data);
  76. }

  77. int8_t writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
  78.     //      010 value to write
  79.     // 76543210 bit numbers
  80.     //    xxx   args: bitStart=4, length=3
  81.     // 00011100 mask byte
  82.     // 10101111 original value (sample)
  83.     // 10100011 original & ~mask
  84.     // 10101011 masked | value
  85.     uint8_t b;
  86.     if(readByte(devAddr, regAddr, &b)!=0){
  87.       uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
  88.       data <<= (bitStart - length + 1); // shift data into correct position
  89.       data &= mask; // zero all non-important bits in data
  90.       b &= ~(mask); // zero all important bits in existing byte
  91.       b |= data; // combine data with existing byte
  92.       return writeByte(devAddr, regAddr, b);
  93.     }
  94.     return 0;
  95. }

  96. int8_t writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) {
  97.     uint8_t b;
  98.     readByte(devAddr, regAddr, &b);
  99.     b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
  100.     return writeByte(devAddr, regAddr, b);
  101. }

  102. /** Get clock source setting.
  103. * @return Current clock source setting
  104. * @see MPU6050_RA_PWR_MGMT_1
  105. * @see MPU6050_PWR1_CLKSEL_BIT
  106. * @see MPU6050_PWR1_CLKSEL_LENGTH
  107. */
  108. uint8_t getClockSource() {
  109.     readBits(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, buffer);
  110.     return buffer[0];
  111. }
  112. /** Set clock source setting.
  113. * An internal 8MHz oscillator, gyroscope based clock, or external sources can
  114. * be selected as the MPU-60X0 clock source. When the internal 8 MHz oscillator
  115. * or an external source is chosen as the clock source, the MPU-60X0 can operate
  116. * in low power modes with the gyroscopes disabled.
  117. *
  118. * Upon power up, the MPU-60X0 clock source defaults to the internal oscillator.
  119. * However, it is highly recommended that the device be configured to use one of
  120. * the gyroscopes (or an external clock source) as the clock reference for
  121. * improved stability. The clock source can be selected according to the following table:
  122. *
  123. * <pre>
  124. * CLK_SEL | Clock Source
  125. * --------+--------------------------------------
  126. * 0       | Internal oscillator
  127. * 1       | PLL with X Gyro reference
  128. * 2       | PLL with Y Gyro reference
  129. * 3       | PLL with Z Gyro reference
  130. * 4       | PLL with external 32.768kHz reference
  131. * 5       | PLL with external 19.2MHz reference
  132. * 6       | Reserved
  133. * 7       | Stops the clock and keeps the timing generator in reset
  134. * </pre>
  135. *
  136. * @param source New clock source setting
  137. * @see getClockSource()
  138. * @see MPU6050_RA_PWR_MGMT_1
  139. * @see MPU6050_PWR1_CLKSEL_BIT
  140. * @see MPU6050_PWR1_CLKSEL_LENGTH
  141. */
  142. void setClockSource(uint8_t source) {
  143.   writeBits(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);
  144. }

  145. // GYRO_CONFIG register

  146. /** Get full-scale gyroscope range.
  147. * The FS_SEL parameter allows setting the full-scale range of the gyro sensors,
  148. * as described in the table below.
  149. *
  150. * <pre>
  151. * 0 = +/- 250 degrees/sec
  152. * 1 = +/- 500 degrees/sec
  153. * 2 = +/- 1000 degrees/sec
  154. * 3 = +/- 2000 degrees/sec
  155. * </pre>
  156. *
  157. * @return Current full-scale gyroscope range setting
  158. * @see MPU6050_GYRO_FS_250
  159. * @see MPU6050_RA_GYRO_CONFIG
  160. * @see MPU6050_GCONFIG_FS_SEL_BIT
  161. * @see MPU6050_GCONFIG_FS_SEL_LENGTH
  162. */
  163. uint8_t getFullScaleGyroRange() {
  164.     readBits(MPU6050_ADDR, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, buffer);
  165.     return buffer[0];
  166. }

  167. /** Set full-scale gyroscope range.
  168. * @param range New full-scale gyroscope range value
  169. * @see getFullScaleRange()
  170. * @see MPU6050_GYRO_FS_250
  171. * @see MPU6050_RA_GYRO_CONFIG
  172. * @see MPU6050_GCONFIG_FS_SEL_BIT
  173. * @see MPU6050_GCONFIG_FS_SEL_LENGTH
  174. */
  175. void setFullScaleGyroRange(uint8_t range) {
  176.   writeBits(MPU6050_ADDR, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
  177. }

  178. /** Get full-scale accelerometer range.
  179. * The FS_SEL parameter allows setting the full-scale range of the accelerometer
  180. * sensors, as described in the table below.
  181. *
  182. * <pre>
  183. * 0 = +/- 2g
  184. * 1 = +/- 4g
  185. * 2 = +/- 8g
  186. * 3 = +/- 16g
  187. * </pre>
  188. *
  189. * @return Current full-scale accelerometer range setting
  190. * @see MPU6050_ACCEL_FS_2
  191. * @see MPU6050_RA_ACCEL_CONFIG
  192. * @see MPU6050_ACONFIG_AFS_SEL_BIT
  193. * @see MPU6050_ACONFIG_AFS_SEL_LENGTH
  194. */
  195. uint8_t getFullScaleAccelRange() {
  196.     readBits(MPU6050_ADDR, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, buffer);
  197.     return buffer[0];
  198. }
  199. /** Set full-scale accelerometer range.
  200. * @param range New full-scale accelerometer range setting
  201. * @see getFullScaleAccelRange()
  202. */
  203. void setFullScaleAccelRange(uint8_t range) {
  204.   writeBits(MPU6050_ADDR, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
  205. }

  206. /** Get the high-pass filter configuration.
  207. * The DHPF is a filter module in the path leading to motion detectors (Free
  208. * Fall, Motion threshold, and Zero Motion). The high pass filter output is not
  209. * available to the data registers (see Figure in Section 8 of the MPU-6000/
  210. * MPU-6050 Product Specification document).
  211. *
  212. * The high pass filter has three modes:
  213. *
  214. * <pre>
  215. *    Reset: The filter output settles to zero within one sample. This
  216. *           effectively disables the high pass filter. This mode may be toggled
  217. *           to quickly settle the filter.
  218. *
  219. *    On:    The high pass filter will pass signals above the cut off frequency.
  220. *
  221. *    Hold:  When triggered, the filter holds the present sample. The filter
  222. *           output will be the difference between the input sample and the held
  223. *           sample.
  224. * </pre>
  225. *
  226. * <pre>
  227. * ACCEL_HPF | Filter Mode | Cut-off Frequency
  228. * ----------+-------------+------------------
  229. * 0         | Reset       | None
  230. * 1         | On          | 5Hz
  231. * 2         | On          | 2.5Hz
  232. * 3         | On          | 1.25Hz
  233. * 4         | On          | 0.63Hz
  234. * 7         | Hold        | None
  235. * </pre>
  236. *
  237. * @return Current high-pass filter configuration
  238. * @see MPU6050_DHPF_RESET
  239. * @see MPU6050_RA_ACCEL_CONFIG
  240. */
  241. uint8_t getDHPFMode() {
  242.     readBits(MPU6050_ADDR, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, buffer);
  243.     return buffer[0];
  244. }
  245. /** Set the high-pass filter configuration.
  246. * @param bandwidth New high-pass filter configuration
  247. * @see setDHPFMode()
  248. * @see MPU6050_DHPF_RESET
  249. * @see MPU6050_RA_ACCEL_CONFIG
  250. */
  251. void setDHPFMode(uint8_t bandwidth) {
  252.     writeBits(MPU6050_ADDR, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, bandwidth);
  253. }

  254. /** Get I2C master clock speed.
  255. * I2C_MST_CLK is a 4 bit unsigned value which configures a divider on the
  256. * MPU-60X0 internal 8MHz clock. It sets the I2C master clock speed according to
  257. * the following table:
  258. *
  259. * <pre>
  260. * I2C_MST_CLK | I2C Master Clock Speed | 8MHz Clock Divider
  261. * ------------+------------------------+-------------------
  262. * 0           | 348kHz                 | 23
  263. * 1           | 333kHz                 | 24
  264. * 2           | 320kHz                 | 25
  265. * 3           | 308kHz                 | 26
  266. * 4           | 296kHz                 | 27
  267. * 5           | 286kHz                 | 28
  268. * 6           | 276kHz                 | 29
  269. * 7           | 267kHz                 | 30
  270. * 8           | 258kHz                 | 31
  271. * 9           | 500kHz                 | 16
  272. * 10          | 471kHz                 | 17
  273. * 11          | 444kHz                 | 18
  274. * 12          | 421kHz                 | 19
  275. * 13          | 400kHz                 | 20
  276. * 14          | 381kHz                 | 21
  277. * 15          | 364kHz                 | 22
  278. * </pre>
  279. *
  280. * @return Current I2C master clock speed
  281. * @see MPU6050_RA_I2C_MST_CTRL
  282. */
  283. uint8_t getMasterClockSpeed() {
  284.     readBits(MPU6050_ADDR, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, buffer);
  285.     return buffer[0];
  286. }
  287. /** Set I2C master clock speed.
  288. * @reparam speed Current I2C master clock speed
  289. * @see MPU6050_RA_I2C_MST_CTRL
  290. */
  291. void setMasterClockSpeed(uint8_t speed) {
  292.     writeBits(MPU6050_ADDR, MPU6050_RA_I2C_MST_CTRL, MPU6050_I2C_MST_CLK_BIT, MPU6050_I2C_MST_CLK_LENGTH, speed);
  293. }

  294. /** Get 3-axis accelerometer readings.
  295. * These registers store the most recent accelerometer measurements.
  296. * Accelerometer measurements are written to these registers at the Sample Rate
  297. * as defined in Register 25.
  298. *
  299. * The accelerometer measurement registers, along with the temperature
  300. * measurement registers, gyroscope measurement registers, and external sensor
  301. * data registers, are composed of two sets of registers: an internal register
  302. * set and a user-facing read register set.
  303. *
  304. * The data within the accelerometer sensors' internal register set is always
  305. * updated at the Sample Rate. Meanwhile, the user-facing read register set
  306. * duplicates the internal register set's data values whenever the serial
  307. * interface is idle. This guarantees that a burst read of sensor registers will
  308. * read measurements from the same sampling instant. Note that if burst reads
  309. * are not used, the user is responsible for ensuring a set of single byte reads
  310. * correspond to a single sampling instant by checking the Data Ready interrupt.
  311. *
  312. * Each 16-bit accelerometer measurement has a full scale defined in ACCEL_FS
  313. * (Register 28). For each full scale setting, the accelerometers' sensitivity
  314. * per LSB in ACCEL_xOUT is shown in the table below:
  315. *
  316. * <pre>
  317. * AFS_SEL | Full Scale Range | LSB Sensitivity
  318. * --------+------------------+----------------
  319. * 0       | +/- 2g           | 8192 LSB/mg
  320. * 1       | +/- 4g           | 4096 LSB/mg
  321. * 2       | +/- 8g           | 2048 LSB/mg
  322. * 3       | +/- 16g          | 1024 LSB/mg
  323. * </pre>
  324. *
  325. * @param x 16-bit signed integer container for X-axis acceleration
  326. * @param y 16-bit signed integer container for Y-axis acceleration
  327. * @param z 16-bit signed integer container for Z-axis acceleration
  328. * @see MPU6050_RA_GYRO_XOUT_H
  329. */
  330. void getAcceleration(int16_t* x, int16_t* y, int16_t* z) {
  331.     readBytes(MPU6050_ADDR, MPU6050_RA_ACCEL_XOUT_H, 6, buffer);
  332.     *x = (((int16_t)buffer[0]) << 8) | buffer[1];
  333.     *y = (((int16_t)buffer[2]) << 8) | buffer[3];
  334.     *z = (((int16_t)buffer[4]) << 8) | buffer[5];
  335. }
  336. /** Get X-axis accelerometer reading.
  337. * @return X-axis acceleration measurement in 16-bit 2's complement format
  338. * @see getMotion6()
  339. * @see MPU6050_RA_ACCEL_XOUT_H
  340. */
  341. int16_t getAccelerationX() {
  342.     readBytes(MPU6050_ADDR, MPU6050_RA_ACCEL_XOUT_H, 2, buffer);
  343.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  344. }
  345. /** Get Y-axis accelerometer reading.
  346. * @return Y-axis acceleration measurement in 16-bit 2's complement format
  347. * @see getMotion6()
  348. * @see MPU6050_RA_ACCEL_YOUT_H
  349. */
  350. int16_t getAccelerationY() {
  351.     readBytes(MPU6050_ADDR, MPU6050_RA_ACCEL_YOUT_H, 2, buffer);
  352.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  353. }
  354. /** Get Z-axis accelerometer reading.
  355. * @return Z-axis acceleration measurement in 16-bit 2's complement format
  356. * @see getMotion6()
  357. * @see MPU6050_RA_ACCEL_ZOUT_H
  358. */
  359. int16_t getAccelerationZ() {
  360.     readBytes(MPU6050_ADDR, MPU6050_RA_ACCEL_ZOUT_H, 2, buffer);
  361.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  362. }

  363. // TEMP_OUT_* registers

  364. /** Get current internal temperature.
  365. * @return Temperature reading in 16-bit 2's complement format
  366. * @see MPU6050_RA_TEMP_OUT_H
  367. */
  368. int16_t getTemperature() {
  369.     readBytes(MPU6050_ADDR, MPU6050_RA_TEMP_OUT_H, 2, buffer);
  370.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  371. }

  372. // GYRO_*OUT_* registers

  373. /** Get 3-axis gyroscope readings.
  374. * These gyroscope measurement registers, along with the accelerometer
  375. * measurement registers, temperature measurement registers, and external sensor
  376. * data registers, are composed of two sets of registers: an internal register
  377. * set and a user-facing read register set.
  378. * The data within the gyroscope sensors' internal register set is always
  379. * updated at the Sample Rate. Meanwhile, the user-facing read register set
  380. * duplicates the internal register set's data values whenever the serial
  381. * interface is idle. This guarantees that a burst read of sensor registers will
  382. * read measurements from the same sampling instant. Note that if burst reads
  383. * are not used, the user is responsible for ensuring a set of single byte reads
  384. * correspond to a single sampling instant by checking the Data Ready interrupt.
  385. *
  386. * Each 16-bit gyroscope measurement has a full scale defined in FS_SEL
  387. * (Register 27). For each full scale setting, the gyroscopes' sensitivity per
  388. * LSB in GYRO_xOUT is shown in the table below:
  389. *
  390. * <pre>
  391. * FS_SEL | Full Scale Range   | LSB Sensitivity
  392. * -------+--------------------+----------------
  393. * 0      | +/- 250 degrees/s  | 131 LSB/deg/s
  394. * 1      | +/- 500 degrees/s  | 65.5 LSB/deg/s
  395. * 2      | +/- 1000 degrees/s | 32.8 LSB/deg/s
  396. * 3      | +/- 2000 degrees/s | 16.4 LSB/deg/s
  397. * </pre>
  398. *
  399. * @param x 16-bit signed integer container for X-axis rotation
  400. * @param y 16-bit signed integer container for Y-axis rotation
  401. * @param z 16-bit signed integer container for Z-axis rotation
  402. * @see getMotion6()
  403. * @see MPU6050_RA_GYRO_XOUT_H
  404. */
  405. void getRotation(int16_t* x, int16_t* y, int16_t* z) {
  406.     readBytes(MPU6050_ADDR, MPU6050_RA_GYRO_XOUT_H, 6, buffer);
  407.     *x = (((int16_t)buffer[0]) << 8) | buffer[1];
  408.     *y = (((int16_t)buffer[2]) << 8) | buffer[3];
  409.     *z = (((int16_t)buffer[4]) << 8) | buffer[5];
  410. }
  411. /** Get X-axis gyroscope reading.
  412. * @return X-axis rotation measurement in 16-bit 2's complement format
  413. * @see getMotion6()
  414. * @see MPU6050_RA_GYRO_XOUT_H
  415. */
  416. int16_t getRotationX() {
  417.     readBytes(MPU6050_ADDR, MPU6050_RA_GYRO_XOUT_H, 2, buffer);
  418.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  419. }
  420. /** Get Y-axis gyroscope reading.
  421. * @return Y-axis rotation measurement in 16-bit 2's complement format
  422. * @see getMotion6()
  423. * @see MPU6050_RA_GYRO_YOUT_H
  424. */
  425. int16_t getRotationY() {
  426.     readBytes(MPU6050_ADDR, MPU6050_RA_GYRO_YOUT_H, 2, buffer);
  427.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  428. }
  429. /** Get Z-axis gyroscope reading.
  430. * @return Z-axis rotation measurement in 16-bit 2's complement format
  431. * @see getMotion6()
  432. * @see MPU6050_RA_GYRO_ZOUT_H
  433. */
  434. int16_t getRotationZ() {
  435.     readBytes(MPU6050_ADDR, MPU6050_RA_GYRO_ZOUT_H, 2, buffer);
  436.     return (((int16_t)buffer[0]) << 8) | buffer[1];
  437. }

  438. // PWR_MGMT_1 register

  439. /** Trigger a full device reset.
  440. * A small delay of ~50ms may be desirable after triggering a reset.
  441. * @see MPU6050_RA_PWR_MGMT_1
  442. * @see MPU6050_PWR1_DEVICE_RESET_BIT
  443. */
  444. void reset() {
  445.     writeBit(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_DEVICE_RESET_BIT, true);
  446. }
  447. /** Get sleep mode status.
  448. * Setting the SLEEP bit in the register puts the device into very low power
  449. * sleep mode. In this mode, only the serial interface and internal registers
  450. * remain active, allowing for a very low standby current. Clearing this bit
  451. * puts the device back into normal mode. To save power, the individual standby
  452. * selections for each of the gyros should be used if any gyro axis is not used
  453. * by the application.
  454. * @return Current sleep mode enabled status
  455. * @see MPU6050_RA_PWR_MGMT_1
  456. * @see MPU6050_PWR1_SLEEP_BIT
  457. */
  458. bool getSleepEnabled() {
  459.     readBit(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, buffer);
  460.     return buffer[0];
  461. }

  462. /** Set sleep mode status.
  463. * @param enabled New sleep mode enabled status
  464. * @see getSleepEnabled()
  465. * @see MPU6050_RA_PWR_MGMT_1
  466. * @see MPU6050_PWR1_SLEEP_BIT
  467. */
  468. void setSleepEnabled(bool enabled) {
  469.     writeBit(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled);
  470. }

  471. /** Get temperature sensor enabled status.
  472. * Control the usage of the internal temperature sensor.
  473. *
  474. * Note: this register stores the *disabled* value, but for consistency with the
  475. * rest of the code, the function is named and used with standard true/false
  476. * values to indicate whether the sensor is enabled or disabled, respectively.
  477. *
  478. * @return Current temperature sensor enabled status
  479. * @see MPU6050_RA_PWR_MGMT_1
  480. * @see MPU6050_PWR1_TEMP_DIS_BIT
  481. */
  482. bool getTempSensorEnabled() {
  483.     readBit(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, buffer);
  484.     return buffer[0] == 0; // 1 is actually disabled here
  485. }
  486. /** Set temperature sensor enabled status.
  487. * Note: this register stores the *disabled* value, but for consistency with the
  488. * rest of the code, the function is named and used with standard true/false
  489. * values to indicate whether the sensor is enabled or disabled, respectively.
  490. *
  491. * @param enabled New temperature sensor enabled status
  492. * @see getTempSensorEnabled()
  493. * @see MPU6050_RA_PWR_MGMT_1
  494. * @see MPU6050_PWR1_TEMP_DIS_BIT
  495. */
  496. void setTempSensorEnabled(bool enabled) {
  497.     // 1 is actually disabled here
  498.     writeBit(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, !enabled);
  499. }


  500. uint8_t getDeviceID() {
  501.   uint8_t buf[1];
  502.   readByte(MPU6050_ADDR, MPU6050_RA_WHO_AM_I, buf);
  503.   LOG_E("MPU6050 getDeviceID : %2x!\r\n", buf[0]);
  504.   return buf[0];
  505. }

  506. // SMPLRT_DIV register

  507. /** Get gyroscope output rate divider.
  508. * The sensor register output, FIFO output, DMP sampling, Motion detection, Zero
  509. * Motion detection, and Free Fall detection are all based on the Sample Rate.
  510. * The Sample Rate is generated by dividing the gyroscope output rate by
  511. * SMPLRT_DIV:
  512. *
  513. * Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
  514. *
  515. * where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or
  516. * 7), and 1kHz when the DLPF is enabled (see Register 26).
  517. *
  518. * Note: The accelerometer output rate is 1kHz. This means that for a Sample
  519. * Rate greater than 1kHz, the same accelerometer sample may be output to the
  520. * FIFO, DMP, and sensor registers more than once.
  521. *
  522. * For a diagram of the gyroscope and accelerometer signal paths, see Section 8
  523. * of the MPU-6000/MPU-6050 Product Specification document.
  524. *
  525. * @return Current sample rate
  526. * @see MPU6050_RA_SMPLRT_DIV
  527. */
  528. uint8_t getRate() {
  529.     readByte(MPU6050_ADDR, MPU6050_RA_SMPLRT_DIV, buffer);
  530.     return buffer[0];
  531. }
  532. /** Set gyroscope sample rate divider.
  533. * @param rate New sample rate divider
  534. * @see getRate()
  535. * @see MPU6050_RA_SMPLRT_DIV
  536. */
  537. void setRate(uint8_t rate) {
  538.     writeByte(MPU6050_ADDR, MPU6050_RA_SMPLRT_DIV, rate);
  539. }

  540. void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) {
  541.    
  542.     LOG_E("MPU6050 getMotion6!\r\n");
  543.     readBytes(MPU6050_ADDR, MPU6050_RA_ACCEL_XOUT_H, 14, buffer);
  544.     *ax = (((int16_t)buffer[0]) << 8) | buffer[1];
  545.     *ay = (((int16_t)buffer[2]) << 8) | buffer[3];
  546.     *az = (((int16_t)buffer[4]) << 8) | buffer[5];
  547.     *gx = (((int16_t)buffer[8]) << 8) | buffer[9];
  548.     *gy = (((int16_t)buffer[10]) << 8) | buffer[11];
  549.     *gz = (((int16_t)buffer[12]) << 8) | buffer[13];
  550. }

  551. void MPU6050() {
  552.     begin();
  553.     // setClockSource(MPU6050_CLOCK_PLL_XGYRO);
  554.     // setFullScaleGyroRange(MPU6050_GYRO_FS_1000);
  555.     // setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
  556.     // setSleepEnabled(false);
  557.     writeByte(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_1, 0x01);
  558.     writeByte(MPU6050_ADDR, MPU6050_RA_PWR_MGMT_2, 0x00);
  559.     writeByte(MPU6050_ADDR, MPU6050_RA_GYRO_CONFIG, 0x18);
  560.     writeByte(MPU6050_ADDR, MPU6050_RA_ACCEL_CONFIG, 0x18);
  561. }
复制代码
main.c

复制代码
消息推送目前还么时间完善,使用pushplus
官方地址https://www.pushplus.plus/,申请注册后拿到token使用http请求即可实现消息推送。
消息推送到微信可以参考

  1. #!/bin/sh
复制代码
这个是做内网穿透的时候,由于natapp免费版总是变地址,写了个脚本,定时发送新的域名用的。日志经过清理,只保留的INFO部分,基本不会太大。
可以直接将消息推送到微信。
视频.gif








v2-eb872f558610a4f2f427916419a66af1_720w.png
v2-079becc8c0e7b492b62dd1d91df2e414_720w.png
v2-7008e45c6b032fb15fe5f90e8e4933e0_720w.png
v2-ad78f1fe43d6e16bdd783a2d11289c1c_720w.png
屏幕截图 2023-12-18 105733.png
v2-c51ecf12063a4c278ff7dfeef545659e_720w.png
v2-84bdb3f880952ac3f0514107afce0fd7_720w.png

本帖被以下淘专辑推荐:

回复

使用道具 举报

bzhou830 | 2023-12-18 11:32:03 | 显示全部楼层
赞一个
选择去发光,而不是被照亮
回复

使用道具 举报

1084504793 | 2023-12-18 11:53:43 | 显示全部楼层
学到了
回复

使用道具 举报

干簧管 | 2023-12-18 13:04:44 | 显示全部楼层
厉害
回复

使用道具 举报

方源 | 2023-12-18 17:04:49 | 显示全部楼层
哇,大佬
回复

使用道具 举报

李白百 | 2023-12-18 17:18:18 | 显示全部楼层
大学生毕设一个
回复 支持 反对

使用道具 举报

lsrly | 2023-12-18 21:53:08 | 显示全部楼层
赞👍🏻
好好学习,努力挣钱,专心
回复

使用道具 举报

san | 2023-12-18 23:30:27 | 显示全部楼层
回复

使用道具 举报

爱笑 | 2023-12-19 08:42:47 | 显示全部楼层
期待完整的作品
用心做好保姆工作
回复 支持 反对

使用道具 举报

WT_0213 | 2023-12-19 09:16:05 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则