-
Notifications
You must be signed in to change notification settings - Fork 1
/
gsa_ds18b20.lua
219 lines (200 loc) · 5.62 KB
/
gsa_ds18b20.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
--------------------------------------------------------------------------------
-- DS18B20 one wire module for NODEMCU
-- Sandor Attila Gerendi
-- LICENCE: http://opensource.org/licenses/MIT
--------------------------------------------------------------------------------
local table = table
local string = string
local ow = ow
local STARTCONVO=0x44
local COPYSCRATCH=0x48
local READSCRATCH=0xBE
local WRITESCRATCH=0x4E
local SP_TEMP_LSB=1
local SP_TEMP_MSB=2
local SP_HIGH_ALARM_TEMP=3
local SP_LOW_ALARM_TEMP=4
local SP_CONFIGURATION=5
local SP_COUNT_REMAIN=7
local SP_COUNT_PER_C=8
local RES_9_BIT = 0x1F
local RES_10_BIT = 0x3F
local RES_11_BIT = 0x5F
local RES_12_BIT = 0x7F
local MODEL_DS18S20=0x10
local MODEL_DS1820=0x10
local MODEL_DS18B20=0x28
local MODEL_DS1822=0x22
local MODEL_DS1825=0x3B
function setup(pin)
ow.setup(pin)
end
function bs2hex(b)
local t = {}
for i = 1, #b do
t[i] = string.format('%02X', b:byte(i))
end
return table.concat(t)
end
function hex2bs(h)
local t={}
for k in h:gmatch"(%x%x)" do
table.insert(t,string.char(tonumber(k,16)))
end
return table.concat(t)
end
function adr2adr(addr)
if addr == nil then return false, 'nil-address' end
if #addr == 16 then
addr = hex2bs(addr)
end
if addr:byte(8) ~= ow.crc8(string.sub(addr,1,7)) then
return false, 'invalid-address'
end
return true, addr
end
function get_conv_time(res)
local t = 750
if res == RES_9_BIT then t = 94
elseif res == RES_10_BIT then t = 188
elseif res == RES_11_BIT then t = 375
end
return t
end
function extract_temp(addr, scrp)
local sgn, temp
local msb = scrp:byte(SP_TEMP_MSB)
local lsb = scrp:byte(SP_TEMP_LSB)
if addr:byte(1) == MODEL_DS18S20 then
sgn = bit.isset(msb, 7)
temp = lsb
temp = bit.lshift(bit.band(temp, 0xfff0), 3)
if sgn then temp = -1 * temp end
temp = temp - 16 + (scrp:byte(SP_COUNT_PER_C) - bit.lshift(scrp:byte(SP_COUNT_REMAIN),7)) / scrp:byte(SP_COUNT_PER_C)
else
temp = lsb + msb * 256
if (temp > 32767) then temp = temp - 65536 end
end
temp = temp * 625
return temp
end
function get_resolution(pin, addr, pow)
local st, scrp
st, addr = adr2adr(addr)
if not st then return st, addr end
if addr:byte(1) == DS18S20MODEL then
return false, 'not-suported'
end
local st, scrp = read_scrp(pin, addr, pow)
if not st then return st, scrp end
return true, scrp:byte(SP_CONFIGURATION)
end
function set_resolution(pin, addr, res, pow)
local st, scrp
st, addr = adr2adr(addr)
if not st then return st, addr end
if addr:byte(1) == DS18S20MODEL then
return false, 'not-suported'
end
st, scrp = read_scrp(pin, addr, pow)
if not st then return st, scrp end
scrp = scrp:sub(1,SP_CONFIGURATION-1)..string.char(res)..scrp:sub(SP_CONFIGURATION+1)
write_scrp(pin, addr, scrp, pow)
return true
end
function get_devices(pin, hex)
local t = {}
ow.reset_search(pin)
repeat
local addr = ow.search(pin)
if(addr ~= nil) then
local fb = addr:byte(1)
if (fb==MODEL_DS18S20)or(fb==MODEL_DS18B20)or(fb==MODEL_DS1822)or(fb==MODEL_DS1825) then
if hex then addr = bs2hex(addr) end
table.insert(t, addr)
end
end
coroutine.yield(50)
until (addr == nil)
ow.reset_search(pin)
return t
end
function write_scrp(pin, addr, scrp, pow)
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, WRITESCRATCH)
ow.write(pin, scrp:byte(SP_HIGH_ALARM_TEMP))
ow.write(pin, scrp:byte(SP_LOW_ALARM_TEMP))
if addr:byte(1) ~= MODEL_DS18S20 then
ow.write(pin, scrp:byte(SP_CONFIGURATION))
end
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, COPYSCRATCH, pow)
if pow then
coroutine.yield(300)
else
coroutine.yield(200)
end
end
function read_scrp(pin, addr, pow)
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, READSCRATCH, pow)
local b = ow.read_bytes(pin, 8)
if ow.crc8(b) ~= ow.read(pin) then
return false, "CRC error"
else
return true, b
end
end
function get_temp(pin, addr, pow, res)
local st, scrp
st, addr = adr2adr(addr)
if not st then return st, addr end
ow.reset(pin)
ow.select(pin, addr)
ow.write(pin, STARTCONVO, pow)
coroutine.yield(get_conv_time(res))
st, scrp = read_scrp(pin, addr, pow)
if not st then return st, scrp end
return true, extract_temp(addr, scrp)
end
function get_temperatures(pin, addr_list, pow, res)
if addr_list == nil then addr_list = get_devices(pin) end
if #addr_list == 0 then return false, 'no-devices' end
ow.reset(pin)
ow.skip(pin)
ow.write(pin, STARTCONVO, pow)
coroutine.yield(get_conv_time(res))
local result = {}
local st, addr, scrp
for i = 1, #addr_list do
st, addr = adr2adr(addr_list[i])
if not st then
print("invalid address", bs2hex(addr_list[i]), scrp)
else
st, scrp = read_scrp(pin, addr, pow)
if st == true then
result[bs2hex(addr)] = extract_temp(addr, scrp)
else
print("problem reading", bs2hex(addr), scrp)
end
end
end
return true, result
end
return {
bs2he=bs2hex,
hex2bs=hex2bs,
get_devices=get_devices,
get_temp=get_temp,
get_temperatures=get_temperatures,
setup=setup,
set_resolution=set_resolution,
get_resolution=get_resolution,
RES_9_BIT=RES_9_BIT,
RES_10_BIT=RES_10_BIT,
RES_11_BIT=RES_11_BIT,
RES_12_BIT=RES_12_BIT
}