pca9685.lua 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. --[[
  2. @module pca9685
  3. @summary pca9685 16路PWM驱动舵机
  4. @version 1.0
  5. @date 2023.12.26
  6. @author xwtx
  7. @usage
  8. --注意:因使用了sys.wait()所有api需要在协程中使用
  9. -- 用法实例
  10. PROJECT = "pca9685"
  11. VERSION = "1.0.0"
  12. sys = require("sys")
  13. pca9685=require("pca9685")
  14. local i2c_id = 1
  15. sys.taskInit(
  16. function()
  17. i2c.setup(i2c_id,i2c.SLOW)
  18. sys.wait(1000)
  19. pca9685.init(i2c_id,60)
  20. sys.wait(1000)
  21. local i=0
  22. while true do
  23. pca9685.setpwm(i2c_id,0,i)
  24. if i >= 100 then
  25. i=0
  26. end
  27. i=i+10
  28. sys.wait(2000)
  29. end
  30. end
  31. )
  32. sys.run()
  33. ]]
  34. local pca9685={}
  35. local PCA_Addr = 0x40 --pwm通道地址
  36. local PCA_Model =0x00 --工作模式:读1/写0
  37. local LED0_ON_L =0x06
  38. local LED0_ON_H =0x07
  39. local LED0_OFF_L= 0x08
  40. local LED0_OFF_H =0x09
  41. local PCA_Pre = 0xFE
  42. local function pca9685_write(i2cId,addr, data)
  43. local ret
  44. ret=i2c.send(i2cId, PCA_Addr, { addr, data })
  45. sys.wait(15)
  46. if ret then
  47. return true
  48. else
  49. return
  50. end
  51. end
  52. local function pca9685_read(i2cId,addr)
  53. i2c.send(i2cId, PCA_Addr, addr)
  54. sys.wait(5)
  55. local data = i2c.recv(i2cId,0x40, 1)
  56. if #data==0 then
  57. return
  58. else
  59. return data
  60. end
  61. end
  62. --[[
  63. pca9685 初始化
  64. @api pca9685.init(i2cId,hz)
  65. @int i2cid 使用的i2c id, 或者是软件i2c的实例
  66. @int hz pca9685的输出频率
  67. @return 成功返回true 失败返回nil
  68. ]]
  69. function pca9685.init(i2cId,hz)
  70. local ret=0
  71. ret=pca9685_write(i2cId,PCA_Model,0x00)
  72. if not ret then
  73. return
  74. end
  75. ret=pca9685.setfreq(i2cId,hz)
  76. if not ret then
  77. return
  78. end
  79. pca9685.setpwm(i2cId,0,0);
  80. pca9685.setpwm(i2cId,1,0);
  81. pca9685.setpwm(i2cId,2,0);
  82. pca9685.setpwm(i2cId,3,0);
  83. pca9685.setpwm(i2cId,4,0);
  84. pca9685.setpwm(i2cId,5,0);
  85. pca9685.setpwm(i2cId,6,0);
  86. pca9685.setpwm(i2cId,7,0);
  87. pca9685.setpwm(i2cId,8,0);
  88. pca9685.setpwm(i2cId,9,0);
  89. pca9685.setpwm(i2cId,10,0);
  90. pca9685.setpwm(i2cId,11,0);
  91. pca9685.setpwm(i2cId,12,0);
  92. pca9685.setpwm(i2cId,13,0);
  93. pca9685.setpwm(i2cId,14,0);
  94. pca9685.setpwm(i2cId,15,0);
  95. sys.wait(100)
  96. return true
  97. end
  98. --[[
  99. pca9685 设置频率
  100. @api pca9685.setfreq(i2cId,freq)
  101. @int i2cid 使用的i2c id, 或者是软件i2c的实例
  102. @int freq pca9685的输出频率,范围为24HZ~1526HZ
  103. @return 成功返回true 失败返回nil
  104. ]]
  105. function pca9685.setfreq(i2cId,freq) --PCA9685频率设置
  106. local prescale
  107. local oldmode
  108. local newmode
  109. local prescaleval
  110. local ret
  111. prescaleval = 25000000;
  112. prescaleval = prescaleval / 4096
  113. prescaleval = prescaleval / freq
  114. prescaleval = prescaleval - 1
  115. prescale = math.floor(prescaleval + 0.5)
  116. oldmode = string.toHex(pca9685_read(i2cId,PCA_Model))
  117. newmode = (oldmode & 0x7F)|0x10
  118. ret=pca9685_write(i2cId,PCA_Model, newmode)
  119. if not ret then
  120. return
  121. end
  122. ret=pca9685_write(i2cId,PCA_Pre, prescale)
  123. if not ret then
  124. return
  125. end
  126. ret=pca9685_write(i2cId,PCA_Model, oldmode)
  127. if not ret then
  128. return
  129. end
  130. sys.wait(5)
  131. ret=pca9685_write(i2cId,PCA_Model, oldmode|0xa1)
  132. if not ret then
  133. return
  134. end
  135. return true
  136. end
  137. --[[
  138. pca9685 设置PWM占空比
  139. @api pca9685.setpwm(i2cId,num, duty_cycle)
  140. @int i2cid 使用的i2c id, 或者是软件i2c的实例
  141. @int num 通道号
  142. @int duty_cycle 占空比 0~100
  143. @return 成功返回true 失败返回nil
  144. ]]
  145. function pca9685.setpwm(i2cId,num, duty_cycle)
  146. local on = 0
  147. if duty_cycle==50 then
  148. on=0
  149. else
  150. on=math.floor(4096*((100-duty_cycle)/100))
  151. end
  152. local off=on+math.floor(4096*(duty_cycle/100))
  153. local ret = i2c.send(i2cId, PCA_Addr, { LED0_ON_L + 4 * num, on & 0xFF, on >> 8, off & 0xFF, off >> 8 })
  154. sys.wait(5)
  155. if ret==false then
  156. return
  157. end
  158. return true
  159. end
  160. return pca9685