init
This commit is contained in:
parent
b07f1d53e9
commit
a7a2dcbc7a
209
DS1820.lua
Normal file
209
DS1820.lua
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- DS18B20 one wire module for NODEMCU
|
||||||
|
-- NODEMCU TEAM
|
||||||
|
-- LICENCE: http://opensource.org/licenses/MIT
|
||||||
|
-- @voborsky, @devsaurus, TerryE 26 Mar 2017
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local modname = ...
|
||||||
|
|
||||||
|
-- Used modules and functions
|
||||||
|
local type, tostring, pcall, ipairs =
|
||||||
|
type, tostring, pcall, ipairs
|
||||||
|
-- Local functions
|
||||||
|
local ow_setup, ow_search, ow_select, ow_read, ow_read_bytes, ow_write, ow_crc8,
|
||||||
|
ow_reset, ow_reset_search, ow_skip, ow_depower =
|
||||||
|
ow.setup, ow.search, ow.select, ow.read, ow.read_bytes, ow.write, ow.crc8,
|
||||||
|
ow.reset, ow.reset_search, ow.skip, ow.depower
|
||||||
|
|
||||||
|
local node_task_post, node_task_LOW_PRIORITY = node.task.post, node.task.LOW_PRIORITY
|
||||||
|
local string_char, string_dump = string.char, string.dump
|
||||||
|
local now, tmr_create, tmr_ALARM_SINGLE = tmr.now, tmr.create, tmr.ALARM_SINGLE
|
||||||
|
local table_sort, table_concat = table.sort, table.concat
|
||||||
|
local file_open = file.open
|
||||||
|
local conversion
|
||||||
|
|
||||||
|
local DS18B20FAMILY = 0x28
|
||||||
|
local DS1920FAMILY = 0x10 -- and DS18S20 series
|
||||||
|
local CONVERT_T = 0x44
|
||||||
|
local READ_SCRATCHPAD = 0xBE
|
||||||
|
local READ_POWERSUPPLY= 0xB4
|
||||||
|
local MODE = 1
|
||||||
|
|
||||||
|
local pin, cb, unit = 3
|
||||||
|
local status = {}
|
||||||
|
|
||||||
|
local debugPrint = function() return end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Implementation
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local function enable_debug()
|
||||||
|
debugPrint = function (...) print(now(),' ', ...) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function to_string(addr, esc)
|
||||||
|
if type(addr) == 'string' and #addr == 8 then
|
||||||
|
return ( esc == true and
|
||||||
|
'"\\%u\\%u\\%u\\%u\\%u\\%u\\%u\\%u"' or
|
||||||
|
'%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(addr:byte(1,8))
|
||||||
|
else
|
||||||
|
return tostring(addr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function readout(self)
|
||||||
|
local next = false
|
||||||
|
local sens = self.sens
|
||||||
|
local temp = self.temp
|
||||||
|
for i, s in ipairs(sens) do
|
||||||
|
if status[i] == 1 then
|
||||||
|
ow_reset(pin)
|
||||||
|
local addr = s:sub(1,8)
|
||||||
|
ow_select(pin, addr) -- select the sensor
|
||||||
|
ow_write(pin, READ_SCRATCHPAD, MODE)
|
||||||
|
local data = ow_read_bytes(pin, 9)
|
||||||
|
|
||||||
|
local t=(data:byte(1)+data:byte(2)*256)
|
||||||
|
-- t is actually signed so process the sign bit and adjust for fractional bits
|
||||||
|
-- the DS18B20 family has 4 fractional bits and the DS18S20s, 1 fractional bit
|
||||||
|
t = ((t <= 32767) and t or t - 65536) *
|
||||||
|
((addr:byte(1) == DS18B20FAMILY) and 625 or 5000)
|
||||||
|
local crc, b9 = ow_crc8(string.sub(data,1,8)), data:byte(9)
|
||||||
|
|
||||||
|
if unit == 'F' then
|
||||||
|
t = (t * 18)/10 + 320000
|
||||||
|
elseif unit == 'K' then
|
||||||
|
t = t + 2731500
|
||||||
|
end
|
||||||
|
local sgn = t<0 and -1 or 1
|
||||||
|
local tA = sgn*t
|
||||||
|
local tH=tA/10000
|
||||||
|
local tL=(tA%10000)/1000 + ((tA%1000)/100 >= 5 and 1 or 0)
|
||||||
|
|
||||||
|
if tH and (t~=850000) then
|
||||||
|
debugPrint(to_string(addr),(sgn<0 and "-" or "")..tH.."."..tL, crc, b9)
|
||||||
|
if crc==b9 then temp[addr]=t end
|
||||||
|
status[i] = 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next = next or status[i] == 0
|
||||||
|
end
|
||||||
|
if next then
|
||||||
|
node_task_post(node_task_LOW_PRIORITY, function() return conversion(self) end)
|
||||||
|
else
|
||||||
|
--sens = {}
|
||||||
|
if cb then
|
||||||
|
node_task_post(node_task_LOW_PRIORITY, function() return cb(temp) end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
conversion = (function (self)
|
||||||
|
local sens = self.sens
|
||||||
|
local powered_only = true
|
||||||
|
for _, s in ipairs(sens) do powered_only = powered_only and s:byte(9) ~= 1 end
|
||||||
|
if powered_only then
|
||||||
|
debugPrint("starting conversion: all sensors")
|
||||||
|
ow_reset(pin)
|
||||||
|
ow_skip(pin) -- skip ROM selection, talk to all sensors
|
||||||
|
ow_write(pin, CONVERT_T, MODE) -- and start conversion
|
||||||
|
for i, _ in ipairs(sens) do status[i] = 1 end
|
||||||
|
else
|
||||||
|
local started = false
|
||||||
|
for i, s in ipairs(sens) do
|
||||||
|
if status[i] == 0 then
|
||||||
|
local addr, parasite = s:sub(1,8), s:byte(9) == 1
|
||||||
|
if parasite and started then break end -- do not start concurrent conversion of powered and parasite
|
||||||
|
debugPrint("starting conversion:", to_string(addr), parasite and "parasite" or "")
|
||||||
|
ow_reset(pin)
|
||||||
|
ow_select(pin, addr) -- select the sensor
|
||||||
|
ow_write(pin, CONVERT_T, MODE) -- and start conversion
|
||||||
|
status[i] = 1
|
||||||
|
if parasite then break end -- parasite sensor blocks bus during conversion
|
||||||
|
started = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tmr_create():alarm(750, tmr_ALARM_SINGLE, function() return readout(self) end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function _search(self, lcb, lpin, search, save)
|
||||||
|
self.temp = {}
|
||||||
|
if search then self.sens = {}; status = {} end
|
||||||
|
local sens = self.sens
|
||||||
|
pin = lpin or pin
|
||||||
|
|
||||||
|
local addr
|
||||||
|
if not search and #sens == 0 then
|
||||||
|
-- load addreses if available
|
||||||
|
debugPrint ("geting addreses from flash")
|
||||||
|
local s,check,a = pcall(dofile, "ds18b20_save.lc")
|
||||||
|
if s and check == "ds18b20" then
|
||||||
|
for i = 1, #a do sens[i] = a[i] end
|
||||||
|
end
|
||||||
|
debugPrint (#sens, "addreses found")
|
||||||
|
end
|
||||||
|
|
||||||
|
ow_setup(pin)
|
||||||
|
if search or #sens == 0 then
|
||||||
|
ow_reset_search(pin)
|
||||||
|
-- ow_target_search(pin,0x28)
|
||||||
|
-- search the first device
|
||||||
|
addr = ow_search(pin)
|
||||||
|
else
|
||||||
|
for i, _ in ipairs(sens) do status[i] = 0 end
|
||||||
|
end
|
||||||
|
local function cycle()
|
||||||
|
if addr then
|
||||||
|
local crc=ow_crc8(addr:sub(1,7))
|
||||||
|
if (crc==addr:byte(8)) and ((addr:byte(1)==DS1920FAMILY) or (addr:byte(1)==DS18B20FAMILY)) then
|
||||||
|
ow_reset(pin)
|
||||||
|
ow_select(pin, addr)
|
||||||
|
ow_write(pin, READ_POWERSUPPLY, MODE)
|
||||||
|
local parasite = (ow_read(pin)==0 and 1 or 0)
|
||||||
|
sens[#sens+1]= addr..string_char(parasite)
|
||||||
|
status[#sens] = 0
|
||||||
|
debugPrint("contact: ", to_string(addr), parasite == 1 and "parasite" or "")
|
||||||
|
end
|
||||||
|
addr = ow_search(pin)
|
||||||
|
node_task_post(node_task_LOW_PRIORITY, cycle)
|
||||||
|
else
|
||||||
|
ow_depower(pin)
|
||||||
|
-- place powered sensors first
|
||||||
|
table_sort(sens, function(a, b) return a:byte(9)<b:byte(9) end) -- parasite
|
||||||
|
-- save sensor addreses
|
||||||
|
if save then
|
||||||
|
debugPrint ("saving addreses to flash")
|
||||||
|
|
||||||
|
local addr_list = {}
|
||||||
|
for i =1, #sens do
|
||||||
|
local s = sens[i]
|
||||||
|
addr_list[i] = to_string(s:sub(1,8), true)..('.."\\%u"'):format(s:byte(9))
|
||||||
|
end
|
||||||
|
local save_statement = 'return "ds18b20", {' .. table_concat(addr_list, ',') .. '}'
|
||||||
|
debugPrint (save_statement)
|
||||||
|
local save_file = file_open("ds18b20_save.lc","w")
|
||||||
|
save_file:write(string_dump(loadstring(save_statement)))
|
||||||
|
save_file:close()
|
||||||
|
end
|
||||||
|
-- end save sensor addreses
|
||||||
|
if lcb then node_task_post(node_task_LOW_PRIORITY, lcb) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
cycle()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function read_temp(self, lcb, lpin, lunit, force_search, save_search)
|
||||||
|
cb, unit = lcb, lunit or unit
|
||||||
|
_search(self, function() return conversion(self) end, lpin, force_search, save_search)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set module name as parameter of require and return module table
|
||||||
|
local M = {
|
||||||
|
sens = {},
|
||||||
|
temp = {},
|
||||||
|
C = 'C', F = 'F', K = 'K',
|
||||||
|
read_temp = read_temp, enable_debug = enable_debug
|
||||||
|
}
|
||||||
|
_G[modname or 'ds18b20'] = M
|
||||||
|
return M
|
||||||
Binary file not shown.
1
Ground/.~lock.датчики.ods#
Normal file
1
Ground/.~lock.датчики.ods#
Normal file
@ -0,0 +1 @@
|
|||||||
|
,zoviet,libreboot,30.03.2025 23:32,file:///home/zoviet/.config/libreoffice/4;
|
||||||
209
Ground/DS1820.lua
Normal file
209
Ground/DS1820.lua
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- DS18B20 one wire module for NODEMCU
|
||||||
|
-- NODEMCU TEAM
|
||||||
|
-- LICENCE: http://opensource.org/licenses/MIT
|
||||||
|
-- @voborsky, @devsaurus, TerryE 26 Mar 2017
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local modname = ...
|
||||||
|
|
||||||
|
-- Used modules and functions
|
||||||
|
local type, tostring, pcall, ipairs =
|
||||||
|
type, tostring, pcall, ipairs
|
||||||
|
-- Local functions
|
||||||
|
local ow_setup, ow_search, ow_select, ow_read, ow_read_bytes, ow_write, ow_crc8,
|
||||||
|
ow_reset, ow_reset_search, ow_skip, ow_depower =
|
||||||
|
ow.setup, ow.search, ow.select, ow.read, ow.read_bytes, ow.write, ow.crc8,
|
||||||
|
ow.reset, ow.reset_search, ow.skip, ow.depower
|
||||||
|
|
||||||
|
local node_task_post, node_task_LOW_PRIORITY = node.task.post, node.task.LOW_PRIORITY
|
||||||
|
local string_char, string_dump = string.char, string.dump
|
||||||
|
local now, tmr_create, tmr_ALARM_SINGLE = tmr.now, tmr.create, tmr.ALARM_SINGLE
|
||||||
|
local table_sort, table_concat = table.sort, table.concat
|
||||||
|
local file_open = file.open
|
||||||
|
local conversion
|
||||||
|
|
||||||
|
local DS18B20FAMILY = 0x28
|
||||||
|
local DS1920FAMILY = 0x10 -- and DS18S20 series
|
||||||
|
local CONVERT_T = 0x44
|
||||||
|
local READ_SCRATCHPAD = 0xBE
|
||||||
|
local READ_POWERSUPPLY= 0xB4
|
||||||
|
local MODE = 1
|
||||||
|
|
||||||
|
local pin, cb, unit = 3
|
||||||
|
local status = {}
|
||||||
|
|
||||||
|
local debugPrint = function() return end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Implementation
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local function enable_debug()
|
||||||
|
debugPrint = function (...) print(now(),' ', ...) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function to_string(addr, esc)
|
||||||
|
if type(addr) == 'string' and #addr == 8 then
|
||||||
|
return ( esc == true and
|
||||||
|
'"\\%u\\%u\\%u\\%u\\%u\\%u\\%u\\%u"' or
|
||||||
|
'%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X '):format(addr:byte(1,8))
|
||||||
|
else
|
||||||
|
return tostring(addr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function readout(self)
|
||||||
|
local next = false
|
||||||
|
local sens = self.sens
|
||||||
|
local temp = self.temp
|
||||||
|
for i, s in ipairs(sens) do
|
||||||
|
if status[i] == 1 then
|
||||||
|
ow_reset(pin)
|
||||||
|
local addr = s:sub(1,8)
|
||||||
|
ow_select(pin, addr) -- select the sensor
|
||||||
|
ow_write(pin, READ_SCRATCHPAD, MODE)
|
||||||
|
local data = ow_read_bytes(pin, 9)
|
||||||
|
|
||||||
|
local t=(data:byte(1)+data:byte(2)*256)
|
||||||
|
-- t is actually signed so process the sign bit and adjust for fractional bits
|
||||||
|
-- the DS18B20 family has 4 fractional bits and the DS18S20s, 1 fractional bit
|
||||||
|
t = ((t <= 32767) and t or t - 65536) *
|
||||||
|
((addr:byte(1) == DS18B20FAMILY) and 625 or 5000)
|
||||||
|
local crc, b9 = ow_crc8(string.sub(data,1,8)), data:byte(9)
|
||||||
|
|
||||||
|
if unit == 'F' then
|
||||||
|
t = (t * 18)/10 + 320000
|
||||||
|
elseif unit == 'K' then
|
||||||
|
t = t + 2731500
|
||||||
|
end
|
||||||
|
local sgn = t<0 and -1 or 1
|
||||||
|
local tA = sgn*t
|
||||||
|
local tH=tA/10000
|
||||||
|
local tL=(tA%10000)/1000 + ((tA%1000)/100 >= 5 and 1 or 0)
|
||||||
|
|
||||||
|
if tH and (t~=850000) then
|
||||||
|
debugPrint(to_string(addr),(sgn<0 and "-" or "")..tH.."."..tL, crc, b9)
|
||||||
|
if crc==b9 then temp[addr]=t end
|
||||||
|
status[i] = 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next = next or status[i] == 0
|
||||||
|
end
|
||||||
|
if next then
|
||||||
|
node_task_post(node_task_LOW_PRIORITY, function() return conversion(self) end)
|
||||||
|
else
|
||||||
|
--sens = {}
|
||||||
|
if cb then
|
||||||
|
node_task_post(node_task_LOW_PRIORITY, function() return cb(temp) end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
conversion = (function (self)
|
||||||
|
local sens = self.sens
|
||||||
|
local powered_only = true
|
||||||
|
for _, s in ipairs(sens) do powered_only = powered_only and s:byte(9) ~= 1 end
|
||||||
|
if powered_only then
|
||||||
|
debugPrint("starting conversion: all sensors")
|
||||||
|
ow_reset(pin)
|
||||||
|
ow_skip(pin) -- skip ROM selection, talk to all sensors
|
||||||
|
ow_write(pin, CONVERT_T, MODE) -- and start conversion
|
||||||
|
for i, _ in ipairs(sens) do status[i] = 1 end
|
||||||
|
else
|
||||||
|
local started = false
|
||||||
|
for i, s in ipairs(sens) do
|
||||||
|
if status[i] == 0 then
|
||||||
|
local addr, parasite = s:sub(1,8), s:byte(9) == 1
|
||||||
|
if parasite and started then break end -- do not start concurrent conversion of powered and parasite
|
||||||
|
debugPrint("starting conversion:", to_string(addr), parasite and "parasite" or "")
|
||||||
|
ow_reset(pin)
|
||||||
|
ow_select(pin, addr) -- select the sensor
|
||||||
|
ow_write(pin, CONVERT_T, MODE) -- and start conversion
|
||||||
|
status[i] = 1
|
||||||
|
if parasite then break end -- parasite sensor blocks bus during conversion
|
||||||
|
started = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tmr_create():alarm(750, tmr_ALARM_SINGLE, function() return readout(self) end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function _search(self, lcb, lpin, search, save)
|
||||||
|
self.temp = {}
|
||||||
|
if search then self.sens = {}; status = {} end
|
||||||
|
local sens = self.sens
|
||||||
|
pin = lpin or pin
|
||||||
|
|
||||||
|
local addr
|
||||||
|
if not search and #sens == 0 then
|
||||||
|
-- load addreses if available
|
||||||
|
debugPrint ("geting addreses from flash")
|
||||||
|
local s,check,a = pcall(dofile, "ds18b20_save.lc")
|
||||||
|
if s and check == "ds18b20" then
|
||||||
|
for i = 1, #a do sens[i] = a[i] end
|
||||||
|
end
|
||||||
|
debugPrint (#sens, "addreses found")
|
||||||
|
end
|
||||||
|
|
||||||
|
ow_setup(pin)
|
||||||
|
if search or #sens == 0 then
|
||||||
|
ow_reset_search(pin)
|
||||||
|
-- ow_target_search(pin,0x28)
|
||||||
|
-- search the first device
|
||||||
|
addr = ow_search(pin)
|
||||||
|
else
|
||||||
|
for i, _ in ipairs(sens) do status[i] = 0 end
|
||||||
|
end
|
||||||
|
local function cycle()
|
||||||
|
if addr then
|
||||||
|
local crc=ow_crc8(addr:sub(1,7))
|
||||||
|
if (crc==addr:byte(8)) and ((addr:byte(1)==DS1920FAMILY) or (addr:byte(1)==DS18B20FAMILY)) then
|
||||||
|
ow_reset(pin)
|
||||||
|
ow_select(pin, addr)
|
||||||
|
ow_write(pin, READ_POWERSUPPLY, MODE)
|
||||||
|
local parasite = (ow_read(pin)==0 and 1 or 0)
|
||||||
|
sens[#sens+1]= addr..string_char(parasite)
|
||||||
|
status[#sens] = 0
|
||||||
|
debugPrint("contact: ", to_string(addr), parasite == 1 and "parasite" or "")
|
||||||
|
end
|
||||||
|
addr = ow_search(pin)
|
||||||
|
node_task_post(node_task_LOW_PRIORITY, cycle)
|
||||||
|
else
|
||||||
|
ow_depower(pin)
|
||||||
|
-- place powered sensors first
|
||||||
|
table_sort(sens, function(a, b) return a:byte(9)<b:byte(9) end) -- parasite
|
||||||
|
-- save sensor addreses
|
||||||
|
if save then
|
||||||
|
debugPrint ("saving addreses to flash")
|
||||||
|
|
||||||
|
local addr_list = {}
|
||||||
|
for i =1, #sens do
|
||||||
|
local s = sens[i]
|
||||||
|
addr_list[i] = to_string(s:sub(1,8), true)..('.."\\%u"'):format(s:byte(9))
|
||||||
|
end
|
||||||
|
local save_statement = 'return "ds18b20", {' .. table_concat(addr_list, ',') .. '}'
|
||||||
|
debugPrint (save_statement)
|
||||||
|
local save_file = file_open("ds18b20_save.lc","w")
|
||||||
|
save_file:write(string_dump(loadstring(save_statement)))
|
||||||
|
save_file:close()
|
||||||
|
end
|
||||||
|
-- end save sensor addreses
|
||||||
|
if lcb then node_task_post(node_task_LOW_PRIORITY, lcb) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
cycle()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function read_temp(self, lcb, lpin, lunit, force_search, save_search)
|
||||||
|
cb, unit = lcb, lunit or unit
|
||||||
|
_search(self, function() return conversion(self) end, lpin, force_search, save_search)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set module name as parameter of require and return module table
|
||||||
|
local M = {
|
||||||
|
sens = {},
|
||||||
|
temp = {},
|
||||||
|
C = 'C', F = 'F', K = 'K',
|
||||||
|
read_temp = read_temp, enable_debug = enable_debug
|
||||||
|
}
|
||||||
|
_G[modname or 'ds18b20'] = M
|
||||||
|
return M
|
||||||
2
Ground/flash.sh
Normal file
2
Ground/flash.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
python3 -m esptool --port /dev/ttyUSB0 erase_flash
|
||||||
|
python3 -m esptool --port /dev/ttyUSB0 write_flash -fm dio 0x00000 nodemcu-release-9-modules-2024-09-15-16-23-23-integer.bin
|
||||||
43
Ground/init.lua
Normal file
43
Ground/init.lua
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
local t = require("DS1820")
|
||||||
|
local pin = 1
|
||||||
|
|
||||||
|
function adc_read()
|
||||||
|
local ao = adc.read(0)
|
||||||
|
print(ao)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function readout(temp)
|
||||||
|
if t.sens then
|
||||||
|
print("Total number of DS18B20 sensors: ".. #t.sens)
|
||||||
|
for i, s in ipairs(t.sens) do
|
||||||
|
print(string.format(" sensor #%d address: %s%s", i, ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(s:byte(1,8)), s:byte(9) == 1 and " (parasite)" or ""))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for addr, temp in pairs(temp) do
|
||||||
|
--if tonumber(temp) < 20000 then
|
||||||
|
print(string.format("Sensor %s: %s °C", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)), temp))
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Module can be released when it is no longer needed
|
||||||
|
--t = nil
|
||||||
|
--package.loaded["ds18b20"] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function read()
|
||||||
|
t:read_temp(readout, pin, t.C)
|
||||||
|
end
|
||||||
|
|
||||||
|
if adc.force_init_mode(adc.INIT_ADC)
|
||||||
|
then
|
||||||
|
node.restart()
|
||||||
|
return -- don't bother continuing, the restart is scheduled
|
||||||
|
end
|
||||||
|
|
||||||
|
timer = tmr.create()
|
||||||
|
timer:register(7000, tmr.ALARM_AUTO,read)
|
||||||
|
timer:start()
|
||||||
|
|
||||||
|
sensorstimer = tmr.create()
|
||||||
|
sensorstimer:register(5000, tmr.ALARM_AUTO, adc_read)
|
||||||
|
sensorstimer:start()
|
||||||
BIN
Ground/nodemcu-release-9-modules-2024-09-15-16-23-23-integer.bin
Normal file
BIN
Ground/nodemcu-release-9-modules-2024-09-15-16-23-23-integer.bin
Normal file
Binary file not shown.
BIN
Ground/датчики.ods
Normal file
BIN
Ground/датчики.ods
Normal file
Binary file not shown.
76
README.md
76
README.md
@ -1,2 +1,76 @@
|
|||||||
# braga_firmware
|
# Бродильная камера на ESP 8266
|
||||||
|
|
||||||
|
## Необходимые детали
|
||||||
|
|
||||||
|
1. Wemos D1 Mini
|
||||||
|
|
||||||
|
2. Датчик интенсивности ультрафиолета GUVA-S12SD
|
||||||
|
|
||||||
|
3. Датчик температуры и влажности DHT-11
|
||||||
|
|
||||||
|
4. Датчик давления и температуры BMP280
|
||||||
|
|
||||||
|
|
||||||
|
## Схема подключения
|
||||||
|
|
||||||
|
DHT 11:
|
||||||
|
|
||||||
|
"-" - GND
|
||||||
|
|
||||||
|
S - D1
|
||||||
|
|
||||||
|
V - 3.3
|
||||||
|
|
||||||
|
BME280:
|
||||||
|
|
||||||
|
SDA - D3
|
||||||
|
|
||||||
|
SCL - D4
|
||||||
|
|
||||||
|
G - G
|
||||||
|
|
||||||
|
V - 3.3
|
||||||
|
|
||||||
|
GUVA-S12SD:
|
||||||
|
|
||||||
|
SIO - AO
|
||||||
|
|
||||||
|
GND - G
|
||||||
|
|
||||||
|
VCC - 3.3
|
||||||
|
|
||||||
|
## Прошивка
|
||||||
|
|
||||||
|
Понадобятся:
|
||||||
|
|
||||||
|
1. esptool - https://docs.espressif.com/projects/esptool/en/latest/esp32/
|
||||||
|
|
||||||
|
2. git
|
||||||
|
|
||||||
|
3. python2 и python3
|
||||||
|
|
||||||
|
По желанию ESPlorer - https://esp8266.ru/forum/threads/esplorer.34/
|
||||||
|
|
||||||
|
Загрузка прошивки с необходимыми модулями:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/Zoviet/meteo
|
||||||
|
cd meteo
|
||||||
|
bash flash.sh
|
||||||
|
|
||||||
|
```
|
||||||
|
После загрузки прошивки устройство сразу готово к работе.
|
||||||
|
|
||||||
|
## Подключение к Wi-Fi
|
||||||
|
|
||||||
|
При подключении к новой сети устройство поднимает веб-сервер. В списке доступных Wi-Fi сетей появится сеть meteo, к которой следует подключиться. В запросе авторизации появится форма для выбора сети, к которой планируется подключить устройство, и форма ввода пароля от нее.
|
||||||
|
|
||||||
|
## Проверка работособности
|
||||||
|
|
||||||
|
При включении и/или перезагрузке устройство, даже не подключенное к Интернету, отдает в виртуальный COM-порт данные датчиков. Прочитать из можно с помощью ESPlorer либо любой программы для чтения COM-порта.
|
||||||
|
|
||||||
|
## Протокол обмена с сервером
|
||||||
|
|
||||||
|
TCP, порт 4999, ожидаемый формат - json, закодированный в Base64.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
Schematic/schematic.fzz
Normal file
BIN
Schematic/schematic.fzz
Normal file
Binary file not shown.
BIN
Schematic/schematic_МП.png
Normal file
BIN
Schematic/schematic_МП.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
BIN
Schematic/schematic_схема.png
Normal file
BIN
Schematic/schematic_схема.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
3
firmware.sh
Normal file
3
firmware.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
dmesg | grep tty
|
||||||
|
python3 -m esptool --port /dev/ttyUSB0 erase_flash
|
||||||
|
python3 -m esptool --port /dev/ttyUSB0 write_flash -fm dio 0x00000 nodemcu-release-17-modules-2025-01-01-15-13-22-float.bin
|
||||||
66
flash.sh
Executable file
66
flash.sh
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if read -p "Подключите плату к USB и нажмите ENTER: " start; then
|
||||||
|
line=$(dmesg | grep 'ttyUSB' | tail -1)
|
||||||
|
if [[ $line == *"attached"* ]]; then
|
||||||
|
port=`echo "$line" | sed 's/.*ttyUSB\(.\)$/\1/'`
|
||||||
|
else
|
||||||
|
printf '\033[91mУстройство не найдено!\033[0m\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
printf '\033[92mУстройство найдено на порту: '$port'\033[0m\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if read -p "Для начала прошивки нажмите ENTER: " start; then
|
||||||
|
cd Firmware
|
||||||
|
firmware=($(find -name '*.bin'))
|
||||||
|
if [[ $firmware == *"nodemcu"* ]]; then
|
||||||
|
printf '\033[92mНайдена прошивка: '$firmware'\033[0m\n\n'
|
||||||
|
printf '\n\033[92mСтираем существующую прошивку:\033[0m\n\n'
|
||||||
|
python3 -m esptool --port /dev/ttyUSB$port erase_flash
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
printf '\033[91mОшибка устройства!\033[0m\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
printf '\n\033[92mЗаливаем прошивку nodemcu для Lua:\033[0m\n\n'
|
||||||
|
python3 -m esptool --port /dev/ttyUSB$port write_flash -fm dio 0x00000 $firmware
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
printf '\033[91mОшибка устройства!\033[0m\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
printf '\033[91mПрошивка не найдена!\033[0m\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ../
|
||||||
|
|
||||||
|
if read -p "Для начала заливки скетча нажмите ENTER: " start; then
|
||||||
|
echo 'Заливаем Lua скетч:'
|
||||||
|
python2 luatool.py --port /dev/ttyUSB$port --src init.lua --dest init.lua --verbose --restart --baud 115200
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
printf '\033[91mОшибка заливки скетча!\033[0m\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '\n\033[92mЖдем перезагрузки устройства:\033[0m\n\n'
|
||||||
|
sleep 5
|
||||||
|
mac=$(python3 -m esptool --port /dev/ttyUSB$port read_mac)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
printf '\033[91mОшибка чтения из устройства!\033[0m\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
guid=`echo "$mac" | grep -m 1 MAC | sed 's/\://g' | sed 's/MAC //g'`
|
||||||
|
echo 'GUID устройства: '$guid
|
||||||
|
first_byte=${guid:0:2}
|
||||||
|
new_byte=$((16#$first_byte + 2 | bc))
|
||||||
|
new_first_byte=`echo "ibase=10; obase=16; ${new_byte}" | bc | sed 's/[A-Z]/\L&/g'`
|
||||||
|
if (( ${#new_first_byte} == 1 )); then
|
||||||
|
new_first_byte='0'$new_first_byte
|
||||||
|
fi
|
||||||
|
guid=`echo "$guid" | sed 's/^'$first_byte'/'$new_first_byte'/'`
|
||||||
|
printf '\033[92mОпределен guid устройства: '$guid' \033[0m\n'
|
||||||
|
|
||||||
|
printf '\033[92mУстановка успешно завершена, ID устройства: \033[0m'$guid'\n'
|
||||||
129
init.lua
Normal file
129
init.lua
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
timing = 5000 -- Sending timer
|
||||||
|
srv = nil -- TCP client
|
||||||
|
uid = '' -- MAC UID
|
||||||
|
dhtpin = 1 -- DHT11 pin
|
||||||
|
sda, scl = 3, 4 -- BME280 pins
|
||||||
|
alt = 320 -- altitude of the measurement place
|
||||||
|
|
||||||
|
-- Weather vars
|
||||||
|
|
||||||
|
T = - 300 -- BME temp
|
||||||
|
P = - 300 -- BME pressure
|
||||||
|
curAlt = - 300 -- BME altitude
|
||||||
|
TB = - 300 -- DHT temp
|
||||||
|
TH = - 300 -- DHT humidity
|
||||||
|
UF = 0 -- UF index
|
||||||
|
|
||||||
|
-- Read the solar sensor
|
||||||
|
|
||||||
|
function adc_read()
|
||||||
|
UF = adc.read(0)
|
||||||
|
print('UF index: '..UF)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read the BME280 sensor
|
||||||
|
|
||||||
|
function bme_read()
|
||||||
|
T, P, H, QNH = bme280.read(alt)
|
||||||
|
local Tsgn = (T < 0 and -1 or 1); T = Tsgn*T
|
||||||
|
print(string.format("T=%s%d.%02d", Tsgn<0 and "-" or "", T/100, T%100))
|
||||||
|
print(string.format("QFE=%d.%03d", P/1000, P%1000))
|
||||||
|
print(string.format("QNH=%d.%03d", QNH/1000, QNH%1000))
|
||||||
|
P = bme280.baro()
|
||||||
|
curAlt = bme280.altitude(P, QNH)
|
||||||
|
local curAltsgn = (curAlt < 0 and -1 or 1); curAlt = curAltsgn*curAlt
|
||||||
|
print(string.format("altitude=%s%d.%02d", curAltsgn<0 and "-" or "", curAlt/100, curAlt%100))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read the DHT11 sensor
|
||||||
|
|
||||||
|
function dht_read()
|
||||||
|
status, temp, humi, temp_dec, humi_dec = dht.read(dhtpin)
|
||||||
|
if status == dht.OK then
|
||||||
|
TB = temp
|
||||||
|
TH = humi
|
||||||
|
print("DHT Temperature:"..temp..";".."Humidity:"..humi)
|
||||||
|
elseif status == dht.ERROR_CHECKSUM then
|
||||||
|
print( "DHT Checksum error." )
|
||||||
|
elseif status == dht.ERROR_TIMEOUT then
|
||||||
|
print( "DHT timed out." )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Prepare data for TCP server
|
||||||
|
|
||||||
|
function data_out()
|
||||||
|
local pack = {}
|
||||||
|
pack['id'] = uid
|
||||||
|
pack['bme'] = {['temp'] = T,['press'] = P,['alt'] = curAlt}
|
||||||
|
pack['dht'] = {['temp'] = TB,['humi'] = TH}
|
||||||
|
pack['uf'] = UF
|
||||||
|
return encoder.toBase64(sjson.encode(pack))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Exchange data with server
|
||||||
|
|
||||||
|
function tcp()
|
||||||
|
srv:connect(4999,"braga.ulgrad.ru")
|
||||||
|
srv:on("connection", function(sck, c)
|
||||||
|
print('connection')
|
||||||
|
sck:send(data_out().."\r\n")
|
||||||
|
end)
|
||||||
|
srv:on("disconnection", function(sck,c)
|
||||||
|
print('disconnection')
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- On Internet connect
|
||||||
|
|
||||||
|
function on_connect()
|
||||||
|
-- Generate UID from MAC address
|
||||||
|
uid = string.gsub(wifi.ap.getmac(),':','')
|
||||||
|
print("Connected to wifi as: " .. wifi.sta.getip())
|
||||||
|
ssid,password,bssid_set,bssid = wifi.sta.getconfig()
|
||||||
|
sensor_start()
|
||||||
|
print(
|
||||||
|
"\nCurrent Station configuration:"
|
||||||
|
.."\nSSID : "..ssid
|
||||||
|
.."\nPassword : "..password
|
||||||
|
.."\nBSSID_set : "..bssid_set
|
||||||
|
.."\nBSSID: "..bssid
|
||||||
|
.."\nUID:"..uid
|
||||||
|
.."\nClient IP:"..wifi.sta.getip().."\n"
|
||||||
|
)
|
||||||
|
srv = net.createConnection(net.TCP, 0)
|
||||||
|
if srv then
|
||||||
|
print('TCP Connection start')
|
||||||
|
tcptimer:start()
|
||||||
|
else
|
||||||
|
print('Error connect to TCP')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Setup ADC
|
||||||
|
|
||||||
|
if adc.force_init_mode(adc.INIT_ADC)
|
||||||
|
then
|
||||||
|
node.restart()
|
||||||
|
return -- don't bother continuing, the restart is scheduled
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Setup sensors
|
||||||
|
|
||||||
|
i2c.setup(0, sda, scl, i2c.SLOW) -- call i2c.setup() only once
|
||||||
|
bme280.setup()
|
||||||
|
|
||||||
|
-- Setup timers
|
||||||
|
|
||||||
|
tcptimer = tmr.create()
|
||||||
|
tcptimer:register(12000, tmr.ALARM_AUTO,tcp)
|
||||||
|
|
||||||
|
inittimer = tmr.create()
|
||||||
|
inittimer:register(5000, tmr.ALARM_SINGLE, function()
|
||||||
|
adc_read()
|
||||||
|
bme_read()
|
||||||
|
dht_read()
|
||||||
|
enduser_setup.start('meteo',on_connect)
|
||||||
|
end)
|
||||||
|
|
||||||
|
inittimer:start()
|
||||||
358
luatool.py
Executable file
358
luatool.py
Executable file
@ -0,0 +1,358 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
#
|
||||||
|
# ESP8266 luatool
|
||||||
|
# Author e-mail: 4ref0nt@gmail.com
|
||||||
|
# Site: http://esp8266.ru
|
||||||
|
# Contributions from: https://github.com/sej7278
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it under
|
||||||
|
# the terms of the GNU General Public License as published by the Free Software
|
||||||
|
# Foundation; either version 2 of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||||
|
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import serial
|
||||||
|
from time import sleep
|
||||||
|
import socket
|
||||||
|
import argparse
|
||||||
|
from os.path import basename
|
||||||
|
|
||||||
|
|
||||||
|
tqdm_installed = True
|
||||||
|
try:
|
||||||
|
from tqdm import tqdm
|
||||||
|
except ImportError, e:
|
||||||
|
if e.message == 'No module named tqdm':
|
||||||
|
tqdm_installed = False
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
version = "0.6.4"
|
||||||
|
|
||||||
|
|
||||||
|
class TransportError(Exception):
|
||||||
|
"""Custom exception to represent errors with a transport
|
||||||
|
"""
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.message
|
||||||
|
|
||||||
|
class AbstractTransport:
|
||||||
|
def __init__(self):
|
||||||
|
raise NotImplementedError('abstract transports cannot be instantiated.')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
raise NotImplementedError('Function not implemented')
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
raise NotImplementedError('Function not implemented')
|
||||||
|
|
||||||
|
def writeln(self, data, check=1):
|
||||||
|
raise NotImplementedError('Function not implemented')
|
||||||
|
|
||||||
|
def writer(self, data):
|
||||||
|
self.writeln("file.writeline([==[" + data + "]==])\r")
|
||||||
|
|
||||||
|
def performcheck(self, expected):
|
||||||
|
line = ''
|
||||||
|
char = ''
|
||||||
|
i = -1
|
||||||
|
while char != chr(62): # '>'
|
||||||
|
char = self.read(1)
|
||||||
|
if char == '':
|
||||||
|
raise Exception('No proper answer from MCU')
|
||||||
|
if char == chr(13) or char == chr(10): # LF or CR
|
||||||
|
if line != '':
|
||||||
|
line = line.strip()
|
||||||
|
if line+'\r' == expected and not args.bar:
|
||||||
|
sys.stdout.write(" -> ok")
|
||||||
|
elif line+'\r' != expected:
|
||||||
|
if line[:4] == "lua:":
|
||||||
|
sys.stdout.write("\r\n\r\nLua ERROR: %s" % line)
|
||||||
|
raise Exception('ERROR from Lua interpreter\r\n\r\n')
|
||||||
|
else:
|
||||||
|
expected = expected.split("\r")[0]
|
||||||
|
sys.stdout.write("\r\n\r\nERROR")
|
||||||
|
sys.stdout.write("\r\n send string : '%s'" % expected)
|
||||||
|
sys.stdout.write("\r\n expected echo : '%s'" % expected)
|
||||||
|
sys.stdout.write("\r\n but got answer : '%s'" % line)
|
||||||
|
sys.stdout.write("\r\n\r\n")
|
||||||
|
raise Exception('Error sending data to MCU\r\n\r\n')
|
||||||
|
line = ''
|
||||||
|
else:
|
||||||
|
line += char
|
||||||
|
if char == chr(62) and expected[i] == char:
|
||||||
|
char = ''
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
|
class SerialTransport(AbstractTransport):
|
||||||
|
def __init__(self, port, baud, delay):
|
||||||
|
self.port = port
|
||||||
|
self.baud = baud
|
||||||
|
self.serial = None
|
||||||
|
self.delay = delay
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.serial = serial.Serial(port, baud)
|
||||||
|
except serial.SerialException as e:
|
||||||
|
raise TransportError(e.strerror)
|
||||||
|
|
||||||
|
self.serial.timeout = 3
|
||||||
|
self.serial.interCharTimeout = 3
|
||||||
|
|
||||||
|
def writeln(self, data, check=1):
|
||||||
|
if self.serial.inWaiting() > 0:
|
||||||
|
self.serial.flushInput()
|
||||||
|
if len(data) > 0 and not args.bar:
|
||||||
|
sys.stdout.write("\r\n->")
|
||||||
|
sys.stdout.write(data.split("\r")[0])
|
||||||
|
self.serial.write(data)
|
||||||
|
sleep(self.delay)
|
||||||
|
if check > 0:
|
||||||
|
self.performcheck(data)
|
||||||
|
elif not args.bar:
|
||||||
|
sys.stdout.write(" -> send without check")
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
return self.serial.read(length)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.serial.flush()
|
||||||
|
self.serial.close()
|
||||||
|
|
||||||
|
|
||||||
|
class TcpSocketTransport(AbstractTransport):
|
||||||
|
def __init__(self, host, port):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.socket = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
except socket.error as e:
|
||||||
|
raise TransportError(e.strerror)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.socket.connect((host, port))
|
||||||
|
except socket.error as e:
|
||||||
|
raise TransportError(e.strerror)
|
||||||
|
# read intro from telnet server (see telnet_srv.lua)
|
||||||
|
self.socket.recv(50)
|
||||||
|
|
||||||
|
def writeln(self, data, check=1):
|
||||||
|
if len(data) > 0 and not args.bar:
|
||||||
|
sys.stdout.write("\r\n->")
|
||||||
|
sys.stdout.write(data.split("\r")[0])
|
||||||
|
self.socket.sendall(data)
|
||||||
|
if check > 0:
|
||||||
|
self.performcheck(data)
|
||||||
|
elif not args.bar:
|
||||||
|
sys.stdout.write(" -> send without check")
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
return self.socket.recv(length)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
def decidetransport(cliargs):
|
||||||
|
if cliargs.ip:
|
||||||
|
data = cliargs.ip.split(':')
|
||||||
|
host = data[0]
|
||||||
|
if len(data) == 2:
|
||||||
|
port = int(data[1])
|
||||||
|
else:
|
||||||
|
port = 23
|
||||||
|
return TcpSocketTransport(host, port)
|
||||||
|
else:
|
||||||
|
return SerialTransport(cliargs.port, cliargs.baud, cliargs.delay)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# parse arguments or use defaults
|
||||||
|
parser = argparse.ArgumentParser(description='ESP8266 Lua script uploader.')
|
||||||
|
parser.add_argument('-p', '--port', default='/dev/ttyUSB0', help='Device name, default /dev/ttyUSB0')
|
||||||
|
parser.add_argument('-b', '--baud', default=9600, help='Baudrate, default 9600')
|
||||||
|
parser.add_argument('-f', '--src', default='main.lua', help='Source file on computer, default main.lua')
|
||||||
|
parser.add_argument('-t', '--dest', default=None, help='Destination file on MCU, default to source file name')
|
||||||
|
parser.add_argument('-c', '--compile', action='store_true', help='Compile lua to lc after upload')
|
||||||
|
parser.add_argument('-r', '--restart', action='store_true', help='Restart MCU after upload')
|
||||||
|
parser.add_argument('-d', '--dofile', action='store_true', help='Run the Lua script after upload')
|
||||||
|
parser.add_argument('-v', '--verbose', action='store_true', help="Show progress messages.")
|
||||||
|
parser.add_argument('-a', '--append', action='store_true', help='Append source file to destination file.')
|
||||||
|
parser.add_argument('-l', '--list', action='store_true', help='List files on device')
|
||||||
|
parser.add_argument('-w', '--wipe', action='store_true', help='Delete all lua/lc files on device.')
|
||||||
|
parser.add_argument('-i', '--id', action='store_true', help='Query the modules chip id.')
|
||||||
|
parser.add_argument('-e', '--echo', action='store_true', help='Echo output of MCU until script is terminated.')
|
||||||
|
parser.add_argument('--bar', action='store_true', help='Show a progress bar for uploads instead of printing each line')
|
||||||
|
parser.add_argument('--delay', default=0.3, help='Delay in seconds between each write.', type=float)
|
||||||
|
parser.add_argument('--delete', default=None, help='Delete a lua/lc file from device.')
|
||||||
|
parser.add_argument('--ip', default=None, help='Connect to a telnet server on the device (--ip IP[:port])')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
transport = decidetransport(args)
|
||||||
|
|
||||||
|
if args.bar and not tqdm_installed:
|
||||||
|
sys.stdout.write("You must install the tqdm library to use the bar feature\n")
|
||||||
|
sys.stdout.write("To install, at the prompt type: \"pip install tqdm\"\n")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if args.list:
|
||||||
|
transport.writeln("local l = file.list();for k,v in pairs(l) do print('name:'..k..', size:'..v)end\r", 0)
|
||||||
|
while True:
|
||||||
|
char = transport.read(1)
|
||||||
|
if char == '' or char == chr(62):
|
||||||
|
break
|
||||||
|
sys.stdout.write(char)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if args.id:
|
||||||
|
transport.writeln("=node.chipid()\r", 0)
|
||||||
|
id=""
|
||||||
|
while True:
|
||||||
|
char = transport.read(1)
|
||||||
|
if char == '' or char == chr(62):
|
||||||
|
break
|
||||||
|
if char.isdigit():
|
||||||
|
id += char
|
||||||
|
print("\n"+id)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if args.wipe:
|
||||||
|
transport.writeln("local l = file.list();for k,v in pairs(l) do print(k)end\r", 0)
|
||||||
|
file_list = []
|
||||||
|
fn = ""
|
||||||
|
while True:
|
||||||
|
char = transport.read(1)
|
||||||
|
if char == '' or char == chr(62):
|
||||||
|
break
|
||||||
|
if char not in ['\r', '\n']:
|
||||||
|
fn += char
|
||||||
|
else:
|
||||||
|
if fn:
|
||||||
|
file_list.append(fn.strip())
|
||||||
|
fn = ''
|
||||||
|
for fn in file_list[1:]: # first line is the list command sent to device
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("Delete file {} from device.\r\n".format(fn))
|
||||||
|
transport.writeln("file.remove(\"" + fn + "\")\r")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if args.delete:
|
||||||
|
transport.writeln("file.remove(\"" + args.delete + "\")\r")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if args.dest is None:
|
||||||
|
args.dest = basename(args.src)
|
||||||
|
|
||||||
|
# open source file for reading
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
f = open(args.src, "rt")
|
||||||
|
except:
|
||||||
|
import os
|
||||||
|
base_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
f = open(os.path.join(base_dir, args.src), "rt")
|
||||||
|
os.chdir(base_dir)
|
||||||
|
except:
|
||||||
|
sys.stderr.write("Could not open input file \"%s\"\n" % args.src)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Verify the selected file will not exceed the size of the serial buffer.
|
||||||
|
# The size of the buffer is 256. This script does not accept files with
|
||||||
|
# lines longer than 230 characters to have some room for command overhead.
|
||||||
|
num_lines = 0
|
||||||
|
for ln in f:
|
||||||
|
if len(ln) > 230:
|
||||||
|
sys.stderr.write("File \"%s\" contains a line with more than 240 "
|
||||||
|
"characters. This exceeds the size of the serial buffer.\n"
|
||||||
|
% args.src)
|
||||||
|
f.close()
|
||||||
|
sys.exit(1)
|
||||||
|
num_lines += 1
|
||||||
|
|
||||||
|
# Go back to the beginning of the file after verifying it has the correct
|
||||||
|
# line length
|
||||||
|
f.seek(0)
|
||||||
|
|
||||||
|
# set serial timeout
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("Upload starting\r\n")
|
||||||
|
|
||||||
|
# remove existing file on device
|
||||||
|
if args.append==False:
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("Stage 1. Deleting old file from flash memory")
|
||||||
|
transport.writeln("file.open(\"" + args.dest + "\", \"w\")\r")
|
||||||
|
transport.writeln("file.close()\r")
|
||||||
|
transport.writeln("file.remove(\"" + args.dest + "\")\r")
|
||||||
|
else:
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("[SKIPPED] Stage 1. Deleting old file from flash memory [SKIPPED]")
|
||||||
|
|
||||||
|
|
||||||
|
# read source file line by line and write to device
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("\r\nStage 2. Creating file in flash memory and write first line")
|
||||||
|
if args.append:
|
||||||
|
transport.writeln("file.open(\"" + args.dest + "\", \"a+\")\r")
|
||||||
|
else:
|
||||||
|
transport.writeln("file.open(\"" + args.dest + "\", \"w+\")\r")
|
||||||
|
line = f.readline()
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("\r\nStage 3. Start writing data to flash memory...")
|
||||||
|
if args.bar:
|
||||||
|
for i in tqdm(range(0, num_lines)):
|
||||||
|
transport.writer(line.strip())
|
||||||
|
line = f.readline()
|
||||||
|
else:
|
||||||
|
while line != '':
|
||||||
|
transport.writer(line.strip())
|
||||||
|
line = f.readline()
|
||||||
|
|
||||||
|
# close both files
|
||||||
|
f.close()
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("\r\nStage 4. Flush data and closing file")
|
||||||
|
transport.writeln("file.flush()\r")
|
||||||
|
transport.writeln("file.close()\r")
|
||||||
|
|
||||||
|
# compile?
|
||||||
|
if args.compile:
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("\r\nStage 5. Compiling")
|
||||||
|
transport.writeln("node.compile(\"" + args.dest + "\")\r")
|
||||||
|
transport.writeln("file.remove(\"" + args.dest + "\")\r")
|
||||||
|
|
||||||
|
# restart or dofile
|
||||||
|
if args.restart:
|
||||||
|
transport.writeln("node.restart()\r")
|
||||||
|
if args.dofile: # never exec if restart=1
|
||||||
|
transport.writeln("dofile(\"" + args.dest + "\")\r", 0)
|
||||||
|
|
||||||
|
if args.echo:
|
||||||
|
if args.verbose:
|
||||||
|
sys.stderr.write("\r\nEchoing MCU output, press Ctrl-C to exit")
|
||||||
|
while True:
|
||||||
|
sys.stdout.write(transport.read(1))
|
||||||
|
|
||||||
|
# close serial port
|
||||||
|
transport.close()
|
||||||
|
|
||||||
|
# flush screen
|
||||||
|
sys.stdout.flush()
|
||||||
|
sys.stderr.flush()
|
||||||
|
if not args.bar:
|
||||||
|
sys.stderr.write("\r\n--->>> All done <<<---\r\n")
|
||||||
15
tests/client.lua
Normal file
15
tests/client.lua
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
local host, port = "meteo.ulgrad.ru", 4999
|
||||||
|
local socket = require("socket")
|
||||||
|
local tcp = assert(socket.tcp())
|
||||||
|
|
||||||
|
tcp:connect(host, port);
|
||||||
|
--note the newline below
|
||||||
|
tcp:send("thunder!");
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local s, status, partial = tcp:receive()
|
||||||
|
print(s or partial)
|
||||||
|
print(status)
|
||||||
|
if status == "closed" then break end
|
||||||
|
end
|
||||||
|
tcp:close()
|
||||||
2
tests/tcp.test
Normal file
2
tests/tcp.test
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
nc meteo.ulgrad.ru 4999
|
||||||
|
nc 5.187.7.142 4999
|
||||||
Loading…
x
Reference in New Issue
Block a user