Project - Occupancy Dimmer

What makes this Occupancy Dimmer different from other sensor lights is it's smooth dim Up and dim Down (no sudden switching On or Off), plus a preset minimum night-light level to avoid total darkness if preferred.
It is useful for young, or old, or infirm, or lazy, or pets... as an automatic night lamp, or for automatic stair/porch/garage/bathroom/nursery lighting etc, or wherever it could be convenient to have automatic timed gentle lighting or motor speed control.

Essentially it is an automatic lamp or bathroom fan that quickly dims smoothly Up when sensing movement, stays On for a pre-set duration, then slowly dims Down to Off (or to a pre-set minimum night-light level) unless re-triggered by more movement again.

Movement detection can be achieved using a PIR or a radar sensor - a PIR is more directional and requires a visible lens, whereas.
a radar sensor can be completely enclosed and have a wider field of view (can be more sensitive, but prone to unwanted triggers).

Some adjustable preset parameters can be fine-tuned to suit needs:

DimUPdelay  (the delay between individual Up steps).
ONtime  (the 'stay on' inactivity duration before starting to Dim Down)
DimDOWNdelay  (the delay between individual Down steps)
NightLight  (minimum brightness level to dim down to)
DimUPdelay and dimDOWNdelay both 0 behaves like a normal sensor light which will switch On then stay On for the duration of ONtime.
NightLight set to non-zero switches between full and dim light levels.
The script presets are easily changed remotely using the Annex Editor, and  this video  shows the effects of changing the variables.

An optional potentiometer can be used to provide a manual minimum night-light brightness if wished (enabled by setting pot=1).

The script is unusual because it avoids branching for interrupts or timers, and instead keeps endlessly looping like an arduino.
It only does one task during each iteration of the loop, and the task behaviour is dependent on the changing setting of the 'mode' flag.
   mode=0 is idle, mode=1 is triggered to dim Up, mode=2 stays On for specified duration, mode=3 dims Down.

When looping in idle mode (0) the sensor is read each loop, and if triggered, the script will keep looping in dim Up mode (1) to 100.
When max brightness of 100 is reached, it changes to mode 2, which keeps looping ON for the ONtime duration which is split into 1 sec loops, allowing frequent opportunity for checking for sensor re-triggers. Re-triggering will cause mode to be set back to 1, so the next loop will cause it to dim back up to 100 if not already there, then change to mode 2 ONtime again.
If not re-triggered before the ONtime duration times out, the mode is changed to dim Down (3) and each loop will step the brightness down until NightLight level is reached which changes mode to idle (0), or a re-trigger changes to mode 1 again.

A debugging flag dev=1 offers an idea of what is happening in the wlog window (check the script comments for some other options).

The dimmer has a 100 step working range (0 to 100), and pauses between each Up or Down step, so the brightness control has maximum resolution and therefore is as smooth as possible.

'Occupancy Dimmer Night-light - Electroguard - developed on Annex 1.41 beta 3"   
dimmer.setup 4,5,0,1                'configure dimmer module, 4 and 13 = zero crossing,  5 = pwm
dimmer.limits 0, 9500                 'actual min/max delay in triac firing
brightness=0                             'initial startup value
nightlight=0                               'minimum brightness setting, acts like a nightnight to avoid total darkness
dimUPdelay=3                           'dim up delay between step changes (ms)
dimDOWNdelay=20                    'dim down delay between step changes (ms)
ONtime=4                                  'On duration before dimming without retrigger (secs)
pot=0                                         '0=no potentiometer, 1=pot installed to set night-light level
dev=0                                         'wlog development flag - 1=show modes, 2=show ramfree, 3=show nightlight setting
active=1                                      'active high or active low trigger
dimmer.brightness brightness
ledpin=15                                     'if optional pwm led is used, set to a valid gpio, else set to -1
if ledpin<>-1 then
 option.pwmfreq 100                      'reduce pwm frequency to reduce cpu load
sensorpin=2                                  'occupancy sensor (PIR or radar module)
pin.mode sensorpin, input, pullup

start:                                            'start of endless loop
if pin(sensorpin)=active then mode=1
select case mode                          'select behaviour according to mode setting
case 1                                          'dim Up
 pause dimUPdelay
 if brightness>100 then
 if dev=1 then wlog "mode1 Up  "+str$(brightness)
 dimmer.brightness brightness
 if ledpin <> -1 then pwm(ledpin)=brightness*10
case 2                                            'On duration
 if dev=2 then wlog str$(ramfree)+"  "+time$
 if pot=1 then
 if dev=3 then
  if pot=1 then wlog "nightlight level="+str$(nightlight)+" set by pot" else wlog "nnightlight level="+str$(nightlight)+", NO POT"
 for c=1 to ONtime
  if pin(sensorpin)=active then mode=1 
  if dev=1 then wlog "mode2 On  "+str$(c)+" secs"
  pause 1000
 next c
case 3                                             'dim Down
 pause dimDowndelay
 if brightness<=nightlight then
 if dev=1 then wlog "mode3 Down  "+str$(brightness)
 dimmer.brightness brightness
 if ledpin <> -1 then pwm(ledpin)=brightness*10
  if (dev=1) and (mode=0) then wlog "mode0 idle"
case else                                          'inactive
 pause 50
end select
goto start

end  '-------------------- End --------------------