Labo workbench light, a bit more clever than a switch

Using an old Arduino, a MosFet transistor, 5m of led strip and an old alarm detector (SIEMENS IR100B), I built an interesting little lighting set up.
The idea is that the leds switch on as you approach the desk.
The detector is a bit sensitive, but it does the job ok.
I was curious about the free run consumption when the leds are turned off.
Doing this project I got my answer: it’s very little. Less than 100mW according the wattmeter.

In attachment, code, schematics and video for reuse and improvement.

thanks to fritzing
/* Theo Reichel, Reichel Complex AI, 02/2010 */

int sensorPin = 2; // interrupt 0
int sensorAlimPin = 4;
int ledArrayPin = 9; // PWM
int buttonPin = 3; // interrupt 1
int ledPin = 11; // PWM

volatile bool sensor_status = LOW;
volatile bool button_pressed = LOW;

volatile unsigned int light_power;

unsigned long sensor_millis_diff = 0;
unsigned long sensor_status_age = 0;

volatile int menu;
int i;

void setup()   {
  Serial.begin(19200);
  Serial.println("Labo desk light with detector started");

  pinMode(ledArrayPin, OUTPUT);
  pinMode(sensorAlimPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);

  digitalWrite(sensorAlimPin, HIGH);

  attachInterrupt(0, sensor_trigger, CHANGE);
  attachInterrupt(1, user_button, FALLING);
}

void loop()
{
// menu
  while (menu == 0)
    detector();

  while (menu == 1)
    always_on();

  while (menu == 2)
    always_off();
}

void fadein()
{
  for (light_power; light_power<255; light_power++)
  {
    analogWrite(ledArrayPin, light_power);

    if (button_pressed) // button can interrupt fade
    {
      button_pressed = LOW;
      break;
    }

    delay(5);
  }
  if (light_power == 255) // electrical workaround
    digitalWrite(ledArrayPin, HIGH);
}

void fadeout()
{
  for (light_power; light_power > 0; light_power--)
  {
    analogWrite(ledArrayPin, light_power);

    if (sensor_status) // sensor can interrupt during fadeout.
      break;

    if (button_pressed) // button can interrupt fade
    {
      button_pressed = LOW;
      break;
    }

    delay(10);
  }
  if (light_power == 0) // electrical workaround
    digitalWrite(ledArrayPin, LOW);
}

/////////// programs /////////////

void detector()
{
  digitalWrite(ledPin, 50);

  if ( sensor_status )
  {
    Serial.print("update sensor_status_age: ");
    Serial.println(sensor_status_age);
    sensor_status_age = millis();  

    if (light_power < 255)
    {
      Serial.print("fadein from light power: ");
      Serial.println(light_power);

      fadein();
    }
  }
  else
  {
    sensor_millis_diff = millis() - sensor_status_age;

    if ( light_power > 0 && sensor_millis_diff > 60000 )
    {
      Serial.print("fadout from light power:");
      Serial.print(light_power);
      Serial.print(", duration without motion");
      Serial.println(sensor_millis_diff);

      fadeout();
    }
  }
}

void always_on()
{
  digitalWrite(ledPin, HIGH);

  if (light_power < 255)
    fadein();
}

void always_off()
{
  analogWrite(ledPin, LOW);

  if (light_power > 0)
    fadeout();
}

/////////// interrupts /////////////

void sensor_trigger()
{
  sensor_status = !digitalRead(sensorPin);
}

void user_button()
{
  button_pressed = HIGH;

  if (menu == 2)
    menu = 0;
  else
    menu++;
}

The next project in the same wave is to make a nice PCB, arduino compatible with FET and detector on board.
Adding some nice little things like RTC, light sensor and a little led display, I plan to build a better light management.
For instance, if the room is bright enough the leds stays off.
If the time is far in the night, meaning that I’m not supposed to be awake, the light is faded to keep it soft for my eyes.
And of course a single push button to iterate different modes.

There is probably a lot more to do to make “clever” lights.
Feel free to share your ideas, I’m very interested.
But please, don’t mention clapping in the hand like in SF movie. I believe the light is improved if it adapts to our presence without our explicit will or interaction.