ak8963.lua 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. --[[
  2. @module ak8963
  3. @summary ak8963 地磁传感器
  4. @version 1.0
  5. @date 2023.06.07
  6. @author Dozingfiretruck
  7. @usage
  8. --注意:因使用了sys.wait()所有api需要在协程中使用
  9. -- 用法实例
  10. local ak8963 = require "ak8963"
  11. i2cid = 0
  12. i2c_speed = i2c.FAST
  13. sys.taskInit(function()
  14. i2c.setup(i2cid,i2c_speed)
  15. ak8963.init(i2cid)--初始化,传入i2c_id
  16. while 1 do
  17. sys.wait(100)
  18. local mag = ak8963.get_mag()--获取地磁仪
  19. log.info("ak8963 mag", "mag.x",mag.x,"mag.y",mag.y,"mag.z",mag.z)
  20. end
  21. end)
  22. ]]
  23. local ak8963 = {}
  24. local sys = require "sys"
  25. local i2cid
  26. local i2cslaveaddr
  27. local deviceid
  28. local AK8963_ADDRESS_AD0_LOW = 0x0C
  29. local AK8963_ADDRESS_AD0_HIGH = 0x0D
  30. ---器件通讯地址
  31. local AK8963_WHO_AM_I = 0x48 -- AK8963
  32. ---AK8963所用地址
  33. -- Read-only Reg
  34. local AK8963_RA_WHO_AM_I = 0x00
  35. local AK8963_REG_INFO = 0x01
  36. local AK8963_REG_ST1 = 0x02
  37. local AK8963_REG_HXL = 0x03
  38. local AK8963_REG_HXH = 0x04
  39. local AK8963_REG_HYL = 0x05
  40. local AK8963_REG_HYH = 0x06
  41. local AK8963_REG_HZL = 0x07
  42. local AK8963_REG_HZH = 0x08
  43. local AK8963_REG_ST2 = 0x09
  44. -- Write/Read Reg
  45. local AK8963_REG_CNTL1 = 0x0A
  46. local AK8963_REG_CNTL2 = 0x0B
  47. local AK8963_REG_ASTC = 0x0C
  48. local AK8963_REG_TS1 = 0x0D
  49. local AK8963_REG_TS2 = 0x0E
  50. local AK8963_REG_I2CDIS = 0x0F
  51. -- Read-only Reg (ROM)
  52. local AK8963_REG_ASAX = 0x10
  53. local AK8963_REG_ASAY = 0x11
  54. local AK8963_REG_ASAZ = 0x12
  55. -- Status
  56. local AK8963_STATUS_DRDY = 0x01
  57. local AK8963_STATUS_DOR = 0x02
  58. local AK8963_STATUS_HOFL = 0x08
  59. local AK8963_ASAX
  60. local AK8963_ASAY
  61. local AK8963_ASAZ
  62. --器件ID检测
  63. local function ak8963_check()
  64. i2c.send(i2cid, AK8963_ADDRESS_AD0_LOW, AK8963_RA_WHO_AM_I)--读器件地址
  65. sys.wait(50)
  66. local revData = i2c.recv(i2cid, AK8963_ADDRESS_AD0_LOW, 1)
  67. if revData:byte() ~= nil then
  68. i2cslaveaddr = AK8963_ADDRESS_AD0_LOW
  69. else
  70. i2c.send(i2cid, AK8963_ADDRESS_AD0_HIGH, AK8963_RA_WHO_AM_I)--读器件地址
  71. sys.wait(50)
  72. local revData = i2c.recv(i2cid, AK8963_ADDRESS_AD0_HIGH, 1)
  73. if revData:byte() ~= nil then
  74. i2cslaveaddr = AK8963_ADDRESS_AD0_HIGH
  75. else
  76. log.info("i2c", "Can't find device")
  77. return false
  78. end
  79. end
  80. i2c.send(i2cid, i2cslaveaddr, AK8963_RA_WHO_AM_I)--读器件地址
  81. sys.wait(50)
  82. local revData = i2c.recv(i2cid, i2cslaveaddr, 1)
  83. log.info("Device i2c address is:", revData:toHex())
  84. if revData:byte() == AK8963_WHO_AM_I then
  85. deviceid = AK8963_WHO_AM_I
  86. log.info("Device i2c id is: AK8963")
  87. else
  88. log.info("i2c", "Can't find device")
  89. return false
  90. end
  91. return true
  92. end
  93. --[[
  94. ak8963初始化
  95. @api ak8963.init(i2c_id)
  96. @number 所在的i2c总线id
  97. @return bool 成功返回true
  98. @usage
  99. ak8963.init(0)
  100. ]]
  101. function ak8963.init(i2c_id)
  102. i2cid = i2c_id
  103. sys.wait(20)
  104. if ak8963_check() then
  105. i2c.send(i2cid, i2cslaveaddr, {AK8963_REG_CNTL1, 0x0F})
  106. i2c.send(i2cid, i2cslaveaddr,AK8963_REG_ASAX)
  107. AK8963_ASAX = i2c.recv(i2cid, i2cslaveaddr, 1):byte()
  108. i2c.send(i2cid, i2cslaveaddr,AK8963_REG_ASAY)
  109. AK8963_ASAY = i2c.recv(i2cid, i2cslaveaddr, 1):byte()
  110. i2c.send(i2cid, i2cslaveaddr,AK8963_REG_ASAZ)
  111. AK8963_ASAZ = i2c.recv(i2cid, i2cslaveaddr, 1):byte()
  112. i2c.send(i2cid, i2cslaveaddr, {AK8963_REG_CNTL1, 0x10})
  113. sys.wait(10)
  114. log.info("ak8963 init_ok")
  115. return true
  116. end
  117. return false
  118. end
  119. --获取地磁计的原始数据
  120. local function ak8963_get_mag_raw()
  121. local mag={x=nil,y=nil,z=nil}
  122. i2c.send(i2cid, i2cslaveaddr,AK8963_REG_HXL)
  123. local x = i2c.recv(i2cid, i2cslaveaddr, 2)
  124. _,mag.x = pack.unpack(x,"<h")
  125. i2c.send(i2cid, i2cslaveaddr,AK8963_REG_HYL)
  126. local y = i2c.recv(i2cid, i2cslaveaddr, 2)
  127. _,mag.y = pack.unpack(y,"<h")
  128. i2c.send(i2cid, i2cslaveaddr,AK8963_REG_HZL)
  129. local z = i2c.recv(i2cid, i2cslaveaddr, 2)
  130. _,mag.z = pack.unpack(z,"<h")
  131. return mag or 0
  132. end
  133. --[[
  134. 获取地磁仪的数据
  135. @api ak8963.get_mag()
  136. @return table 地磁仪数据
  137. @usage
  138. local mag = ak8963.get_mag()--获取地磁仪
  139. log.info("ak8963 mag", "mag.x",mag.x,"mag.y",mag.y,"mag.z",mag.z)
  140. ]]
  141. function ak8963.get_mag()
  142. local mag={x=nil,y=nil,z=nil}
  143. i2c.send(i2cid, i2cslaveaddr, {AK8963_REG_CNTL1, 0x11})
  144. sys.wait(10)
  145. local tmp = ak8963_get_mag_raw()
  146. mag.x = tmp.x*((AK8963_ASAX-128)*0.5/128+1)
  147. mag.y = tmp.y*((AK8963_ASAY-128)*0.5/128+1)
  148. mag.z = tmp.z*((AK8963_ASAZ-128)*0.5/128+1)
  149. return mag
  150. end
  151. return ak8963