add: libfota需要兼容老的hmeta库, 没有hwver函数
[LuatOS.git] / script / libs / pca9685.lua
blob5545076d6b05436bfe10c12e164565827e3c0d9e
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"
14 sys = require("sys")
15 pca9685=require("pca9685")
17 local i2c_id = 1
18 sys.taskInit(
19 function()
20 i2c.setup(i2c_id,i2c.SLOW)
21 sys.wait(1000)
22 pca9685.init(i2c_id,60)
23 sys.wait(1000)
24 local i=0
25 while true do
26 pca9685.setpwm(i2c_id,0,i)
27 if i >= 100 then
28 i=0
29 end
30 i=i+10
31 sys.wait(2000)
32 end
33 end
36 sys.run()
43 local pca9685={}
48 local PCA_Addr = 0x40 --pwm通道地址
49 local PCA_Model =0x00 --工作模式:读1/写0
50 local LED0_ON_L =0x06
51 local LED0_ON_H =0x07
52 local LED0_OFF_L= 0x08
53 local LED0_OFF_H =0x09
54 local PCA_Pre = 0xFE
56 local function pca9685_write(i2cId,addr, data)
57 local ret
58 ret=i2c.send(i2cId, PCA_Addr, { addr, data })
59 sys.wait(15)
60 if ret then
61 return true
62 else
63 return
64 end
65 end
67 local function pca9685_read(i2cId,addr)
68 i2c.send(i2cId, PCA_Addr, addr)
69 sys.wait(5)
70 local data = i2c.recv(i2cId,0x40, 1)
71 if #data==0 then
72 return
73 else
74 return data
75 end
76 end
77 --[[
78 pca9685 初始化
79 @api pca9685.init(i2cId,hz)
80 @int i2cid 使用的i2c id, 或者是软件i2c的实例
81 @int hz pca9685的输出频率
82 @return 成功返回true 失败返回nil
84 function pca9685.init(i2cId,hz)
85 local ret=0
86 ret=pca9685_write(i2cId,PCA_Model,0x00)
87 if not ret then
88 return
89 end
90 ret=pca9685.setfreq(i2cId,hz)
91 if not ret then
92 return
93 end
94 pca9685.setpwm(i2cId,0,0);
95 pca9685.setpwm(i2cId,1,0);
96 pca9685.setpwm(i2cId,2,0);
97 pca9685.setpwm(i2cId,3,0);
98 pca9685.setpwm(i2cId,4,0);
99 pca9685.setpwm(i2cId,5,0);
100 pca9685.setpwm(i2cId,6,0);
101 pca9685.setpwm(i2cId,7,0);
102 pca9685.setpwm(i2cId,8,0);
103 pca9685.setpwm(i2cId,9,0);
104 pca9685.setpwm(i2cId,10,0);
105 pca9685.setpwm(i2cId,11,0);
106 pca9685.setpwm(i2cId,12,0);
107 pca9685.setpwm(i2cId,13,0);
108 pca9685.setpwm(i2cId,14,0);
109 pca9685.setpwm(i2cId,15,0);
110 sys.wait(100)
111 return true
115 --[[
116 pca9685 设置频率
117 @api pca9685.setfreq(i2cId,freq)
118 @int i2cid 使用的i2c id, 或者是软件i2c的实例
119 @int freq pca9685的输出频率,范围为24HZ~1526HZ
120 @return 成功返回true 失败返回nil
122 function pca9685.setfreq(i2cId,freq) --PCA9685频率设置
123 local prescale
124 local oldmode
125 local newmode
126 local prescaleval
127 local ret
128 prescaleval = 25000000;
129 prescaleval = prescaleval / 4096
130 prescaleval = prescaleval / freq
131 prescaleval = prescaleval - 1
132 prescale = math.floor(prescaleval + 0.5)
133 oldmode = string.toHex(pca9685_read(i2cId,PCA_Model))
134 newmode = (oldmode & 0x7F)|0x10
135 ret=pca9685_write(i2cId,PCA_Model, newmode)
136 if not ret then
137 return
139 ret=pca9685_write(i2cId,PCA_Pre, prescale)
140 if not ret then
141 return
143 ret=pca9685_write(i2cId,PCA_Model, oldmode)
144 if not ret then
145 return
147 sys.wait(5)
148 ret=pca9685_write(i2cId,PCA_Model, oldmode|0xa1)
149 if not ret then
150 return
152 return true
155 --[[
156 pca9685 设置PWM占空比
157 @api pca9685.setpwm(i2cId,num, duty_cycle)
158 @int i2cid 使用的i2c id, 或者是软件i2c的实例
159 @int num 通道号
160 @int duty_cycle 占空比 0~100
161 @return 成功返回true 失败返回nil
163 function pca9685.setpwm(i2cId,num, duty_cycle)
164 local on = 0
165 if duty_cycle==50 then
166 on=0
167 else
168 on=math.floor(4096*((100-duty_cycle)/100))
170 local off=on+math.floor(4096*(duty_cycle/100))
171 local ret = i2c.send(i2cId, PCA_Addr, { LED0_ON_L + 4 * num, on & 0xFF, on >> 8, off & 0xFF, off >> 8 })
172 sys.wait(5)
173 if ret==false then
174 return
176 return true
178 return pca9685