camera/init.lua
2026-08-20 14:01:08 +04:00

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)