#include <SPI.h>
#include <ShiftPWM.h> // include ShiftPWM.h after setting the pins!
#include <Wire.h>
#include <EEPROM.h>
#define DS1307_I2C_ADDRESS 0x68 // This is the I2C address
const int ShiftPWM_latchPin=8;
const bool ShiftPWM_invertOutputs = 0; // if invertOutputs is 1, outputs will be active low. Usefull for common anode RGB led's.
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
int numRegisters = 3;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
int command = 0; // This is the command char, in ascii form, sent from the serial port
//My LED setup...
//
//0 - UV
//1 - Blue
//2 - Red
//3 - Red
//4 - Yellow
//5 - Yellow
//6 - White
//7 - White
//
//8,9,10,11,12,13,14,15 - White
//
//16 - UV
//17 - UV
//18 - Blue
//19 - Red
//20 - Red
//21 - Yellow
//22 - White
//23 - White
int num_led_steps = 24;
int led_on_order[24] = {16, 0,17, 1,18, 2,19, 3,20, 4,21, 5, 8, 9, 6,22, 7,23,10,11,12,13,14,15};
int led_off_order[24] = {-1,-1,-1,-1,-1,-1,-1,-1, 1,18,-1,-1, 2,19, 3,20,-1,-1,-1,-1,-1,-1,-1,-1};
int alarm_hour = 0;
int alarm_minute = 0;
int days_to_alarm[7] = {0,0,0,0,0,0,0};
int alarm_current_position = 0;
long last_action_time = 0;
int alarm_duration = 24; //number of minutes for alarm to take.
int time_between_up = 1000;
long now = 0;
int i,j;
void setup()
{
//Set up ShiftPWM
pinMode(ShiftPWM_latchPin, OUTPUT);
SPI.setBitOrder(LSBFIRST);
// SPI_CLOCK_DIV2 is only a tiny bit faster in sending out the last byte.
// SPI transfer and calculations overlap for the other bytes.
SPI.setClockDivider(SPI_CLOCK_DIV4);
SPI.begin();
//Begin Wire protocol for reading from clock chip
Wire.begin();
//Serial so you can read and report the time and alarm.
Serial.begin(9600);
//read the stored alarm time.
alarm_hour = EEPROM.read(0);
alarm_minute = EEPROM.read(1);
days_to_alarm[0] = EEPROM.read(2);
days_to_alarm[1] = EEPROM.read(3);
days_to_alarm[2] = EEPROM.read(4);
days_to_alarm[3] = EEPROM.read(5);
days_to_alarm[4] = EEPROM.read(6);
days_to_alarm[5] = EEPROM.read(7);
days_to_alarm[6] = EEPROM.read(8);
//Set up the shiftPWM constants
ShiftPWM.SetAmountOfRegisters(numRegisters);
ShiftPWM.Start(pwmFrequency,maxBrightness);
//Everything off.
ShiftPWM.SetAll(0);
long calc = (long)(alarm_duration * 60l * 1000l);
calc = calc / ((long)(num_led_steps * maxBrightness));
time_between_up = (int)calc;
Serial.print("Value Shift Amount: ");
Serial.println(time_between_up);
}
void loop()
{
now = millis(); //get the time now.
if (now - last_action_time > 1000) //read and deal with the alarm only every second.
{
last_action_time = now;
getDateDs1307(); //sets the global date/time constants
if (days_to_alarm[(dayOfWeek-1)] == 1)
{
if ((hour*60+minute) == ((alarm_hour*60+alarm_minute)-alarm_duration)) //if we're an appropriate number of minutes before the alarm is to be finished, start the alarm.
{
alarm_go();
}
if ((hour*60+minute) == ((alarm_hour*60+alarm_minute)+120)) //turn the lights off after 2 hours.
{
for (int i=maxBrightness; i>=0; i--)
{
ShiftPWM.SetAll(i);
delay(100);
}
}
}
}
/**
* With this code you can set the date/time, retreive the date/time and use the extra memory of an RTC DS1307 chip.
* Serial Communication method with the Arduino that utilizes a leading CHAR for each command described below.
* Commands:
* T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99) - T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year) - T Sets the date of the RTC DS1307 Chip.
* Example to set the time for 02-Feb-09 @ 19:57:11 for the 3 day of the week, use this command - T1157193020209
* A(00-59)(00-23)(0-1)(0-1)(0-1)(0-1)(0-1)(0-1)(0-1)
* Set alarm to the alarm time. each 0/1 after the hour is the day of the week to alarm or not, sunday-saturday.
*/
if (Serial.available()) { // Look for char in serial que and process if found
command = Serial.read();
if (command == 84) { //If command = "T" Set Date
setDateDs1307();
}
if (command == 65) {
setAlarm();
}
}
command = 0; // reset command
delay(100);
}
void alarm_go()
{
for(i = 0; i < num_led_steps; i++)
{
for (j = 0; j <= maxBrightness; j++)
{
ShiftPWM.SetOne(led_on_order[i],j); //follow the order of turning lights on
if (led_off_order[i] != -1) //and the ones you want to turn off.
{
ShiftPWM.SetOne(led_off_order[i],maxBrightness-j);
}
delay(time_between_up);
}
}
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
void getDateDs1307()
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x00);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
second = bcdToDec(Wire.receive() & 0x7f);
minute = bcdToDec(Wire.receive());
hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
dayOfWeek = bcdToDec(Wire.receive());
dayOfMonth = bcdToDec(Wire.receive());
month = bcdToDec(Wire.receive());
year = bcdToDec(Wire.receive());
Serial.print(">");
Serial.print(hour, DEC);
Serial.print(":");
Serial.print(minute, DEC);
Serial.print(":");
Serial.print(second, DEC);
Serial.print(" ");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.print(",");
Serial.print(alarm_hour);
Serial.print(":");
Serial.print(alarm_minute);
Serial.print(",");
for (i=0;i<7;i++)
{
if (days_to_alarm[i] == 1)
Serial.print("*");
else
Serial.print("-");
}
Serial.println();
}
void setDateDs1307()
{
second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
dayOfWeek = (byte) (Serial.read() - 48);
dayOfMonth = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x00);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}
void setAlarm()
{
alarm_minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
alarm_hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
days_to_alarm[0] = (byte) (Serial.read() - 48);
days_to_alarm[1] = (byte) (Serial.read() - 48);
days_to_alarm[2] = (byte) (Serial.read() - 48);
days_to_alarm[3] = (byte) (Serial.read() - 48);
days_to_alarm[4] = (byte) (Serial.read() - 48);
days_to_alarm[5] = (byte) (Serial.read() - 48);
days_to_alarm[6] = (byte) (Serial.read() - 48);
EEPROM.write(0,alarm_hour);
EEPROM.write(1,alarm_minute);
EEPROM.write(2,days_to_alarm[0]);
EEPROM.write(3,days_to_alarm[1]);
EEPROM.write(4,days_to_alarm[2]);
EEPROM.write(5,days_to_alarm[3]);
EEPROM.write(6,days_to_alarm[4]);
EEPROM.write(7,days_to_alarm[5]);
EEPROM.write(8,days_to_alarm[6]);
}