led.lua 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. -- local led_pin = 1 --GPIO 5
  2. local led_pin = 2 --nodeMCU LED
  3. local override_pin = 4 --GPIO 4
  4. local HEARTBEAT_times = {40, 200, 40, 900} --format is alternating on and off times in ms
  5. local TRIPLEBLINK_times = {100, 20, 100, 20, 100, 20, 100} --format is alternating off and on times in ms
  6. local led_pwm_frequency = 500 --units: hz
  7. local led_max_brightness = 1023
  8. local current_pattern
  9. local pattern_queue = {}
  10. local HEARTBEAT_index = 1
  11. local TRIPLEBLINK_index = 1
  12. --pattern definitions
  13. local patterns = {
  14. STOPPED = 0,
  15. HEARTBEAT = 1,
  16. FADEIN = 2,
  17. FADEOUT = 3,
  18. TRIPLEBLINK = 4
  19. }
  20. local patterns_initial_pwm_duty = {
  21. [0] = 0,
  22. 0,
  23. 0,
  24. led_max_brightness,
  25. led_max_brightness
  26. }
  27. local pattern_intervals = {
  28. [0] = 0,
  29. HEARTBEAT_times,
  30. 1,
  31. 1,
  32. TRIPLEBLINK_times
  33. }
  34. --dependencies
  35. local TIMER = TIMERS.led
  36. local debug_message = debug_message
  37. local gpio = gpio
  38. local pwm = pwm
  39. local tmr = tmr
  40. local table = table
  41. local print = print
  42. module(...)
  43. function testcall()
  44. do_pattern(patterns.FADEOUT)
  45. end
  46. function init()
  47. debug_message('led.init')
  48. --handle timer, take exclusive control
  49. tmr.unregister(TIMER)
  50. current_pattern = patterns.STOPPED
  51. --init pins
  52. gpio.mode(override_pin, gpio.OUTPUT)
  53. pwm.setup(led_pin, led_pwm_frequency, 0)
  54. pwm.start(led_pin)
  55. pwm.stop(led_pin)
  56. end
  57. function stop()
  58. tmr.unregister(TIMER)
  59. --deassert control
  60. gpio.write(override_pin, gpio.LOW)
  61. current_pattern = patterns.STOPPED
  62. pattern_queue = {}
  63. end
  64. function do_pattern(next_pattern)
  65. debug_message('led.do_pattern: ' .. next_pattern)
  66. if(next_pattern == current_pattern) then
  67. debug_message('led.do_pattern: next same as current')
  68. return
  69. end
  70. if current_pattern ~= patterns.STOPPED then
  71. debug_message('led.do_pattern: current not STOPPED')
  72. --put next_pattern in queue
  73. table.insert(pattern_queue, next_pattern)
  74. else
  75. debug_message('current, next: ' .. current_pattern .. ', ' .. next_pattern)
  76. --start next_pattern!
  77. current_pattern = next_pattern
  78. -- override_enable()
  79. gpio.write(override_pin, gpio.HIGH)
  80. pattern(
  81. patterns_initial_pwm_duty[next_pattern],
  82. pattern_intervals[next_pattern],
  83. next_pattern_funcs[next_pattern]
  84. )
  85. end
  86. --rewrite queue:
  87. --when queueing new pattern, if transition (or flag) not nil then do immediately
  88. --otherwise enqueue and let end_function or similar get next from queue
  89. --STOP should instead a pattern like all others, renamed as OFF
  90. --transition functions transition(t) --> t+1
  91. --if t+1 is nil, end pattern
  92. end
  93. --TODO: intervals not used (still using global state)
  94. function pattern(initial_pwm_duty, intervals, transition)
  95. debug_message('led.pattern')
  96. pwm.setduty(led_pin, initial_pwm_duty)
  97. local pwm_duty = initial_pwm_duty
  98. --looping timer instead of alarm_single, can deregister on nil
  99. transition()
  100. end
  101. function FADEIN_update()
  102. local current_brightness = pwm.getduty(led_pin)
  103. current_brightness = current_brightness + 1
  104. if(current_brightness > led_max_brightness) then
  105. current_brightness = led_max_brightness
  106. end
  107. pwm.setduty(led_pin, current_brightness)
  108. if current_brightness < led_max_brightness then
  109. tmr.alarm(TIMER, 2, tmr.ALARM_SINGLE, FADEIN_update)
  110. else
  111. end_pattern()
  112. end
  113. end
  114. function FADEOUT_update()
  115. local current_brightness = pwm.getduty(led_pin)
  116. current_brightness = current_brightness - 1
  117. if(current_brightness < 0) then
  118. current_brightness = 0
  119. end
  120. pwm.setduty(led_pin, current_brightness)
  121. if current_brightness > 0 then
  122. tmr.alarm(TIMER, 2, tmr.ALARM_SINGLE, FADEOUT_update)
  123. else
  124. end_pattern()
  125. end
  126. end
  127. function HEARTBEAT_update()
  128. local current_brightness = pwm.getduty(led_pin)
  129. current_brightness = led_max_brightness - current_brightness
  130. pwm.setduty(led_pin, current_brightness)
  131. tmr.alarm(TIMER, HEARTBEAT_times[HEARTBEAT_index], tmr.ALARM_SINGLE, HEARTBEAT_update)
  132. HEARTBEAT_index = HEARTBEAT_index + 1
  133. if HEARTBEAT_index > table.getn(HEARTBEAT_times) then
  134. HEARTBEAT_index = 1
  135. end
  136. --pattern does not end
  137. end
  138. function TRIPLEBLINK_update()
  139. local current_brightness = pwm.getduty(led_pin)
  140. current_brightness = led_max_brightness - current_brightness
  141. pwm.setduty(led_pin, current_brightness)
  142. tmr.alarm(TIMER, TRIPLEBLINK_times[TRIPLEBLINK_index], tmr.ALARM_SINGLE, TRIPLEBLINK_update)
  143. TRIPLEBLINK_index = TRIPLEBLINK_index + 1
  144. if TRIPLEBLINK_index > table.getn(TRIPLEBLINK_times) then
  145. end_pattern()
  146. end
  147. end
  148. next_pattern_funcs = {
  149. HEARTBEAT_update,
  150. FADEIN_update,
  151. FADEOUT_update,
  152. TRIPLEBLINK_update
  153. }
  154. function end_pattern()
  155. if table.getn(pattern_queue) == 0 then
  156. stop()
  157. else
  158. p = pattern_queue[1]
  159. table.remove(pattern_queue, 1)
  160. current_pattern = patterns.STOPPED
  161. tmr.unregister(TIMER)
  162. do_pattern(p)
  163. end
  164. end
  165. init(TIMER)