mpu6xxx.lua 9.3 KB

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