Leonid Piliptsevich
Published © GPL3+

Sensal - All Senses Alarm Clock

Wake up, get productive or sleepy with the help of all available senses only when you need it.

IntermediateWork in progress5 hours17,669
Sensal - All Senses Alarm Clock

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Real Time Clock (RTC)
Real Time Clock (RTC)
http://playground.arduino.cc/Main/DS1302RTC
×1
LED (generic)
LED (generic)
3w
×3
FemtoBuck LED Driver
SparkFun FemtoBuck LED Driver
any adjustable led driver
×1
DHT11 Temperature & Humidity Sensor (4 pins)
DHT11 Temperature & Humidity Sensor (4 pins)
×1
SparkFun Serial Enabled LCD Kit
SparkFun Serial Enabled LCD Kit
my version- https://arduino-info.wikispaces.com/LCD-Blue-I2C
×1
Resistor 10k ohm
Resistor 10k ohm
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Photo resistor
Photo resistor
×1
9V 1A Switching Wall Power Supply
9V 1A Switching Wall Power Supply
i use 12v 2a
×1
Breadboard (generic)
Breadboard (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
SparkFun Analog joystick
×1

Story

Read more

Schematics

Sensal

Sensal

Code

Arduino sketch for Sensal

Arduino
If you cannot understand my comments, please feel free to write me.
Also for now you have to reflash it every time you want to change your alarm time.
// I assume you know how to connect the DS1302 and LCD.
// DS1302:  RST pin    -> Arduino Digital 5 (red)
//          DAT pin   -> Arduino Digital 6 (orange)
//          SCLK pin  -> Arduino Digital 7 (yellow)
//          VCC pin   -> - (my rtc works only from a built in battery, otherwise it returns an error, so no connection here)
//          GND pin   -> GND
// LCD:     SLC       -> analog  A5(black)
//          SDA       -> analog  A4(white) 
//          VCC       -> VCC
//          GND       -> GND
// A0 -> light control (on GND  photoresistor, on +5v resistor (10k))
// pin 9 -> PWM light control + 1k resistor
// pin 12-> DHT11 (s)
// pin2 -> SW (joystick)
// A2 -> WRy (joystick)
// A1 -> WRx (joystick)
/*
 * 
 Parts:
 - lcd i2c display
 - photoresistor to control LCD backlight
 - joystick
 - RTC module ds1302
 - DHT11 temperature and humidity sensor
 - powerfull LEDs
 - PWM adjustable 
 Soon:
 - speaker
 - relay to control powerful heater
 - fan(s) and small heater to make an aromatizer
 - windows lock
 - much-much more...

Functions:
- shows time, date, temperature, humidity, and alarm time on different screens
- Alarm. Only light alarm for now, sound, heat, smell will be when i get more hardware
- Light. Just click joystick to switch it on and off.
  
*/

//<Wire.h> Needed for LiquidCrystal_I2C.h library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DS1302RTC.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DHT.h>
#define LED_PIN 9
#define DHTPIN 12
#define DHTTYPE DHT11
#define LDR_PIN A0
#define axis_X A1    // horizontal (Х)  Analog 1
#define axis_Y A2    // Vertical (Y)  Analog 2
#define axis_Z 2    //  Z (joystick button)  Digital 2
int value_X, value_Y, value_Z = 0;    // variable to save joystick state
boolean buttonWasUp = true;  // variable to save button state
boolean ledEnabled;  // Are LEDs are turned on?
unsigned long previousMillis = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
boolean ledAlarmIsOn = false;
byte lastBrightnessLevel;
byte ledBrightness = 0;
byte screenNum = 0;
byte lastScreenNum = 0;
byte alarmHour = 19; // set alarm hours
byte alarmMinute = 28; // set alarm minutes
byte cursorNum = 0;
// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);
// Init the DS1302
// Set pins:  CE(rst), IO(dat),CLK
DS1302RTC RTC(5, 6, 7);
// Init the LCD
//   initialize the library with the numbers of the interface pins (sda-a4; scl-a5)
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  pinMode(13, OUTPUT);
 // Serial.begin(9600);
  pinMode(axis_Z, INPUT_PULLUP); // joystick button
 analogWrite(LED_PIN, ledBrightness); // LEDs are turned off by default 
  // Setup LCD to 16x2 characters
  lcd.init();//initialize screen
  dht.begin();//initialize dht11 sensor
  setSyncProvider(RTC.get);          // the function to get the time from the RTC
  // Alarm daily
  Alarm.alarmRepeat(alarmHour, alarmMinute , 0, MorningAlarm); // alarm time
}


void loop()
{

  // turn LEDs on if alarm is on.  (pause in milliseconds between brightness levels, 
  //starting level of brightness , final level of brightness,
  //should it blink in a given range)
  AlarmLed(3000, 0, 40, false);
  AlarmLed(1500, 40, 70, false);
  AlarmLed(100, 60, 220, false);
  AlarmLed(50, 60, 220, true);
  readJoystick(); //read joystick movements
  click (); // read joystick button state
  joystick(); // //control LED brightness with joystick
  screenBacklight(); // screen autobrightness
  screens(screenNumX()); // showing different screens
  Alarm.delay (1);   // Wait small time before repeating, needed for aralm
}


void print2digits(int number) {
  if (number >= 0 && number < 10) {
    lcd.write('_');
  }
  lcd.print(number);
}

// this method is needed for alarm to work
void MorningAlarm() {
  ledAlarmIsOn = true;
}

// control LED. (on-off-blinking in given range of brightness) (pause in milliseconds between brightness levels, 
//starting level of brightness , final level of brightness,
  //should it blink in a given range)
void AlarmLed(unsigned int interval, int startLed, int endLed, boolean blink) {
  // was brightness decreasing?
  if ( ledBrightness == endLed  || ledBrightness < lastBrightnessLevel) {
    if(ledBrightness != startLed && blink == true && (unsigned int)(millis() - previousMillis) >= interval )
    {
      previousMillis = millis();
      lastBrightnessLevel = ledBrightness;
      ledBrightness--;
      analogWrite(LED_PIN, ledBrightness);
    }
  }
  // was brightness increasing?
  else if (ledBrightness == startLed || ledBrightness >= lastBrightnessLevel) {
    if (ledAlarmIsOn == true  && ledBrightness < endLed  && ((unsigned int)(millis() - previousMillis) >= interval) ){
      previousMillis = millis();
      lastBrightnessLevel = ledBrightness;
      ledBrightness++;
      analogWrite(LED_PIN, ledBrightness);
    }
  }
}


void  click () {
  value_Z = digitalRead(axis_Z);   // read joystick butoon state
    // is button pressed now?
  boolean buttonIsUp = digitalRead(axis_Z);
  // if was up (&&) and not up now»...
  if (buttonWasUp && !buttonIsUp) {
    // ...it may be click or fault signal, so we wait a little
    delay(5);
    // ... and read signal again
    buttonIsUp = digitalRead(axis_Z);
    if (!buttonIsUp) {  // if it is still presed
      // ...it is a click. Revert LED state
      ledEnabled = !ledEnabled;
      if (ledEnabled  ) {
        ledBrightness = 110;
        analogWrite(LED_PIN, ledBrightness);
     
      }
      else if (ledAlarmIsOn) {
        ledAlarmIsOn = false;
        ledBrightness = 0;
        analogWrite(LED_PIN, ledBrightness);
         }
      else {
        ledBrightness = 0;
        analogWrite(LED_PIN, ledBrightness);
         }
    }
  }
  buttonWasUp = buttonIsUp;   // remember last state of the button
}


void screenBacklight() {
  // screen autobrightness
  if ( analogRead(LDR_PIN) >= 890 && ledAlarmIsOn == false) {

    lcd.noBacklight();
  }
  else {
    lcd.backlight();
  }
}

//control LED brightness with joystick
void joystick() {

  if (ledEnabled)

  {
    
    if (millis() >= (previousMillis + 200)) {            // comparing current time with previous time plus 0.2 seconds

      previousMillis = millis();

      if (value_Y >= 0 && value_Y < 50 && ledBrightness > 1)        ledBrightness -= 2;
      else if (value_Y >= 0 && value_Y < 50 && screenNum == 1 )       cursorNum--;
      if (value_Y > 50 && value_Y < 485 && ledBrightness > 0)        ledBrightness--;
      else if (value_Y > 50 && value_Y < 485 && screenNum == 1 )        cursorNum--;
      if (value_Y > 495 && value_Y < 900 && ledBrightness < 160)     ledBrightness++;
      else if (value_Y > 495 && value_Y < 900 && screenNum == 1 )        cursorNum++;
      if (value_Y > 980 && ledBrightness < 159)       ledBrightness += 2;
      else if (value_Y > 980  && screenNum == 1 )       cursorNum ++;
      analogWrite(LED_PIN, ledBrightness);
    }
  }
}

// change screen number
byte screenNumX() {

  lastScreenNum = screenNum;
  if (millis() >= (previousMillis1 + 500)) {            //  comparing current time with previous time plus 0.5 seconds
    previousMillis1 = millis();
    if (value_X >= 0 && value_X < 490  ) screenNum++;
    if (value_X > 510 && value_X > 980 ) screenNum++;
  }
  if (screenNum > 1) screenNum = 0;
  return screenNum;
}

// change screen depending on screen number
void screens(byte x) {
  if (lastScreenNum != screenNum)   lcd.clear(); // if screen is changing, clear it before change
  if (screenNum == 0   ) {

    // print current ledbrightness
    lcd.setCursor(13, 1);
    lcd.print(ledBrightness);
    lcd.print(F("   "));

    int h = dht.readHumidity(); // Read Humidity
    int t = dht.readTemperature(); // Read temperature as Celsius
    // print humidity
    lcd.setCursor(9, 0);
    lcd.print('h');
    lcd.setCursor(10, 0);
    lcd.print(h);
    // print temp
    lcd.setCursor(13, 0);
    lcd.print('t');
    lcd.setCursor(14, 0);
    lcd.print(t);

    static int sday = 0;// Saved day number for change check

    // Display time centered on the upper line
    lcd.setCursor(0, 0);
    print2digits(hour());
    lcd.print(' ');
    print2digits(minute());
    lcd.print(' ');
    print2digits(second());

    // Update in 00:00:00 hour only
    if (sday != day() || lastScreenNum != 0 ) {
      // Display abbreviated Day-of-Week in the lower left corner
      lcd.setCursor(0, 1);
      lcd.print(dayShortStr(weekday()));
      // Display date in the lower right corner
      lcd.setCursor(4, 1);
      lcd.print(' ');
      print2digits(day());
      lcd.print('/');
      print2digits(month());
      //   lcd.print("/");
      //   lcd.print(year());
    }
    // Warning!
    if (timeStatus() != timeSet) {
      lcd.setCursor(0, 1);
      lcd.print(F("RTC ERROR: SYNC!"));
    }
    // Save day number
    sday = day();
  }

  else if (screenNum == 1 && lastScreenNum != screenNum) {

    if (cursorNum == 0 || cursorNum == 1) {

      if (millis() >= (previousMillis2 + 100)) {   // comparing current time with previous time plus 0.1 seconds
        previousMillis2 = millis();

        lcd.setCursor(0, 0);
      }
      lcd.print(alarmHour);
      lcd.print(' ');
      lcd.print(alarmMinute);
    }
  }
}

void readJoystick() {
  value_X = analogRead(axis_X);    // read horizontal (Х)  joystick
  value_Y = analogRead(axis_Y);    // read vertical (y) joystick
}

Credits

Leonid Piliptsevich

Leonid Piliptsevich

1 project • 9 followers

Comments