mpu6xxx.lua 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. --- 模块功能:mpu6xxx
  2. -- @module mpu6xxx
  3. -- @author Dozingfiretruck
  4. -- @license MIT
  5. -- @copyright OpenLuat.com
  6. -- @release 2020.12.22
  7. --支持mpu6500,mpu6050,mpu9250,icm2068g,icm20608d,自动判断器件id,只需要配置i2c id就可以
  8. local sys = require "sys"
  9. --pm.wake("mpu6xxx")
  10. local i2cid = 0 --i2cid
  11. local i2cslaveaddr
  12. local deviceid
  13. local MPU6XXX_ADDRESS_AD0_LOW = 0x68 -- address pin low (GND), default for InvenSense evaluation board
  14. local MPU6XXX_ADDRESS_AD0_HIGH = 0x69 -- address pin high (VCC)
  15. ---器件通讯地址
  16. local MPU6050_WHO_AM_I = 0x68 -- mpu6050
  17. local MPU6500_WHO_AM_I = 0x70 -- mpu6500
  18. local MPU9250_WHO_AM_I = 0x71 -- mpu9250
  19. local ICM20608G_WHO_AM_I = 0xAF -- icm20608G
  20. local ICM20608D_WHO_AM_I = 0xAE -- icm20608D
  21. local MPU6XXX_ACCEL_SEN = 16384
  22. local MPU6XXX_GYRO_SEN = 1310
  23. local MPU60X0_TEMP_SEN = 340
  24. local MPU60X0_TEMP_OFFSET = 36.5
  25. local MPU6500_TEMP_SEN = 333.87
  26. local MPU6500_TEMP_OFFSET = 21
  27. ---MPU6XXX所用地址
  28. local MPU6XXX_RA_ACCEL_XOUT_H = 0x3B
  29. local MPU6XXX_RA_ACCEL_XOUT_L = 0x3C
  30. local MPU6XXX_RA_ACCEL_YOUT_H = 0x3D
  31. local MPU6XXX_RA_ACCEL_YOUT_L = 0x3E
  32. local MPU6XXX_RA_ACCEL_ZOUT_H = 0x3F
  33. local MPU6XXX_RA_ACCEL_ZOUT_L = 0x40
  34. local MPU6XXX_RA_TEMP_OUT_H = 0x41
  35. local MPU6XXX_RA_TEMP_OUT_L = 0x42
  36. local MPU6XXX_RA_GYRO_XOUT_H = 0x43
  37. local MPU6XXX_RA_GYRO_XOUT_L = 0x44
  38. local MPU6XXX_RA_GYRO_YOUT_H = 0x45
  39. local MPU6XXX_RA_GYRO_YOUT_L = 0x46
  40. local MPU6XXX_RA_GYRO_ZOUT_H = 0x47
  41. local MPU6XXX_RA_GYRO_ZOUT_L = 0x48
  42. local MPU6XXX_RA_SMPLRT_DIV = 0x19 --陀螺仪采样率,典型值:0x07(125Hz)
  43. local MPU6XXX_RA_CONFIG = 0x1A --低通滤波频率,典型值:0x06(5Hz)
  44. local MPU6XXX_RA_GYRO_CONFIG = 0x1B --陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  45. local MPU6XXX_RA_ACCEL_CONFIG = 0x1C --加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  46. local MPU6XXX_RA_FIFO_EN = 0x23 --fifo使能
  47. local MPU6XXX_RA_INT_PIN_CFG = 0x37 --int引脚有效电平
  48. local MPU6XXX_RA_INT_ENABLE = 0x38 --中断使能
  49. local MPU6XXX_RA_USER_CTRL = 0x6A
  50. local MPU6XXX_RA_PWR_MGMT_1 = 0x6B --电源管理,典型值:0x00(正常启用)
  51. local MPU6XXX_RA_PWR_MGMT_2 = 0x6C
  52. local MPU6XXX_RA_WHO_AM_I = 0x75
  53. --器件ID检测
  54. local function mpu6xxx_check()
  55. i2c.send(i2cid, MPU6XXX_ADDRESS_AD0_LOW, MPU6XXX_RA_WHO_AM_I)--读器件地址
  56. sys.wait(50)
  57. local revData = i2c.recv(i2cid, MPU6XXX_ADDRESS_AD0_LOW, 1)
  58. if revData:byte() ~= nil then
  59. i2cslaveaddr = MPU6XXX_ADDRESS_AD0_LOW
  60. else
  61. i2c.send(i2cid, MPU6XXX_ADDRESS_AD0_HIGH, MPU6XXX_RA_WHO_AM_I)--读器件地址
  62. sys.wait(50)
  63. local revData = i2c.recv(i2cid, MPU6XXX_ADDRESS_AD0_HIGH, 1)
  64. if revData:byte() ~= nil then
  65. i2cslaveaddr = MPU6XXX_ADDRESS_AD0_HIGH
  66. else
  67. log.info("i2c", "Can't find device")
  68. return 1
  69. end
  70. end
  71. i2c.send(i2cid, i2cslaveaddr, MPU6XXX_RA_WHO_AM_I)--读器件地址
  72. sys.wait(50)
  73. local revData = i2c.recv(i2cid, i2cslaveaddr, 1)
  74. log.info("Device i2c address is#:", revData:toHex())
  75. if revData:byte() == MPU6050_WHO_AM_I then
  76. deviceid = MPU6050_WHO_AM_I
  77. log.info("Device i2c id is: MPU6050")
  78. elseif revData:byte() == MPU6500_WHO_AM_I then
  79. deviceid = MPU6500_WHO_AM_I
  80. log.info("Device i2c id is: MPU6500")
  81. elseif revData:byte() == MPU9250_WHO_AM_I then
  82. deviceid = MPU9250_WHO_AM_I
  83. log.info("Device i2c id is: MPU9250")
  84. elseif revData:byte() == ICM20608G_WHO_AM_I then
  85. deviceid = ICM20608G_WHO_AM_I
  86. log.info("Device i2c id is: ICM20608G")
  87. elseif revData:byte() == ICM20608D_WHO_AM_I then
  88. deviceid = ICM20608D_WHO_AM_I
  89. log.info("Device i2c id is: ICM20608D")
  90. else
  91. log.info("i2c", "Can't find device")
  92. return 1
  93. end
  94. return 0
  95. end
  96. --器件初始化
  97. local function mpu6xxx_init()
  98. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_PWR_MGMT_1, 0x80})--复位
  99. sys.wait(100)
  100. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_PWR_MGMT_1, 0x00})--唤醒
  101. sys.wait(100)
  102. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_SMPLRT_DIV, 0x07})--陀螺仪采样率,典型值:0x07(125Hz)
  103. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_CONFIG, 0x06})--低通滤波频率,典型值:0x06(5Hz)
  104. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_GYRO_CONFIG, 0x18})--陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  105. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_ACCEL_CONFIG, 0x01})--加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  106. --i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_FIFO_EN, 0x00})--关闭fifo
  107. --i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_INT_ENABLE, 0x00})--关闭所有中断
  108. --i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_USER_CTRL, 0x00})--I2C主模式关闭
  109. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_PWR_MGMT_1, 0x01})--设置x轴的pll为参考
  110. i2c.send(i2cid, i2cslaveaddr, {MPU6XXX_RA_PWR_MGMT_2, 0x00})--加速度计与陀螺仪开启
  111. log.info("i2c init_ok")
  112. end
  113. --获取温度的原始数据
  114. local function mpu6xxx_get_temp_raw()
  115. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_TEMP_OUT_H)--获取的地址
  116. local buffer = i2c.recv(i2cid, i2cslaveaddr, 2)--获取2字节
  117. local temp = string.unpack(">h",buffer)
  118. --log.info("get_temp_raw type: "..type(buffer).." hex: "..buffer:toHex().." temp: "..temp)
  119. return temp or 0
  120. end
  121. --获取加速度计的原始数据
  122. local function mpu6xxx_get_accel_raw()
  123. local accel={x=nil,y=nil,z=nil}
  124. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_ACCEL_XOUT_H)--获取的地址
  125. local x = i2c.recv(i2cid, i2cslaveaddr, 2)--获取6字节
  126. accel.x = string.unpack(">h",x)
  127. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_ACCEL_YOUT_H)--获取的地址
  128. local y = i2c.recv(i2cid, i2cslaveaddr, 2)--获取6字节
  129. accel.y = string.unpack(">h",y)
  130. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_ACCEL_ZOUT_H)--获取的地址
  131. local z = i2c.recv(i2cid, i2cslaveaddr, 2)--获取6字节
  132. accel.z = string.unpack(">h",z)
  133. --log.info("get_accel_raw: x="..x:toHex().." y="..y:toHex().." z="..z:toHex())
  134. return accel or 0
  135. end
  136. --获取陀螺仪的原始数据
  137. local function mpu6xxx_get_gyro_raw()
  138. local gyro={x=nil,y=nil,z=nil}
  139. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_GYRO_XOUT_H)--获取的地址
  140. local x = i2c.recv(i2cid, i2cslaveaddr, 2)--获取6字节
  141. gyro.x = string.unpack(">h",x)
  142. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_GYRO_YOUT_H)--获取的地址
  143. local y = i2c.recv(i2cid, i2cslaveaddr, 2)--获取6字节
  144. gyro.y = string.unpack(">h",y)
  145. i2c.send(i2cid, i2cslaveaddr,MPU6XXX_RA_GYRO_ZOUT_H)--获取的地址
  146. local z = i2c.recv(i2cid, i2cslaveaddr, 2)--获取6字节
  147. gyro.z = string.unpack(">h",z)
  148. return gyro or 0
  149. end
  150. --获取温度的原始数据
  151. local function mpu6xxx_get_temp()
  152. local temp=nil
  153. local tmp = mpu6xxx_get_temp_raw()
  154. if deviceid == MPU6050_WHO_AM_I then
  155. temp = tmp / MPU60X0_TEMP_SEN + MPU60X0_TEMP_OFFSET
  156. else
  157. temp = tmp / MPU6500_TEMP_SEN + MPU6500_TEMP_OFFSET
  158. end
  159. return temp
  160. end
  161. --获取加速度计的数据,单位: mg
  162. local function mpu6xxx_get_accel()
  163. local accel={x=nil,y=nil,z=nil}
  164. local tmp = mpu6xxx_get_accel_raw()
  165. accel.x = tmp.x*1000/MPU6XXX_ACCEL_SEN
  166. accel.y = tmp.y*1000/MPU6XXX_ACCEL_SEN
  167. accel.z = tmp.z*1000/MPU6XXX_ACCEL_SEN
  168. return accel
  169. end
  170. --获取陀螺仪的数据,单位: deg / 10s
  171. local function mpu6xxx_get_gyro()
  172. local gyro={x=nil,y=nil,z=nil}
  173. local tmp = mpu6xxx_get_gyro_raw()
  174. gyro.x = tmp.x*100/MPU6XXX_GYRO_SEN
  175. gyro.y = tmp.y*100/MPU6XXX_GYRO_SEN
  176. gyro.z = tmp.z*100/MPU6XXX_GYRO_SEN
  177. return gyro
  178. end
  179. local function mpu6xxx()
  180. sys.wait(4000)
  181. if i2c.setup(i2cid,i2c.SLOW) ~= i2c.SLOW then
  182. log.error("testI2c.init","fail")
  183. return
  184. end
  185. if mpu6xxx_check()~= 0 then
  186. return
  187. end
  188. mpu6xxx_init()
  189. while true do
  190. local t = mpu6xxx_get_temp()
  191. log.info("6050temptest", t)
  192. local a = mpu6xxx_get_accel()
  193. log.info("6050acceltest", "accel.x",a.x,"accel.y",a.y,"accel.z",a.z)
  194. local g = mpu6xxx_get_gyro()
  195. log.info("6050gyrotest", "gyro.x",g.x,"gyro.y",g.y,"gyro.z",g.z)
  196. sys.wait(1000)
  197. end
  198. end
  199. sys.taskInit(mpu6xxx)