Project - Controlled Relay















Adds CycleON and CycleOFF buttons to the previous Simple Relay
Provides optional Delay and Duration for both the On and Off operations.

The timing diagram on the right shows how the On and Off Delays and Durations work.

Delays and Durations can be enabled/disabled using the appropriate checkboxs.
A disabled Delay will operate immediately irrespective of the set value.
A disabled Duration will not return to it's previous state after being triggered, irrespective of the set value.

Using the values shown in the screenshot above as examples...
CycleON button would immediately switch On (eg:) a lamp  (because delay is unchecked), then it would switch back Off after the elapsed 1 min duration.
CycleOFF button would delay 7 seconds (cos delay is ticked) before switching Off (to eg: reboot a router), then switch back On again after 8 sec Off duration.

The required Delays and Durations are obtained from a 1sec clock using 'virtual timer' countdown counters which are decremented every second until they reach 0 to trigger the events. Secs are * 60 for mins, * another 60 for hours, and then * 24 for days ... these same multiplier values are used by the script.

If using a Sonoff S20, rather than echo the blue led relay status, the onboard green LED blinks on/off while any virtual timers are still pending to show it will change.
 

Basic:
title$  = "Controlled Relay"
led = 1                                                 'Onscreen LED$ variable, 0=on 1=off,
ledpin = 13                                           'Sonoff green LED (active low)
ledoff = 1                                              'Sonoff LED Off state
pin.mode ledpin, output
pin(ledpin) = ledoff
relaypin = 12                                         'Sonoff relay (active high)
relayoff = 0                                            'Sonoff Relay Off state
pin.mode relaypin, output
pin(relaypin) = 0
buttonpin = 0                                         'Sonoff button (active low)
pin.mode buttonpin, input, pullup
interrupt buttonpin, pressed
ledstat$ = "green"                                  'Toggle button colour
unitslist$ = "secs, mins, hours, days"    'Displayed time multiplier
secs=1: mins=secs*60: hours=mins*60: days=hours*24
interval = 1
delayon = 0
ondelay = 5
ondelaycountdown = -1
ondelunits$ = "secs"
timedon = 1
onduration = 1
ondurationcountdown = -1
ondurunits$ = "mins"
delayoff = 1
offdelay = 7
offdelaycountdown = -1
offdelunits$ = "secs"
timedoff = 1
offduration = 8
offdurationcountdown = -1
offdurunits$ = "secs"
timer0 1000, ticker                           
gosub paint
onhtmlreload paint
wait

ticker:
if ondelaycountdown >= 0 then
 pin(ledpin) = 1 - pin(ledpin)
 if ondelaycountdown > 0 then
  ondelaycountdown = ondelaycountdown -1
 else
  ondelaycountdown = -1
  gosub relayon
  COMMAND "interval=" + ondurunits$
  if timedon = 1 then ondurationcountdown = onduration * interval
 endif
endif
if ondurationcountdown >= 0 then
 if pin(ledpin) = 0 then pin(ledpin) = 1 else pin(ledpin) = 0
 if ondurationcountdown > 0 then
  ondurationcountdown = ondurationcountdown -1
 else
  ondurationcountdown = -1
  gosub relayoff
 endif
endif
if offdelaycountdown >= 0 then
 if pin(ledpin) = 0 then pin(ledpin) = 1 else pin(ledpin) = 0
 if offdelaycountdown > 0 then
  offdelaycountdown = offdelaycountdown -1
 else
  offdelaycountdown = -1
  gosub relayoff
  COMMAND "interval=" + offdurunits$
  if timedoff = 1 then offdurationcountdown = offduration * interval
 endif
endif
if offdurationcountdown >= 0 then
 if pin(ledpin) = 0 then pin(ledpin) = 1 else pin(ledpin) = 0
 if offdurationcountdown > 0 then
  offdurationcountdown = offdurationcountdown -1
 else
  offdurationcountdown = -1
  gosub relayon
 endif
endif
'refresh
return

paint:
cls
autorefresh 1000
a$ = a$ + cssid$("tb40", "width:40;")
a$ = a$ + cssid$("tb60", "width:60;")
a$ = a$ + cssid$("butled", "height:3em; font-size:1.5em; border-radius:.4em; padding:.5em; color:white; background:" + ledstat$ + ";")
a$ = a$ + |<br><div style='display: table; margin-right:auto;margin-left:auto;text-align:center;'>|
a$ = a$ + title$ + "<br><br>"
a$ = a$ + led$(led)
a$ = a$ + "<br><br>"
a$ = a$ + button$("Instant On",relayon) + string$(9,"&nbsp;") + button$("Toggle", toggle, "butled") + string$(9,"&nbsp;") + button$("Instant Off",relayoff)
a$ = a$ + "<br>"
a$ = a$ + |<table align='center'><tr><td>|
a$ = a$ + button$("CycleON&nbsp;", cycleon) + |</td><td>| + " delay " + |</td><td>|
a$ = a$ + " " + checkbox$(delayon) + |</td><td>|
a$ = a$ + " " + textbox$(ondelay,"tb40") + |</td><td>|
a$ = a$ + listbox$(ondelunits$,unitslist$,"tb60") + |</td><td>|
a$ = a$ + string$(9,"&nbsp;")+ "  On  duration " + |</td><td>|
a$ = a$ + checkbox$(timedon) + |</td><td>|
a$ = a$ + " " + textbox$(onduration,"tb40") + |</td><td>| + listbox$(ondurunits$,unitslist$,"tb60") + |</td></tr><br><br><tr><td>|
a$ = a$ + button$("CycleOFF", cycleoff) + |</td><td>| + " delay " + |</td><td>|
a$ = a$ + " " + checkbox$(delayoff) + |</td><td>| + " " + textbox$(offdelay,"tb40") + |</td><td>| + listbox$(offdelunits$,unitslist$,"tb60") + |</td><td>|
a$ = a$ + string$(9,"&nbsp;")+ "  Off duration " + |</td><td>| + checkbox$(timedoff) + |</td><td>| + " " + textbox$(offduration,"tb40")
a$ = a$ + |</td><td>| + listbox$(offdurunits$,unitslist$,"tb60")  + |</td></tr></table><br>|
a$ = a$ + |</div>|
html a$
a$ = ""
return

pressed:
if pin(buttonpin) = 0 then gosub toggle
return

relayon:
if pin(relaypin) = relayoff then
 if relayoff = 0 then pin(relaypin) = 1 else pin(relaypin) = 0
endif
pin(ledpin) = 1 - ledoff
html cssid$("butled", "background:red;")
led = 0
refresh
return

relayoff:
refresh
if pin(relaypin) <> relayoff then pin(relaypin) = relayoff
pin(ledpin) = ledoff
html cssid$("butled", "background:green;")
led = 1
refresh
return

toggle:
if pin(relaypin) = relayoff then gosub relayon else gosub relayoff
return

cycleon:
COMMAND "interval=" + ondelunits$
if delayon > 0 then ondelaycountdown = ondelay * interval else ondelaycountdown = 0
return

cycleoff:
COMMAND "interval=" + offdelunits$
if delayoff > 0 then offdelaycountdown = offdelay * interval else offdelaycountdown = 0
return

'-------------------- End ---------------------




Note: This project was removed last year because the listbox$ components did not display correctly - but the old link remained from the previous project, and many people requested access to it, so the project has been made available again now that the listboxes work with the latest Annex 1.37 beta 4 firmware release.