Hackster is hosting Hackster Holidays, Ep. 5: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 5 on Friday!
Jiří Praus
Published © GPL3+

Wake Me Up!

Can light wake you up in the morning?

IntermediateFull instructions provided3 hours9,753

Things used in this project

Story

Read more

Schematics

Schematics of high voltage circuit

Schematics of low voltage circuit

Code

lightalarm.ino

Arduino
A smart light bulb that lights up when its time to get out of your bed.
/*
A smart light bulb that lights up when its time to get out of your bed.

How it works:
1) when power is turned on, the light is switched on as a check that it works
2) it will slowly dim until turned off completelly
3) at 6 am in the morning light will slowly turn on until switched off at the evening
4) light will not turn on when room is not dark anymore (photocell)

How to use:
- turn on the light when going to bed and it will light up the room when you wake up in the morning, turn off light when leaving room to turn it off.
- the time will be preserved due to the DS3231 module

@author Jiri Praus (https://twitter.com/jipraus)

AC Light control inspired by http://arduinotehniq.blogspot.com/2014/10/ac-light-dimmer-with-arduino.html
*/

#include <TimerOne.h> // avaiable from http://www.arduino.cc/playground/Code/
#include "RTClib.h"

#define TRIAC_PIN 2
#define ZERO_CROSS_PIN 3
#define LIGHT_SENSOR_PIN A6

#define FREQUENCY_STEP 75 // This is the delay-per-brightness step in microseconds for 50Hz (change the value in 65 for 60Hz)
#define CHANGE_DIM_LEVEL_EVERY 1 // change dim level every N seconds, slowness of brightining/dimming

#define MAX_DIM_LEVEL 128 // off
#define MIN_DIM_LEVEL 0 // on
#define DARK_THRESHOLD 300 // resistance of photocell when it is consider dark outside

// triac control variables
volatile byte triacCounter = 0; // triac control timer
volatile boolean zeroCrossed = false; // AC phase zero-crossed flag

// dim control
byte dimLevel = MIN_DIM_LEVEL; // on power on, the light is on and will dim slowly as a check
boolean lightOn = false;

// alarm clock
RTC_DS3231 rtc;

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

  digitalWrite(TRIAC_PIN, LOW);
  pinMode(TRIAC_PIN, OUTPUT);
  pinMode(ZERO_CROSS_PIN, INPUT);
  pinMode(LIGHT_SENSOR_PIN, INPUT);

  // init real time clock
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while(1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // following line sets the RTC to the date & time this sketch was compiled
  }

  // initialize interrupts and timers for triac control
  noInterrupts();
  attachInterrupt(digitalPinToInterrupt(ZERO_CROSS_PIN), zeroCrossDetected, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  interrupts();

  Timer1.initialize(FREQUENCY_STEP);
  Timer1.attachInterrupt(triacTimerInterrupt, FREQUENCY_STEP);
}

void loop() {
  delay(CHANGE_DIM_LEVEL_EVERY * 1000);
  checkAlarmClock();
  adjustDimLevel();

  debugPrint();
}

void zeroCrossDetected() {
  zeroCrossed = true; // set the boolean to true to tell our dimming function that a zero cross has occured
  triacCounter = 0; // start counting when triac should be opened
  digitalWrite(TRIAC_PIN, LOW); // turn off light
}

void triacTimerInterrupt() {
  if (dimLevel >= MAX_DIM_LEVEL) { // permanently off
    digitalWrite(TRIAC_PIN, LOW);
  }
  else if (dimLevel <= MIN_DIM_LEVEL) { // permanently on
    digitalWrite(TRIAC_PIN, HIGH);
  }
  else if (zeroCrossed) {
    if (triacCounter >= dimLevel) {
      digitalWrite(TRIAC_PIN, HIGH); // open triac
      zeroCrossed = false; // reset zero cross detection until next half vawe
    } 
    else {
      triacCounter ++;  // increment time step counter
    }
  }
}

void adjustDimLevel() {
  if (lightOn && dimLevel > MIN_DIM_LEVEL) {
    dimLevel--;
  }
  else if (!lightOn && dimLevel < MAX_DIM_LEVEL) {
    dimLevel++;
  }
}

void checkAlarmClock() {
  if (!lightOn && isRoomDark()) { // do not waste energy when room is already light up
    DateTime now = rtc.now();
    if (now.hour() == 6 && now.minute() == 0) {
      lightOn = true; // start alarm clock at 6am
    }
  }
}

boolean isRoomDark() {
  return analogRead(LIGHT_SENSOR_PIN) < DARK_THRESHOLD;
}

void debugPrint() {
  Serial.print("lightOn=");
  Serial.println(lightOn);
  
  Serial.print("dimLevel=");
  Serial.println(dimLevel);
  
  DateTime now = rtc.now();
  Serial.print("datetime=");
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.println(now.second(), DEC);

  Serial.print("lightLevel=");
  Serial.println(analogRead(LIGHT_SENSOR_PIN));
}

Credits

Jiří Praus

Jiří Praus

10 projects • 204 followers
Developer for Samepage.io and hardware maker. I started with a simple Arduino kit two years ago and I fell in love with the platform.

Comments