Use Light to Wake Up (LAMP-ALARM) Sunrise Alarm Pendant Lamp

by MakeUnited in Circuits > Assistive Tech

4339 Views, 66 Favorites, 0 Comments

Use Light to Wake Up (LAMP-ALARM) Sunrise Alarm Pendant Lamp

Imagen2.png
Lamp Alarm

Waking up, we all do it at least once a day. The problem is that everyone does it at different times and in different ways.

Most people use sound to wake up, and many hate it. But did you know that:

  • According to WHO, 5% of the world population has some sort of hearing impairment? (They can’t hear sound very well)
  • Also, sound doesn't just stay in your room, it travels through walls. (It can wake up other people unintentionally)


Instead of sound, we can use light

Introducing “Lamp-Alarm”.

This is an alarm, in form of a lamp, that turns on the light gradually, like the sunrise, to wake you up. You only have to configure 4 things. Find settings on the menu and:

  • Select the hour and minute to which it should be completely turned on.(Use the rotary encoder to navigate and configure)
  • Then, how many minutes before it should start lighting up.
  • Finally, how many minutes later it will be on, at full power.

As always:

Your word is a lamp for my feet, a light on my path.
Psalm 119:105

Without God, this project wouldn’t have been possible. Thank you very much!!


OK! If you want a LAMP-ALARM, here is what you need:

Supplies

Electronics:

  • 1x Arduino Nano
  • 1x TIP35C Transistor
  • 1x 0.96''OLED Display
  • 1x Rotary Encoder+Switch
  • 1x RTC time module
  • 1x MCP4725 12-bit DAC Converter
  • 1x Perfboard 15x15cm
  • 2x 2 Pin Screw Blue PCB Terminal
  • 80x Straigh Pin Headers
  • 10x 90° Pin Headers
  • 4 [meters] of 2 Conductor Wire
  • 1x 12v-2A Power Supply
  • 1x Normal Screw Socket for Light Bulbs
  • 1x 12v Light Bulb

Mechanics:

  • Pieces of Wood
  • Screws
  • Metal Brackets (Flat and Normal L types)
  • U Shaped Nails
  • White Glue
  • Black Paint
  • Paint Brush

Tools:

  • Soldering Iron + Tin
  • Drill
  • Screw Drivers
  • Saw
  • Ruler
  • Wire Cutter
  • Sand Paper
  • Multimeter

Electronics Schematic

Squematic.png

The circuit is very simple. It doesn't have too many components and each one has a very important function:

  • Arduino Nano: It's the brain that commands everything.
  • OLED Display: This one displays all the information about time and alarms.
  • RTC Time Module: Thanks to this, we can know what time it is without worrying about the power supply of the Arduino.
  • Rotary Encoder: It helps you configure the alarms and navigate through the menu.
  • DAC Module: It increases the resolution of our PWM signal from 8-bit to 12-bit.
  • Transistor: It is our bridge between 5V and 12V. Thanks to it, we can control the LED Light Bulb.
  • Screw Mounts: They make connecting and disconnecting wires easy.

If you notice, all the connections are distributed to work on a Perfboard without extra cables. No crossovers.

Arduino Code

Arduino Code.png

So, we want to make a lamp that lights up gradually (like the sunrise) and waits fully lighted up for some time and then it must shut down. We also must be able to configure the alarm in situ.

So we need to start programming. First, we need some libraries:

#include <Wire.h>
#include <RTClib.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MCP4725.h>

Then we need to define some variables for the range in 0 to 4095 where the transistor works as a variable resistor:

long minRes=400;
long maxRes=700;

Now we have the RTC variables:

// * RTC Variables
RTC_DS3231 rtc;
int a_hora=5;
int a_minuto=00;
int minutos_antes=5;
int minutos_despues=5;

Now some variables to program the alarm:

// * Alarm Variables
int i_hora;
int i_minuto;
int f_hora;
int f_minuto;
int start_alarm=0;
long c;
int segundo_anterior;
int rise=0;
long segundos_rise=minutos_antes*60;

Remember that we wanted to configure the alarm in situ. That means that we don't need to plug the arduino to our PC's and upload the program. We can achive this with a menu. On the first page we will have the time shown and on the second we can start changing the alarm parameters with the rotary encoder.

// * Menu Variables
int pagPrincipales=2;
int posPaginas=5;
int maxPos=pagPrincipales*posPaginas;
int pag1=0;
int subMenuPag2=0;

Now we have some variables for the DAC:

// * DAC Variables
Adafruit_MCP4725 dac;

For the Rotary Encoder:

// * Rotary Encoder Variables
int xPos = 0;                                     
volatile int pinA = 4;                            
int pinB = 3;  
int switchPin = 2; 
int switchState = HIGH;                           
volatile int pinAstateCurrent = LOW;              
volatile int pinAStateLast = pinAstateCurrent; 

Now for the OLED.

WARNING!!!

.........................

You have to be carefull with this. Verify (scan) the address of your OLED. Here is a tutorial on how to do it. Then if it is different, change it:

// * OLED Variables
#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
#define OLED_RESET    -1 
#define SCREEN_ADDRESS 0x3C 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

So now that we have a menu, we want to make it more appealing. Thus, we inserted an image of a clock. We followed this tutorial to make it possible. If you want something different you can change it. Here is the image on hex code:

const unsigned char clockAlarm [] PROGMEM = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x03, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x1f, 0xf8, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0xff, 0xfe, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc3, 0xff, 0xff, 0x87, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x87, 0xff, 0xff, 0xc3, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1f, 0xf0, 0x1f, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x01, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x80, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x03, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x80, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x03, 0x80, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x80, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x80, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x03, 0xc0, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x07, 0xe0, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0xfc, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x3e, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x1f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x7f, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x07, 0xe0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

And the last variables are to reduce the false pressings of the switch from the rotary encoder. (Debounce):

// * Debounce Variable
long startTimeDeb = 0;

Now we have the void Setup where we turn and configure all the sensors and calculate minutes and hours for the alarm to turn on correctly. We also use interrupts for the switch and rotary encoder:

// ****************    SETUP    **************** //

void setup(){
 Serial.begin(9600);

 // ** DAC Configuration

 dac.begin(0x60);
 dac.setVoltage(0,false);

 // ** OLED Configuration
 if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
   Serial.println(F("SSD1306 allocation failed"));
   for(;;); // Don't proceed, loop forever
 }
 display.display();
 display.clearDisplay();

 // ** RTC Configuration
 if (! rtc.begin()){
   Serial.println("No hay un módulo RTC");
   while (1);
 }
 //rtc.adjust(DateTime(2021, 9, 20, 18, 29, 0)); To adjust RTC module date and time

 // ** Alarm Configuration
 if(a_minuto-minutos_antes<0){
   i_hora=a_hora-1;
   i_minuto=60-(minutos_antes-a_minuto);
 }else{
   i_hora=a_hora;
   i_minuto=a_minuto-minutos_antes;
 }
  if(a_minuto+minutos_despues>59){
   f_hora=a_hora+1;
   f_minuto=minutos_despues+a_minuto-60;
 }else{
   f_hora=a_hora;
   f_minuto=a_minuto+minutos_despues;
 }
 segundos_rise=minutos_antes*60;

 // ** Rotary Encoder Configuration
 pinMode (switchPin, INPUT_PULLUP);
 pinMode (pinA, INPUT);                  
 pinMode (pinB, INPUT);                  
 attachInterrupt(digitalPinToInterrupt(pinB), update, CHANGE);
 attachInterrupt(digitalPinToInterrupt(switchPin), switchPressed, FALLING);

}

Now we have the void loop where it configures what is shown on the screen, it also checks if it is time to start the alarm, it also configures the intensity of the light bulb on the different stages of the alarm:

// ****************    LOOP    **************** //

void loop(){
 DateTime now = rtc.now();
 int pag1Time =1;
 // Page 1 Time
 if(xPos>=0 && xPos<pag1Time*posPaginas && subMenuPag2==0){
   display.clearDisplay();
   display.setTextSize(4);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,20);
   String timeval = String(now.hour())+":"+String(now.minute());
   display.println(timeval);
   display.setRotation(2);
   display.display(); 
 }
 // Page 2 Alarm Setup Menu 
 if(xPos>=1*posPaginas && xPos<=2*posPaginas && subMenuPag2==0){
   display.clearDisplay();
   display.drawBitmap(0,0,clockAlarm,128,64, WHITE);
   display.setTextSize(1);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(30,0);
   display.println("Configuracion");
   display.setRotation(2);
   display.display();
 }

 if(subMenuPag2==1){
   display.clearDisplay();
   display.setTextSize(4);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,20);
   display.println(a_hora);
   display.setTextSize(2);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,0);
   display.println("Hora");
   display.setRotation(2);
   display.display(); 
 }
 if(subMenuPag2==2){
   display.clearDisplay();
   display.setTextSize(4);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,20);
   display.println(a_minuto);
   display.setTextSize(2);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,0);
   display.println("Minuto");
   display.setRotation(2);
   display.display(); 
 }
 if(subMenuPag2==3){
   display.clearDisplay();
   display.setTextSize(4);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,20);
   display.println(minutos_antes);
   display.setTextSize(1);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,0);
   display.println("Minutos Antes");
   display.setRotation(2);
   display.display(); 
 }
 if(subMenuPag2==4){
   display.clearDisplay();
   display.setTextSize(4);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,20);
   display.println(minutos_despues);
   display.setTextSize(1);
   display.setTextColor(SSD1306_WHITE);
   display.setCursor(0,0);
   display.println("Minutos Despues");
   display.setRotation(2);
   display.display(); 
 }

 // *** Alarm and Light Actions
 if(now.hour()==i_hora && now.minute()==i_minuto && now.second()==0){
   start_alarm=1;
   c=0;
   segundo_anterior=0;
 }
 if(start_alarm==1 && segundo_anterior!=now.second()){
   c++;
   segundo_anterior=now.second();
   int intensidad = minRes+(maxRes-minRes)*c/segundos_rise;
   dac.setVoltage(intensidad,false);
   Serial.println("Intensidad: "+ String(intensidad));
 }

 if(now.hour()==a_hora && now.minute()==a_minuto && now.second()==0){
   start_alarm=0;
   dac.setVoltage(maxRes,false);
 }
 if(now.hour()==f_hora && now.minute()==f_minuto && now.second()==0){
   dac.setVoltage(0,false);
 }

 delay(100);

}

We use an extra function to update the menu and alarm values when the rotary encoder is moved:

void update(){
 // ROTATION DIRECTION
 pinAstateCurrent = digitalRead(pinA);   // Read the current state of Pin A
 // If there is a minimal movement of 1 step
 if ((pinAStateLast == LOW) && (pinAstateCurrent == HIGH)) { 
   if (digitalRead(pinB) == HIGH) {     // If Pin B is HIGH
     xPos++;
     if(subMenuPag2==0){
       if(xPos>maxPos){
         xPos=0;
       }
     }
     if(subMenuPag2==1){
       if(xPos>23){
         xPos=0;
       }
       a_hora=xPos;
     }
     if(subMenuPag2==2){
       if(xPos>59){
         xPos=0;
       }
       a_minuto=xPos;
     }
     if(subMenuPag2==3){
       if(xPos>59){
         xPos=0;
       }
       minutos_antes=xPos;
     }
     if(subMenuPag2==4){
       if(xPos>59){
         xPos=0;
       }
       minutos_despues=xPos;
     }


   } else {
     xPos--;
     if(subMenuPag2==0){
       if(xPos<0){
         xPos=maxPos;
       }
     }
     if(subMenuPag2==1){
       if(xPos<0){
         xPos=23;
       }
       a_hora=xPos;
     }
     if(subMenuPag2==2){
       if(xPos<0){
         xPos=59;
       }
       a_minuto=xPos;
     }
     if(subMenuPag2==3){
       if(xPos<0){
         xPos=59;
       }
       minutos_antes=xPos;
     }
     if(subMenuPag2==4){
       if(xPos<0){
         xPos=59;
       }
       minutos_despues=xPos;
     }
   }   
 } 
 pinAStateLast = pinAstateCurrent;       // Store the latest read value in the currect state variable
}

Finally, we use another extra function to verify when the button(switch) from the rotary encoder is pressed. This configures the menu and the alarms:

void switchPressed(){
 Serial.println("Switch pressed");

 if (millis() - startTimeDeb > 150){
   if(subMenuPag2==4){
     subMenuPag2=0;
     xPos=0;
     if(a_minuto-minutos_antes<0){
       i_hora=a_hora-1;
       i_minuto=60-(minutos_antes-a_minuto);
     }else{
       i_hora=a_hora;
       i_minuto=a_minuto-minutos_antes;
     }
      if(a_minuto+minutos_despues>59){
       f_hora=a_hora+1;
       f_minuto=minutos_despues+a_minuto-60;
     }else{
       f_hora=a_hora;
       f_minuto=a_minuto+minutos_despues;
     }
     segundos_rise=minutos_antes*60;
   }
   if(subMenuPag2==3){
     subMenuPag2=4;
     xPos=minutos_despues;
   }
   if(subMenuPag2==2){
     subMenuPag2=3;
     xPos=minutos_antes;
   }
   if(subMenuPag2==1){
     subMenuPag2=2;
     xPos=a_minuto;
   }
   if(xPos>=5 && xPos<=10 && subMenuPag2==0){
     subMenuPag2=1;
     xPos=a_hora;
   }
   startTimeDeb = millis();
 }
}


 ↓ ↓ ↓ Here you have the full code :

Downloads

PCB

PCB Desgin 2.png
PCB Design 2.jpg

To have a good-looking project, we decided that cables were not the right path so a PCB was made. We followed the schematics to solder the paths.

Optional:

  • The components were not soldered directly to the Perfboard. We used headers so the components would be available to use in a future project.

While soldering, use a multimeter to check the connections on the way. Because if you solder everything at once, later it will be extremely difficult to find the mistake.

This tutorial was very helpful on how to solder. Remember not to add to much tin and also wait until your connections are cold to continue.

Lamp Design

Mecanical Design.png
Mechanical Design 1.png

Goodbye electronics, hello mechanics!

This part is a Creative Part! This means that the design depends for who you are making the lamp.

This lamp was designed on the best CAD program:

Autodesk FUSION 360

.............................................

This is the best software to design, simulate, render and animate projects.

I really thank Autodesk Inc. for making such a great and easy way to transalate ideas into reality.

In this case a modern-vintage style lamp alarm was requested. That is why we decided to make it as a pendant lamp.

We started our research and couldn't find any table lamp with this features. So, we thought that it was a great idea!

Downloads

Lamp Construction

Sunrise Alarm GIF.gif

Here you have a GIF on how to assemble the screws with the pieces of wood. You can use glue before putting the screws for a better seal.

The wood used in this project were leftovers (trash) from a carpentry. Use should:

  1. Get the pieces of wood that you like
  2. Buy screws that fit the sizes of the wood

A recommendation is to drill a hole before putting the screws. The diameter of the hole must be less than the diameter of the screw.

You should leave it 12 hours drying.

As we told you before this step is totally up to you and what the end user wants. So be free to design whatever type of lamp you want. Let your creativity flow!

Final Decorations

Final Touches.png

A requirement of this project is to look cool! To achieve it, we did some things:

  • Paint the Light Blub Socket black. It combines with the black chord.
  • Paint the PCB black. It combines with wood and the metal parts.
  • We sanded the wood for a nice finish.
  • Screw the PCB to the base wood.
  • Use Metal Brackets (L type, Normal and Flat) for a vintage/industrial style.
  • We held the cable on one side with U nails. It looks more organized.

If you find a better way to make it cool, don't hesitate to use it!

Congratulations! You Finished!

Lamp.jpg

If you got to this part...

🎉🎉🎉!!!!CONGRATULATIONS!!!! 🎉🎉🎉

Now you have a Cool Alarm Lamp!

Warnings...

20211016_125243.jpg
20211016_125755.jpg

As always you should be careful and ASK for HELP to an ADULT!:

  • Electricity is not a joke. Be careful with your connections. You can cause serious injuries to yourself or people near you.
  • Always use protective gear (eyes, face, mouth, hands, body) when working with tools.
  • It's easier to design first and then build. You reduce time improvising.
  • When soldering the PCB, check your connections on the go. Use a multimeter to verify continuity.
  • Use pin headers in your PCB. This will let you re-use the components.
  • Sand the wood for a better finish.
  • Scan the I2C addresses of each component (specially for the OLED Display) to avoid errors.

Acknowledgment!

This project was a little challenging in the programming section but it was worth it. It was fun hahaha....

I would like to thank God for giving me this opportunity and my family for supporting the projects.

The proposal was achieved and a recommendation is not to hold firmly to the tutorial... BE CREATIVE!!! Try a different style of lamp, new features...

This project solves a problems. Maybe right now it is only helping Two but thanks to Instructables we can reach Thousands!

If you have any question, we are here to answer!