[Project Completed] Arduino controlled Smart Reading Lamp

Hello everybody,
Greetings…
I am very fond of reading books at bed time, before going to sleep. Recently my table lamp is gone broken so I am planning to build my own smart table lamp that can automatically be ON or OFF according to my presence. The system is targetted to be like this.

First, Check if there is any one reading a book or not, If YES then turn on the light (Using a Simple High power LED Matrix board ) if NO then Dimm the light.

Procedure:
I am using an ultra-sonic sensor that will seek for obstacle (BOOK) horizontally. As we generally ,at bed time, read books lying, the sensor will be placed right above my head & horizontally check for the obstacle(book).

This is my modified sketch

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
int led = 13;
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("Ping: ");
  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  if (uS / US_ROUNDTRIP_CM < 10)
  {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500); 
  }
  else
  digitalWrite(led, LOW);
  delay(500); 
}

This is working but I want to add a few things

  1. Manipulate the distance that controls the LED state, suppose I want the obstacle distance to be set by a pot rather than the fixed distance on the code if (uS / US_ROUNDTRIP_CM < 10)
  2. The LED 13 is not glowing at the fullest, it is a little dimmer. How to solve it?

Thanks for your time spent on reading my post. Your help shall be highly appraised. Thank you.

  1. The LED 13 is not glowing at the fullest, it is a little dimmer. How to solve it?

The LED pin is not set yo OUTPUT. Of course it will be dim.

  1. Manipulate the distance that controls the LED state, suppose I want the obstacle distance to be set by a pot rather than the fixed distance on the code

OK. I suppose that you do. Now what? Where are you reading from a potentiometer? What value?

Thanks for your response & solving the LED dimming issue. :slight_smile:

I want to read the potentiometer value & put it in a variable "potValue ".
potValue = analogRead(potPin);

Then I will map the value using the map( ) function
int bookDistance = map(potValue, 0, 1023, 10, 50);

then I put the “bookDistance” value in the ultrasonic sensor margin value
if (uS / US_ROUNDTRIP_CM < bookDistance) {
digitalWrite(ledPin, HIGH);

This is the basic algorithm I am planning to implement. Am I missing something? Kindly guide.
Thanks & regards.

your potmeter idea looks good, although I would extend the mapping rfom 10… 100cm to get some “working range”.

Furthermore I would add a function that when there is no book present, it will wait for 15 seconds before dimming the light.
(Dimming can be done with PWM - analogWrite) That gives you time to put the book away with some light.

Finally you could add an RTC to start the lamp in the morning (dimmed of course)…

Just regarding naming, I suggest you use bookDistance to record the distance of the actual book, and some other name such as thresholdDistance to record the value you have calculated from the potentiometer input.

Then your distance comparison makes more sense to me as:

if(bookDistance < thresholdDistance)
{
    ... etc

Thanks robtillaart & PeterH for your suggesstion. Tonight I will modify the code & post it here in the morning. Thanks to the entire arduino community for all the help & support

Hello,
I tried to develop the sketch…

// ---------------------------------------------------------------------------
// Example NewPing library sketch that does a ping about 20 times per second.
// ---------------------------------------------------------------------------

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int led = A0;
int pot = A5; // set the A5 pin as potmeter's output
int potValue = 0;
int bookDistance = 0;
int thresholdDistance = 0;
void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
  pinMode(led, OUTPUT);
  pinMode(pot, INPUT); 
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("BookDistance: ");
  bookDistance = uS / US_ROUNDTRIP_CM;
  Serial.print(bookDistance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  
  potValue = analogRead(pot);
  Serial.print("PotValue: ");
  Serial.println(potValue);
  
  thresholdDistance = map(potValue, 0, 1023, 10, 50);
  Serial.print("ThresholdDistance: ");
  Serial.println(thresholdDistance);
  
  if (bookDistance < thresholdDistance)
  {
  analogWrite(led, 250);   // turn the LED on (HIGH is the voltage level)
 // delay(10); 
  }
  else
  analogWrite(led, 128); 
}

Wiring:
A0 pin > 4.7K Resistor > LED > GND
A5 pin is connected to the Vout (Middle pin) of the pot. the other terminal pins of the pot is connected to 5V & GND
Ultrasonic sensor is connected & working properly.

Results:
This is the output of serial monitor

Pot is working, Threshold value is changing
Ultrasonic sensor is also working & book distance is changing
BUT the intensity of the LED stays almost the same. it stays dimmer & doesn’t get brighter if the bookDistance < thresholdDistance.
I think I am missing something, can’t find it out. please guide.

I want to add the 15 seconds delay before dimming the light as Mr. Robtillaart suggested. What will be more efficient for this action? delay() or millis()?
thanks for your time for realizing the issue.

  if (bookDistance < thresholdDistance)
  {
  analogWrite(led, 250);   // turn the LED on (HIGH is the voltage level)
 // delay(10); 
  }
  else
  analogWrite(led, 128);  // <<<<<<<<<<<<<<<<<< use a lower value here?

Maybe try your LED to a PWM pin, like 3/5/6/9/10/11? This happened to me a few days ago when I was using pin A0 for a similar dim to bright test. When I switched to a PWM pin it worked perfectly.

Good morning :slight_smile:
I just get up & see your replies… The Dimming issue is solved. I used PWM pin 3 & the system is working as it is expected to.

Now the second half, How to add a 15 second delay before dimming the lights & finally a 2 minute delay before completely turn off the lights?

This is the full working code with PWM pin3. Before I was using A0 pin but with pin3 I get the best results…

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int led = 3; //PWM pin 3 fro LED output
int pot = A5; // set the A5 pin as potmeter's output
int potValue = 0;  // potmeter value will be stored here
int bookDistance = 0;   //ultrasonic sensor reading
int thresholdDistance = 0;  // potmeter value is mapped to determine the threshold distance

void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
  pinMode(led, OUTPUT);
  pinMode(pot, INPUT); 
}

void loop() {
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("BookDistance: ");
  bookDistance = uS / US_ROUNDTRIP_CM; //the function uS / US_ROUNDTRIP_CM returns the ultrasonic reading in cm
  Serial.print(bookDistance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  
  potValue = analogRead(pot);  // Read & store the potmeter value
  Serial.print("PotValue: ");
  Serial.println(potValue);
  
  thresholdDistance = map(potValue, 0, 1023, 10, 50);
  Serial.print("ThresholdDistance: ");
  Serial.println(thresholdDistance);
  
  if (bookDistance < thresholdDistance)
  {
  analogWrite(led, 255);   // turn the LED on (HIGH is the voltage level)
 // delay(10); 
  }
  else
  analogWrite(led, 102); 
}

Thanks Rob for your suggestions & gawain7 for your quick tweak
Thanks to the community.
cheers…

Now the second half, How to add a 15 second delay before dimming the lights & finally a 2 minute delay before completely turn off the lights?

The better implementation is to make a small state machine for the LED, and let the sensors control the state transitions.
a state is nothing more/less than an integer value (ok enums are better)

have a look at the following snippet, read it good and try to understand what it does before copying it in your sketch.

// the 4 states of the LED
#define STATE_OFF   0   // led == off
#define STATE_ON    1   // led = 100%
#define STATE_DECREASE1  2   // led goes from 100% -> 30% in 15 seconds
#define STATE_DECREASE2 3   // led goes from 30% to 0% -> other rate

// var to hold the state
int state = 0;
// var to hold the brightness of the LED
uint8_t brightness = 0;

...

void loop()
{
  bookDistance = getDistance();  // move existing code to function.

  // state transitions code
  switch(state)
  {
  case STATE_OFF:  
    if (bookDistance < thresholdDistance) state = STATE_READ;
    // if there is no book state stays the same.
    break;
  case STATE_ON:  
    if (bookDistance >= thresholdDistance) state = STATE_DECREASE1;
    break;
  case STATE_DECREASE1:  
    if (bookDistance < thresholdDistance) state = STATE_ON;  // for if you fetched another book
    if (brightness <= 100) state = STATE_DECREASE2;
    break;
  case STATE_DECREASE2:  
    if (brightness == 0) state = STATE_OFF;
    break;
  default: state = STATE_OFF
  }

  // set brightness according to state
  switch(state)
  {
  case STATE_OFF:  
    brightness = 0;
    break;
  case STATE_ON:  
    brightness = 255;
    break;
  case STATE_DECREASE1:
    brightness--;
    delay(100);  // determines the rate of dimming
    break;
  case STATE_DECREASE2:  
    brightness--;
    delay(50);
    break;
  default: state = STATE_OFF
  }
// apply brightness to the LED.
analogWrite(led, brightness);

}

a STATE_INCREASE would increase the brightness in a certain rate. the transition from OFF → INCREASE can be triggered by time

Hello,

Thanks for your constant support. I am really trying to understand the code & added the increment case there. But there is a few things to clarify.

  1. STATE_DECREASE1 is defined as 3. can I use the PWM pin 3 in the same code?
  2. why there is 2 separate set of switch state methods with same cases… one with with book distance & the other is with brightness? May I add the conditions & brightness in the same case?

Here is the code I am trying to accomplish with your help. This is the current progress… One more thing, instead of 2 decrement cases I want to add a single decrement case.

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

// the 4 states of the LED
#define STATE_OFF  0   // led == off
#define STATE_INCREASE  1 // increase the brightness
#define STATE_ON  2   // led = 100%
#define STATE_DECREASE1  3   // LED goes from 100% to OFF max 60 seconds
//#define STATE_DECREASE2 4   // led goes from 30% to 0% -> other rate

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int led = 3;                   //PWM pin 3 fro LED output
int pot = A5;                  // set the A5 pin as potmeter's output
int potValue = 0;              // potmeter value will be stored here
int bookDistance = 0;          //ultrasonic sensor reading
int thresholdDistance = 0;    // potmeter value is mapped to determine the threshold distance
// gets the book distance
void getDistance(){
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("BookDistance: ");
  bookDistance = uS / US_ROUNDTRIP_CM; //the function uS / US_ROUNDTRIP_CM returns the ultrasonic reading in cm
  Serial.print(bookDistance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
}
// gets the threshold distance by mapping the potmeter value
void getThreshold(){
  potValue = analogRead(pot);  // Read & store the potmeter value
  Serial.print("PotValue: ");
  Serial.println(potValue);
  thresholdDistance = map(potValue, 0, 1023, 10, 50);
  Serial.print("ThresholdDistance: ");
  Serial.println(thresholdDistance);
}
void setup() {
  Serial.begin(115200);        // Open serial monitor at 115200 baud to see ping results.
  pinMode(led, OUTPUT);
  pinMode(pot, INPUT); 
  int state = 0;              // var to hold the state
  uint8_t brightness = 0;     // var to hold the brightness of the LED
}

void loop() {
  delay(50);                  // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  getDistance();              // chcks & stores the value of book distance
  getThreshold();     // chcks & stores the threshold value

  switch(state)               // state transitions code
  {
  case STATE_OFF:  
    brightness = 0;
    analogWrite(led, brightness);        // apply brightness to the LED.
    if (bookDistance < thresholdDistance) state = STATE_INCREASE;        // if there is no book state stays the same.
    break;
    
  case STATE_INCREASE:
      for (int a = 0; a < 6; a++ ){        // increase the brightness slowly in 5 step
      brightness = brightness + 51;
      analogWrite(led, brightness);      // apply brightness to the LED.
      delay(500);
      }
      state = STATE_ON;
      break;
      
  case STATE_ON:
    brightness = 255;
    analogWrite(led, brightness);        // apply brightness to the LED.    
    if (bookDistance >= thresholdDistance) state = STATE_DECREASE1;
    break;
  case STATE_DECREASE1:  
  
    if (bookDistance < thresholdDistance) state = STATE_ON;  // for if you fetched another book
    
    if (brightness <= 100) state = STATE_DECREASE2;
    break;
.......
.................

I am stuck in the last part of the above code. You put a seperate brightness switch case code there. May I use it in the first set of switch case statements?

  case STATE_DECREASE1:
    brightness--;
    delay(100);  // determines the rate of dimming
    break;

Can’t figure out the exact algo for the following part… suppose during the decremental 60 seconds of time in which I am supposed to fetch the book if I pick up the book withinin 35 or 40 seconds only, the decrement will stop immediately & the light will be on STATE_ON mode?

Thanks for all your time & effort spent for helping us.
Greetings…

Greetings,

The full code is developed. here it is

// ---------------------------------------------------------------------------
// Example NewPing library sketch that does a ping about 20 times per second.
// ---------------------------------------------------------------------------
#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

// the 4 states of the LED
#define STATE_OFF  0   // led == off
#define STATE_INCREASE  1 // increase the brightness
#define STATE_ON  2   // led = 100%
#define STATE_DECREASE1  3   // LED goes from 100% to OFF max 60 seconds
//#define STATE_DECREASE2 4   // led goes from 30% to 0% -> other rate

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int led = 3;                   //PWM pin 3 fro LED output
int pot = A5;                  // set the A5 pin as potmeter's output
int potValue = 0;              // potmeter value will be stored here
int bookDistance = 0;          //ultrasonic sensor reading
int thresholdDistance = 0;    // potmeter value is mapped to determine the threshold distance
// gets the book distance
void getDistance(){
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("BookDistance: ");
  bookDistance = uS / US_ROUNDTRIP_CM; //the function uS / US_ROUNDTRIP_CM returns the ultrasonic reading in cm
  Serial.print(bookDistance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
}
// gets the threshold distance by mapping the potmeter value
void getThreshold(){
  potValue = analogRead(pot);  // Read & store the potmeter value
  Serial.print("PotValue: ");
  Serial.println(potValue);
  thresholdDistance = map(potValue, 0, 1023, 10, 50);
  Serial.print("ThresholdDistance: ");
  Serial.println(thresholdDistance);
}
void setup() {
  Serial.begin(115200);        // Open serial monitor at 115200 baud to see ping results.
  pinMode(led, OUTPUT);
  pinMode(pot, INPUT); 
  int state = 0;              // var to hold the state
  uint8_t brightness = 0;     // var to hold the brightness of the LED
}

void loop() {
  delay(50);                  // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  getDistance();              // chcks & stores the value of book distance
  getThreshold();     // chcks & stores the threshold value

  switch(state)               // state transitions code
  {
  case STATE_OFF:  // This will be the initial state of the system after powering it up.
    brightness = 0;
    analogWrite(led, brightness);        // apply brightness to the LED.
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value
    if (bookDistance < thresholdDistance) state = STATE_INCREASE;        // if there is no book state stays the same.
    break;
    
  case STATE_INCREASE: // This is the transition period from OFF to ON state
     for (int a = 0; a < 6; a++ ){        // increase the brightness slowly in 5 step
     brightness = brightness + 51;
     analogWrite(led, brightness);      // apply brightness to the LED.
     delay(500);
     }
     state = STATE_ON;
     break;
      
  case STATE_ON: // This is the state while reading the book
    brightness = 255;
    analogWrite(led, brightness);        // apply brightness to the LED.  
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value  
    if (bookDistance >= thresholdDistance) state = STATE_DECREASE;
    break;
        
  case STATE_DECREASE:  // This is the 60 seconds time in which the book should be within the range, otherwise the system will be OFF again
    for (int b = 0; b < 60; b++){  //dimming of light & simultaneously checking for the book 
    brightness = brightness - 4;
    analogWrite(led, brightness);      // apply brightness to the LED.
    delay (1000);                // 60 times 1 second = total 1 minute time for fetching the book
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value
    if (bookDistance < thresholdDistance){
      state = STATE_ON;
      break;
         }
      }
    if (brightness <= 20) state = STATE_OFF; // if 60 seconds are over switch to the OFF mode. Brightness will be less than 20 after 60 seconds
    break;
      }
}

I was a little bit confused about the two set of switch case statements as suggested. I tried my best & the results are disappointing… It comes up with errors .:frowning:

_Smart_Lamp.ino: In function 'void loop()':
_Smart_Lamp:53: error: 'state' was not declared in this scope
_Smart_Lamp:56: error: 'brightness' was not declared in this scope
_Smart_Lamp:77: error: 'STATE_DECREASE' was not declared in this scope
_Smart_Lamp:80: error: 'STATE_DECREASE' was not declared in this scope
_Smart_Lamp.ino: In function 'void loop()':
_Smart_Lamp:53: error: 'state' was not declared in this scope
_Smart_Lamp:56: error: 'brightness' was not declared in this scope
_Smart_Lamp:77: error: 'STATE_DECREASE' was not declared in this scope
_Smart_Lamp:80: error: 'STATE_DECREASE' was not declared in this scope

Thanking you in anticipation. Good day.

Hello all, :slight_smile:

Finally the code is up & running. I did mistakes in declaring the variables in wrong place. Now it is working fine.
The code is tested in breadboard only. By this week I will start to develop the actual hardware in veroboard.

Working:
Initially right after powering up the system , the LED is off. When book is within the threshold distance the light slowly increases & then it is fully glowing. The POT is working fine & the threshold distance can be manipulated by using the pot. If no book present the light slowly decreases upto 60 seconds & finally it is OFF. Again if the book comes in the range the light slowly increases & goes to ON mode

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

// the 4 states of the LED
#define STATE_OFF  0   // led == off
#define STATE_INCREASE  1 // increase the brightness
#define STATE_ON  2   // led = 100%
#define STATE_DECREASE  3   // LED goes from 100% to OFF max 60 seconds
//#define STATE_DECREASE2 4   // led goes from 30% to 0% -> other rate

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int led = 3;                   //PWM pin 3 fro LED output
int pot = A5;                  // set the A5 pin as potmeter's output
int potValue = 0;              // potmeter value will be stored here
int bookDistance = 0;          //ultrasonic sensor reading
int thresholdDistance = 0;    // potmeter value is mapped to determine the threshold distance
int brightness = 0;     // var to hold the brightness of the LED
int state = STATE_OFF;              // var to hold the state
// gets the book distance
void getDistance(){
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("BookDistance: ");
  bookDistance = uS / US_ROUNDTRIP_CM; //the function uS / US_ROUNDTRIP_CM returns the ultrasonic reading in cm
  Serial.print(bookDistance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
}
// gets the threshold distance by mapping the potmeter value
void getThreshold(){
  potValue = analogRead(pot);  // Read & store the potmeter value
  Serial.print("PotValue: ");
  Serial.println(potValue);
  thresholdDistance = map(potValue, 0, 1023, 10, 50);
  Serial.print("ThresholdDistance: ");
  Serial.println(thresholdDistance);
}
void setup() {
  Serial.begin(115200);        // Open serial monitor at 115200 baud to see ping results.
  pinMode(led, OUTPUT);
  pinMode(pot, INPUT); 
}

void loop() {
  delay(50);                  // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  getDistance();              // chcks & stores the value of book distance
  getThreshold();     // chcks & stores the threshold value

  switch(state)               // state transitions code
  {
  case STATE_OFF:  // This will be the initial state of the system after powering it up.
    brightness = 0;
    analogWrite(led, brightness);        // apply brightness to the LED.
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value
    if (bookDistance < thresholdDistance) state = STATE_INCREASE;        // if there is no book state stays the same.
    break;
    
  case STATE_INCREASE: // This is the transition period from OFF to ON state
     for (int a = 0; a < 6; a++ ){        // increase the brightness slowly in 5 step
     brightness = brightness + 51;
     analogWrite(led, brightness);      // apply brightness to the LED.
     delay(500);
     }
     state = STATE_ON;
     break;
      
  case STATE_ON: // This is the state while reading the book
    brightness = 255;
    analogWrite(led, brightness);        // apply brightness to the LED.  
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value  
    if (bookDistance >= thresholdDistance) state = STATE_DECREASE;
    break;
        
  case STATE_DECREASE:  // This is the 60 seconds time in which the book should be within the range, otherwise the system will be OFF again
    for (int b = 0; b < 60; b++){  //dimming of light & simultaneously checking for the book 
    brightness = brightness - 4;
    analogWrite(led, brightness);      // apply brightness to the LED.
    delay (1000);                // 60 times 1 second = total 1 minute time for fetching the book
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value
    if (bookDistance < thresholdDistance){
      state = STATE_ON;
      break;
         }
      }
    if (brightness <= 20) state = STATE_OFF; // if 60 seconds are over switch to the OFF mode. Brightness will be less than 20 after 60 seconds
    break;
      }
}

Bugs:
One issue found. While getting into STATE_ON, the light suddenly decrease for an instant then it is fully glowing. The STATE_INCREASE is working fine with 5 increments from off(PWM value 0) to brightest(PWM value 255). Right after the increment when it is time to stay fullt bright, the light dimms for an instant & then glows with full brightness (STATE_ON). Any clue on how to fix it?

Suggestions Needed:

  1. How to make it more power efficient so that it will draw lowest possible amount of current during the ON time & especially in the OFF time as well & I can keep the system always on ?
  2. How to improvise the code to make it more realistic?
  3. Atmega328P is not that much cheaper so I am thinking to upload the sketch on cheaper AVRs such as ATtiny2313. Any suggestions please

Thanks

Hello everybody,
The coding is finally accomplished. & by using the INTERRUPT feature the lamp can be operated in all 3 modes… ON mode, OFF mode & SMART mode.

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 600 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

// the 5 states of the LED
#define STATE_OFF  0   // led == off
#define STATE_INCREASE  1 // increase the brightness
#define STATE_ON  2   // led = 100%
#define STATE_HOLD  3   // LED goes on 255 for 30 seconds
#define STATE_DECREASE 4   // led goes from 100% to 0% -> 30 seconds

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
int led = 3;                   //PWM pin 3 fro LAMP LED output
int pot = A5;                  // set the A5 pin as potmeter's output
int potValue = 0;              // potmeter value will be stored here
int bookDistance = 0;          //ultrasonic sensor reading
int thresholdDistance = 0;    // potmeter value is mapped to determine the threshold distance
int brightness = 0;     // var to hold the brightness of the LED
int state = STATE_OFF;  // var to hold the state, initialise with off state
int button = 0; // pin 2 for INTERRUPT 0 to select the MODE
int onLed = 5; // pin 5 for ON MODE status
int smartLed = 6; // pin 6 for SMART MODE status
int offLed = 7; //pin 7 for OFF MODE status
volatile int sysMode = 1; // volatile integer for holding the surrent state of the system, 1= ON mode, 2= SMART mode, 3= OFF mode
// ISR for selecting the mode
void mode(){
  if (sysMode == 1){ //if system is in ON MODE then switch to SMART MODE
  brightness = 0;   // Initialize SMART MODE with STATE OFF
  analogWrite(led, brightness);        // apply brightness to the LED.
  state = STATE_OFF;
  sysMode = 2;
  }
  else if (sysMode == 2){ //if system is in SMART MODE then switch to OFF MODE
  analogWrite(led, 0);  // apply "no brightness" to the LED. OFF MODE.     
  digitalWrite (onLed, LOW);
  digitalWrite (offLed, HIGH);  //activate only the OFF MODE status led
  digitalWrite (smartLed, LOW);
  state = STATE_OFF;
  sysMode = 3;
  }
  else if (sysMode == 3){ //if system is in OFF MODE then switch to ON MODE
  digitalWrite (onLed, HIGH); //activate only the ON MODE status led
  digitalWrite (offLed, LOW);
  digitalWrite (smartLed, LOW);
  analogWrite(led, 255); // apply full brightness to the LED. ON MODE.
  brightness = 0; 
  sysMode = 1; 
  }
}

// gets the book distance
void getDistance(){
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  Serial.print("BookDistance: ");
  bookDistance = uS / US_ROUNDTRIP_CM; //the function uS / US_ROUNDTRIP_CM returns the ultrasonic reading in cm
  Serial.print(bookDistance); // Convert ping time to distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
}
// gets the threshold distance by mapping the potmeter value
void getThreshold(){
  potValue = analogRead(pot);  // Read & store the potmeter value
  Serial.print("PotValue: ");
  Serial.println(potValue);
  thresholdDistance = map(potValue, 0, 1023, 10, 50);
  Serial.print("ThresholdDistance: ");
  Serial.println(thresholdDistance);
}
void setup() {
  Serial.begin(19200);    // Open serial monitor at 115200 baud to see ping results.
  pinMode(led, OUTPUT);    // Declare the LAMP LED & Status LEDs as UOTPUT
  pinMode (onLed, OUTPUT);
  pinMode (offLed, OUTPUT);
  pinMode (smartLed, OUTPUT);
  pinMode(pot, INPUT); //DEclare the ANALOG input via POT
  attachInterrupt(button, mode, RISING);  // ISR for change the MODE
  digitalWrite (onLed, HIGH); //activate only the ON MODE status led
  digitalWrite (offLed, LOW);
  digitalWrite (smartLed, LOW);
  analogWrite(led, 255); // apply full brightness to the LED. ON MODE.  
}

void loop() {
if (sysMode == 1) analogWrite (led, 255) ;  // ON MODE
else if (sysMode == 2){  // SMART MODE
  digitalWrite (onLed,LOW );
  digitalWrite (offLed, LOW);
  digitalWrite (smartLed, HIGH);  //activate only the SMART MODE status led
  delay(50);                  // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
//  getDistance();              // chcks & stores the value of book distance
//  getThreshold();     // chcks & stores the threshold value
  switch(state)               // state transitions code
  {
  case STATE_OFF:  // This will be the initial state of the system after powering it up.
    delay(10);

    brightness = 0;  // brightness will be 0 at OFF STATE
    analogWrite(led, brightness);        // apply brightness to the LED.
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value
    if (bookDistance < thresholdDistance) state = STATE_INCREASE;        // if there is no book state stays the same.
    break;
    
  case STATE_INCREASE: // This is the transition period from OFF to ON state
     for (int a = 0; a <3; a++ ){        // increase the brightness slowly in 3 steps
     brightness = brightness + 85;
     analogWrite(led, brightness);      // apply brightness to the LED.
     delay(500);
     }
     state = STATE_ON; // Switch to BOOK reading state (STATE_ON)
     break;
      
  case STATE_ON: // This is the state while reading the book
    brightness = 255;
    analogWrite(led, brightness);        // apply brightness to the LED.  
    getDistance();              // chcks & stores the value of book distance
    getThreshold();     // chcks & stores the threshold value  
    if (bookDistance >= thresholdDistance) state = STATE_HOLD;
    break;
        
  case STATE_HOLD:  // This is the 30 seconds time in which the LED will hold the full brightness state even if there is no book.
    for (int b = 0; b < 60; b++){  //dimming of light & simultaneously checking for the book 
      analogWrite(led, brightness);      // apply brightness to the LED.
      delay (500);                // 60 times 1 second = total 1 minute time for fetching the book
      getDistance();              // chcks & stores the value of book distance
      getThreshold();     // chcks & stores the threshold value
      if (sysMode != 2){
        brightness = 0;
        delay(10);
        analogWrite(led, brightness);        // apply brightness to the LED.
        state = STATE_OFF;
        break;
        }
      else if (bookDistance < thresholdDistance){
        state = STATE_ON;
        break;
        }
      }
    if (bookDistance >= thresholdDistance){
        state = STATE_DECREASE;
        break;
      }
    
  case STATE_DECREASE: //30 seconds delay with intensity decrement of LAMP LED. Book should be within the range, otherwise the system will be OFF again
    for (int b = 0; b < 120; b++){  //dimming of light & simultaneously checking for the book 
      brightness = brightness - 2;
      analogWrite(led, brightness);      // apply brightness to the LED.
      delay (250);                // 120 times 0.25 second = total 0.5 minute time for fetching the book
      getDistance();              // chcks & stores the value of book distance
      getThreshold();     // chcks & stores the threshold value
      if (sysMode != 2){
        brightness = 0;
        delay(10);
        analogWrite(led, brightness);        // apply brightness to the LED.
        state = STATE_OFF;
        break;
        }
      else if (bookDistance < thresholdDistance){
        state = STATE_ON;
        break;
        }
      }  
  if (brightness <= 20) state = STATE_OFF; // if 60 seconds are over switch to the OFF mode. Brightness will be less than 20 after 60 seconds
      break;
      }
  }
else if (sysMode == 3) analogWrite (led, 0) ;
}

All credit goes to Mr. Rob Tillaart & I also want to thank PaulS, PeterH , gawain7 and the entire arduino forum for their support.

Results are exactly as expected. Few logic can be implemented in short & tricky way but since I don’t have any previous experience in coding, I opted to go for simple & lengthy process. Need to know if arduino is supported in ATtiny 2313 chips? Any Idea how to put this code into an ATtiny chip by using my UNO board?

Put it in a box.... :slight_smile: