diff --git a/flash.sh b/flash.sh index 389bd92..8cd9d08 100755 --- a/flash.sh +++ b/flash.sh @@ -1,4 +1,4 @@ -rm firmware/*bin +rm -f firmware/*bin cp /home/wes/code/nodemcu-firmware/bin/*bin ./firmware rm -f sources/lfs.img cd sources && ./compile.sh @@ -8,8 +8,8 @@ nodemcu-tool reset function reset_flash() { nodemcu-tool reset esptool.py --port /dev/ttyUSB0 erase_flash - esptool.py --port /dev/ttyUSB0 write_flash -fm dio 0x00000 firmware/0x00000.bin - esptool.py --port /dev/ttyUSB0 write_flash -fm dio 0x10000 firmware/0x10000.bin + esptool.py --port /dev/ttyUSB0 write_flash -fm qio 0x00000 firmware/0x00000.bin + esptool.py --port /dev/ttyUSB0 write_flash -fm qio 0x10000 firmware/0x10000.bin } #reset_flash diff --git a/sources/_init.lua b/sources/_init.lua index d9c29b1..7c30848 100644 --- a/sources/_init.lua +++ b/sources/_init.lua @@ -7,21 +7,6 @@ lights = {} lights[green] = false lights[red] = false --- cron job which checks if auto mode is enabled --- if auto mode is enabled, it cycles through various timers --- runs the current timer for one period (cron job runs once every period of time) --- then stops and unregisters that timer, and moves on to the next, etc --- if auto mode is disabled, it does nothing --- UI allows you to configure auto mode period maybe --- UI could also allow to configure the specific settings but this might be too much work - -function display_table(t) - print("table") - for k, v in pairs(t) do - print("k = " .. tostring(k), ", v = " .. tostring(v)) - end -end - function calc_duty_cycle(duty_cycle_factor) if duty_cycle_factor <= 1 then return 1023 @@ -30,37 +15,79 @@ function calc_duty_cycle(duty_cycle_factor) end end -function make_timer(pin, interval, initial_duty_cycle) +function is_table(v) + local is_it_a_table, _ = pcall(function() return v["is_table"] end) + return is_it_a_table +end + +function show_pair(key, value) + -- TODO handle case of array and then call back to show_list + if is_table(value) then + return "("..tostring(key) .. " . " .. tostring(show_table(value)) .. ")" + else + return "("..tostring(key) .. " . " .. tostring(value) .. ")" + end +end + +function show_table(t) + result = "" + for key, value in pairs(t) do + result = result .. show_pair(key, value) + end + return "(" .. result .. ")" +end + +function show_list(ts) + if is_table(12) or (not is_table({green=12})) then + return "" + end + result = "" + for _, t in ipairs(ts) do + if is_table(t) then + result = result .. show_table(t) + else + result = result .. tostring(t) + end + end + return "(" .. result .. ")" +end + +function make_timer(params) -- interval is in milliseconds -- pin is the gpio number - local duty_cycle_t = initial_duty_cycle - local direction = 1 + -- params {pin=pin, frequency=frequency, duty_cycle=duty_cycle, step=step, interval=interval, delay=delay} + + local duty_cycle_t = params["duty_cycle"] + local direction = params["step"] local delay = 0 print("timer created!") + print(duty_cycle_t) local timer = tmr.create() - timer:register(interval, tmr.ALARM_AUTO, function() + timer:register(params["interval"], tmr.ALARM_AUTO, function() if delay > 0 then delay = delay - 1 return end - if duty_cycle_t >= 1023 then - delay = 200 - direction = -1 - elseif duty_cycle_t <= 0 then - delay = 200 - direction = 1 + if (direction > 0 and ((duty_cycle_t + direction) >= 1023)) then + delay = params["delay"] + direction = -math.abs(direction) end - duty_cycle_t = duty_cycle_t + direction + if ((direction <= 0) and ((duty_cycle_t + direction) < 0)) then + delay = params["delay"] + direction = math.abs(direction) + end if delay > 0 then return end + duty_cycle_t = duty_cycle_t + direction + -- if this is running then it's turned on - lights[pin] = true - pwm.setduty(pin, duty_cycle_t) + lights[params["pin"]] = true + pwm.setduty(params["pin"], duty_cycle_t) end) return timer end @@ -71,31 +98,92 @@ pwm.setup(red, 500, 1023) pwm.start(green) pwm.start(red) -timers = {} -timers[green] = make_timer(green, 10, 1) -timers[red] = make_timer(red, 10, 1023) -timers[green]:stop() -timers[red]:stop() +timers = {red=false, green=false} + +-- cron job which checks if auto mode is enabled +-- if auto mode is enabled, it cycles through various timers +-- runs the current timer for one period (cron job runs once every period of time) +-- then stops and unregisters that timer, and moves on to the next, etc +-- if auto mode is disabled, it does nothing +-- UI allows you to configure auto mode period maybe +-- UI could also allow to configure the specific settings but this might be too much work + +auto_mode_enabled = true -function turn_on_fade(pin) - timers[pin]:start() +function make_timer_params(pin, duty_cycle, interval, frequency, step, delay) + duty_cycle = duty_cycle or 1023 + interval = interval or 20 + step = step or 1 + frequency = frequency or 500 + delay = delay or 200 + return {pin=pin, frequency=frequency, duty_cycle=duty_cycle, step=step, interval=interval, delay=delay} +end + +function unregister_timers() + if timers[green] then + timers[green]:unregister() + end + if timers[red] then + timers[red]:unregister() + end + duty_cycle = 1023 + pwm.setduty(red, duty_cycle) + pwm.setduty(green, duty_cycle) +end + +timer_states = { + {green=make_timer_params(green, 1022, 200, 1000, 1021, 5), red=make_timer_params(red, 1022, 200, 1000, -1021, 5)}, + {green=make_timer_params(green, 1023, 5), red=make_timer_params(red, 1, 5)}, + --{green=make_timer_params(green, 1022, 100, 1000, -1021, 5), red=make_timer_params(red, 1022, 100, 1000, 1021, 5)}, + --{green=make_timer_params(green, 1023, 5, 1000), red=make_timer_params(red, 1, 5, 1000)}, + --{green=make_timer_params(green, 1023, 5), red=make_timer_params(red, 1023, 5)}, + --{green=make_timer_params(green, 1, 5), red=make_timer_params(red, 1023, 5)}, + --{green=make_timer_params(green, 1), red=make_timer_params(red, 1023)}, + } + +function start_auto_mode() + -- this is enabled by default + local current_state = 1 + local number_of_states = table.getn(timer_states) + print("Making cronjob, number of states = " .. number_of_states) + cron.reset() + unregister_timers() + cron.schedule("*/1 * * * *", function(e) + if auto_mode_enabled then + print("Auto mode enabled, switching modes, current mode = " .. current_state) + + unregister_timers() + + -- TODO iter8 thru them instead + timers[green] = make_timer(timer_states[current_state]["green"]) + timers[red] = make_timer(timer_states[current_state]["red"]) + timers[green]:start() + timers[red]:start() + + current_state = (current_state % number_of_states) + 1 + + end + end) end function turn_light_on(pin, duty_cycle) - if not lights[pin] then + if not lights[pin] and not auto_mode_enabled then lights[pin] = true pwm.setduty(pin, duty_cycle) end end function turn_light_off(pin) - if lights[pin] then + if lights[pin] and not auto_mode_enabled then pwm.setduty(pin, 0) lights[pin] = false end end function toggle_light(pin) + if auto_mode_enabled then + return + end print("Toggling " .. tostring(pin)) local duty_cycle = calc_duty_cycle(1) print("duty_cycle = ".. duty_cycle) @@ -178,6 +266,7 @@ function startup() nil, function(sec, usec, server, info) print('synced ntp ', sec, usec, server) + start_auto_mode() end, function() print('failed to sync ntp') @@ -203,13 +292,12 @@ function startup() end elseif req.url == "/toggle_mode" then local params = extract_formdata(urldecode(chunk)) - display_table(params) if params["toggle_mode"] == "mode_manual" then - timers[green]:stop() - timers[red]:stop() - elseif params["toggle_mode"] == "mode_fade" then - timers[green]:start() - timers[red]:start() + unregister_timers() + auto_mode_enabled = false + elseif params["toggle_mode"] == "mode_auto" then + start_auto_mode() + auto_mode_enabled = true end elseif req.url == "/reboot" then node.restart() @@ -222,10 +310,10 @@ function startup() res:send_header("Content-Type", "text/html") res:send_header("Connection", "close") - local toggle_mode = gen_form("Toggle Mode", "toggle_mode", {["mode_fade"]="Fade", ["mode_manual"]="Manual"}, gen_select) + local toggle_mode = gen_form("Toggle Mode", "toggle_mode", {["mode_manual"]="Manual", ["mode_auto"]="Auto"}, gen_select) local toggle_lights_form = gen_form("Toggle Lights Form", "toggle", {["toggle_red"]="Red", ["toggle_green"]="Green"}, gen_select) - res:send("
Uptime: ".. tostring(tmr.time()) .. " seconds" .. toggle_lights_form .. toggle_mode .. "
" .. get_info("hw") .. get_info("build_config") .. get_info("sw_version") .. "
") + res:send("
Uptime: ".. tostring(tmr.time()) .. " seconds" .. toggle_lights_form .. toggle_mode .. "
" .. get_info("hw") .. get_info("build_config") .. get_info("sw_version") .. show_list(timer_states) .. "
") res:send("\r\n") elseif req.url == "/toggle" then res:send(nil, 303)