185 lines
5.3 KiB
Lua
185 lines
5.3 KiB
Lua
analog_pin = 0
|
|
t = require("DS1820")
|
|
num_readings = 8
|
|
readings = {}
|
|
read_index = 1
|
|
total = 0
|
|
timing = 6000
|
|
ds_pin = 1
|
|
|
|
pin_ten = 2
|
|
pin_fan = 6
|
|
pin_led_g = 7
|
|
pin_led_r = 5
|
|
|
|
adc_min = 0
|
|
adc_max = 1023
|
|
steps = {4, 8, 12, 16, 20, 24, 28}
|
|
current_t = 16
|
|
|
|
hysteresis = 1
|
|
ten_on_time = 0
|
|
ten_off_time = 0
|
|
ten_was_active = false
|
|
|
|
gpio.mode(pin_ten, gpio.OUTPUT)
|
|
gpio.mode(pin_fan, gpio.OUTPUT)
|
|
gpio.mode(pin_led_g, gpio.OUTPUT)
|
|
gpio.mode(pin_led_r, gpio.OUTPUT)
|
|
|
|
gpio.write(pin_ten, gpio.HIGH)
|
|
gpio.write(pin_fan, gpio.HIGH)
|
|
gpio.write(pin_led_g, gpio.LOW)
|
|
gpio.write(pin_led_r, gpio.LOW)
|
|
|
|
if adc.force_init_mode(adc.INIT_ADC) then node.restart() end
|
|
|
|
for i = 1, num_readings do readings[i] = 0 end
|
|
|
|
results = {}
|
|
|
|
function read_smoothed_adc()
|
|
total = total - readings[read_index]
|
|
local raw = adc.read(analog_pin)
|
|
readings[read_index] = raw
|
|
total = total + raw
|
|
read_index = read_index + 1
|
|
if read_index > num_readings then read_index = 1 end
|
|
return total / num_readings
|
|
end
|
|
|
|
function control_logic(avg_temp)
|
|
local time_now = tmr.time()
|
|
local temp_ok = (avg_temp >= (current_t - hysteresis)) and (avg_temp <= (current_t + hysteresis))
|
|
|
|
if temp_ok then
|
|
gpio.write(pin_led_g, gpio.HIGH)
|
|
gpio.write(pin_led_r, gpio.LOW)
|
|
else
|
|
gpio.write(pin_led_g, gpio.LOW)
|
|
gpio.write(pin_led_r, gpio.HIGH)
|
|
end
|
|
|
|
if avg_temp < (current_t - hysteresis) then
|
|
if gpio.read(pin_ten) == gpio.HIGH then
|
|
gpio.write(pin_ten, gpio.LOW)
|
|
ten_on_time = time_now
|
|
ten_was_active = true
|
|
end
|
|
if ten_was_active and ten_on_time > 0 and (time_now - ten_on_time >= 300) then
|
|
if gpio.read(pin_fan) == gpio.HIGH then
|
|
gpio.write(pin_fan, gpio.LOW)
|
|
end
|
|
else
|
|
gpio.write(pin_fan, gpio.HIGH)
|
|
end
|
|
elseif avg_temp > (current_t + hysteresis) then
|
|
gpio.write(pin_ten, gpio.HIGH)
|
|
ten_was_active = false
|
|
ten_on_time = 0
|
|
if gpio.read(pin_fan) == gpio.HIGH then
|
|
gpio.write(pin_fan, gpio.LOW)
|
|
end
|
|
else
|
|
if gpio.read(pin_ten) == gpio.LOW then
|
|
gpio.write(pin_ten, gpio.HIGH)
|
|
ten_off_time = time_now
|
|
end
|
|
if ten_was_active and ten_off_time > 0 then
|
|
if (time_now - ten_off_time >= 300) then
|
|
gpio.write(pin_fan, gpio.HIGH)
|
|
ten_was_active = false
|
|
ten_on_time = 0
|
|
ten_off_time = 0
|
|
end
|
|
else
|
|
gpio.write(pin_fan, gpio.HIGH)
|
|
end
|
|
end
|
|
|
|
local ten_state = gpio.read(pin_ten) == gpio.LOW and 1 or 0
|
|
local fan_state = gpio.read(pin_fan) == gpio.LOW and 1 or 0
|
|
print(string.format("T_cur: %2d C | T_set: %2d C | TEN: %d | FAN: %d | Act: %s",
|
|
avg_temp, current_t, ten_state, fan_state, tostring(ten_was_active)))
|
|
end
|
|
|
|
function readout(temp)
|
|
local count = 0
|
|
local sum = 0
|
|
for addr, t_val in pairs(temp) do
|
|
local short_id = string.format('%02X', addr:byte(8))
|
|
local t_ceil = t_val
|
|
if t_val > 1000 then t_ceil = t_val / 10000 end
|
|
|
|
results[short_id] = t_ceil
|
|
print("Sensor " .. short_id .. ": " .. t_ceil .. " C")
|
|
|
|
sum = sum + t_ceil
|
|
count = count + 1
|
|
end
|
|
if count > 0 then
|
|
control_logic(sum / count)
|
|
else
|
|
print("No sensors found")
|
|
end
|
|
end
|
|
|
|
function read_sensors()
|
|
t:read_temp(readout, ds_pin, t.C)
|
|
end
|
|
|
|
function start_web_server()
|
|
wifi.setmode(wifi.SOFTAP)
|
|
local cfg = {}
|
|
cfg.ssid = "Thermostat-WiFi"
|
|
wifi.ap.config(cfg)
|
|
|
|
srv = net.createServer(net.TCP)
|
|
srv:listen(80, function(conn)
|
|
conn:on("receive", function(sck, payload)
|
|
local response = {"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"}
|
|
table.insert(response, "<html><head><meta http-equiv='refresh' content='5'></head><body>")
|
|
table.insert(response, "<h2>Thermostat Status</h2>")
|
|
table.insert(response, "<p><b>Target Temp:</b> " .. current_t .. " C</p><hr>")
|
|
|
|
for id, temp in pairs(results) do
|
|
table.insert(response, "<p><b>Tank [ID: " .. id .. "]:</b> " .. temp .. " C</p>")
|
|
end
|
|
|
|
table.insert(response, "</body></html>")
|
|
|
|
local function send_chunk(sk)
|
|
if #response > 0 then
|
|
sk:send(table.remove(response, 1))
|
|
else
|
|
sk:close()
|
|
end
|
|
end
|
|
sck:on("sent", send_chunk)
|
|
send_chunk(sck)
|
|
end)
|
|
end)
|
|
print("HTTP Server started on 192.168.4.1")
|
|
end
|
|
|
|
tmr.create():alarm(2000, tmr.ALARM_SINGLE, function()
|
|
collectgarbage()
|
|
start_web_server()
|
|
|
|
sensortimer = tmr.create()
|
|
sensortimer:register(timing, tmr.ALARM_AUTO, read_sensors)
|
|
sensortimer:start()
|
|
|
|
adctimer = tmr.create()
|
|
adctimer:register(300, tmr.ALARM_AUTO, function()
|
|
local avg_raw = read_smoothed_adc()
|
|
if avg_raw < adc_min then avg_raw = adc_min end
|
|
if avg_raw > adc_max then avg_raw = adc_max end
|
|
local step_index = 1 + ((avg_raw - adc_min) * (#steps - 1)) / (adc_max - adc_min)
|
|
if step_index > #steps then step_index = #steps end
|
|
if step_index < 1 then step_index = 1 end
|
|
current_t = steps[step_index]
|
|
end)
|
|
adctimer:start()
|
|
end)
|