/*
// Typhon firmware
// v0.2 alpha 2010-23-11
// N. Enders, R. Ensminger
// Changes made by BoostLED have notations as below.
// This sketch provides firmware for the Typhon LED controller.
// It provides a structure to fade 4 independent channels of LED lighting
// on and off each day, to simulate sunrise and sunset.
//
// Current work in progress:
// - store all LED variables in EEPROM so they are not reset by a loss of power
//
// Future developments may include:
// - moon phase simulation
// - storm simulation
//
// Sketch developed in Arduino-18
// Requires LiquidCrystal, Wire, EEPROM, EEPROMVar, and Button libraries.
// Button is available here: http://www.arduino.cc/playground/Code/Button
// EEPROMVar is available here: http://www.arduino.cc/playground/uploads/Profiles/EEPROMVar_01.zip
*/
// include the libraries:
#include <Button.h>
#include <EEPROMVar.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <Wire.h>
/**** Define Variables & Constants ****/
/**************************************/
// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68
// create the LCD
LiquidCrystal lcd(8, 7, 5, 4, 16, 2);
// set up backlight
int bkl = 6; // backlight pin
byte bklIdle = 10; // PWM value for backlight at idle
byte bklOn = 70; // PWM value for backlight when on
int bklDelay = 10000; // ms for the backlight to idle before turning off
unsigned long bklTime = 0; // counter since backlight turned on
// create the menu counter
int menuCount = 1;
int menuSelect = 0;
//create manual override variables
boolean override = false;
byte overmenu = 0;
int overpercent = 0;
// create the buttons
Button menu = Button(12,PULLDOWN);
Button select = Button(13,PULLDOWN);
Button plus = Button(14,PULLDOWN);
Button minus = Button(15,PULLDOWN);
// Button state constants.
byte buttonNotPressed = 0;
byte buttonUniquePress = 1;
byte buttonIsPressed = 2;
byte slowCount = 3; // number of intervals to do a "slowDelay" when holding a button
int slowDelay = 1000; // milliseconds to delay when initially holding a button
int fastDelay = 100; // milliseconds to delay after holding the button for "slowCount" intervals
// LED variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0; // counter that resets at midnight.
int oldMinCounter = 0; // counter that resets at midnight.
EEPROMVar<boolean> inverted = false; //Modified by NetSurge
// Used for button hold down
int intervalCounter = 0;
int oldIntervalCounter;
unsigned long currMil = 0; // current millisecond
int oneVal = 0; // current value for channel 1
int twoVal = 0; // current value for channel 2
int threeVal = 0; // current value for channel 3
int fourVal = 0; // current value for channel 4
// Variables making use of EEPROM memory:
EEPROMVar<int> oneStartMins = 750; // minute to start this channel.
EEPROMVar<int> onePhotoPeriod = 720; // photoperiod in minutes for this channel.
EEPROMVar<int> oneMax = 100; // max intensity for this channel, as a percentage
EEPROMVar<int> oneFadeDuration = 60; // duration of the fade on and off for sunrise and sunset for
// this channel.
EEPROMVar<int> twoStartMins = 810;
EEPROMVar<int> twoPhotoPeriod = 600;
EEPROMVar<int> twoMax = 100;
EEPROMVar<int> twoFadeDuration = 60;
EEPROMVar<int> threeStartMins = 810;
EEPROMVar<int> threePhotoPeriod = 600;
EEPROMVar<int> threeMax = 100;
EEPROMVar<int> threeFadeDuration = 60;
EEPROMVar<int> fourStartMins = 480;
EEPROMVar<int> fourPhotoPeriod = 510;
EEPROMVar<int> fourMax = 100;
EEPROMVar<int> fourFadeDuration = 60;
typedef struct {
int Led; // channel pin
int StartMins; // minute to start this channel.
int PhotoPeriod; // photoperiod in minutes for this channel.
int Max; // max intensity for this channel, as a percentage
int FadeDuration; // duration of the fade on and off for sunrise and sunset for
// this channel.
}
channelVals_t;
channelVals_t channel[4];
/*
int oneStartMins = 1380; // minute to start this channel.
int onePhotoPeriod = 120; // photoperiod in minutes for this channel.
int oneMax = 100; // max intensity for this channel, as a percentage
int oneFadeDuration = 60; // duration of the fade on and off for sunrise and sunset for
// this channel.
int twoStartMins = 800;
int twoPhotoPeriod = 60;
int twoMax = 100;
int twoFadeDuration = 15;
int threeStartMins = 800;
int threePhotoPeriod = 60;
int threeMax = 100;
int threeFadeDuration = 30;
int fourStartMins = 800;
int fourPhotoPeriod = 120;
int fourMax = 100;
int fourFadeDuration = 60;
*/
/****** RTC Functions ******/
/***************************/
// Convert decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// Sets date and time, starts the clock
void setDate(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
// Gets the date and time
void getDate(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
int setLed(int mins, // current time in minutes
int ledPin, // pin for this channel of LEDs
int start, // start time for this channel of LEDs
int period, // photoperiod for this channel of LEDs
int fade, // fade duration for this channel of LEDs
int ledMax // max value for this channel
) {
int val = 0;
//fade up
if (mins > start || mins <= start + fade) {
val = map(mins - start, 0, fade, 0, ledMax);
}
//fade down
if (mins > start + period - fade && mins <= start + period) {
val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
}
//off or post-midnight run.
if (mins <= start || mins > start + period) {
if((start+period)%1440 < start && (start + period)%1440 > mins )
{
val=map((start+period-mins)%1440,0,fade,0,ledMax);
}
else
val = 0;
}
//invert for BuckPuck Functions
//Added by NetSurge
if(inverted){
// val=~val;
// val=val&255;
// ledMax=~ledMax;
// ledMax=100-ledMax;
}
if (val > ledMax) {
val = ledMax;
}
if (val < 0) {
val = 0;
}
if(inverted){
analogWrite(ledPin, map(val, 0, 100, 255, 0));
}
else{
analogWrite(ledPin, map(val, 0, 100, 0, 255));
}
//Debugging info 0-255 PWM Output
//Modified by NetSurge
/*
if(inverted){
if(ledPin == 9){
lcd.setCursor(0,0);
lcd.print(map(val, 0, 100, 255, 0));
}
if(ledPin == 10){
lcd.setCursor(4,0);
lcd.print(map(val, 0, 100, 255, 0));
}
if(ledPin == 11){
lcd.setCursor(8,0);
lcd.print(map(val, 0, 100, 255, 0));
}
if(ledPin == 3){
lcd.setCursor(12,0);
lcd.print(map(val, 0, 100, 255, 0));
}
}
else{
if(ledPin == 9){
lcd.setCursor(0,0);
lcd.print(map(val, 0, 100, 0, 255));
}
if(ledPin == 10){
lcd.setCursor(4,0);
lcd.print(map(val, 0, 100, 0, 255));
}
if(ledPin == 11){
lcd.setCursor(8,0);
lcd.print(map(val, 0, 100, 0, 255));
}
if(ledPin == 3){
lcd.setCursor(12,0);
lcd.print(map(val, 0, 100, 0, 255));
}
}
*/
if(override){
val=overpercent;
}
return val;
}
/**** Display Functions ****/
/***************************/
// format a number of minutes into a readable time (24 hr format)
void printMins(int mins, //time in minutes to print
boolean ampm //print am/pm?
) {
int hr = (mins%1440)/60;
int mn = mins%60;
if(hr<10){
lcd.print(" ");
}
lcd.print(hr);
lcd.print(":");
if(mn<10){
lcd.print("0");
}
lcd.print(mn);
}
// format hours, mins, secs into a readable time (24 hr format)
void printHMS (byte hr,
byte mn,
byte sec //time to print
)
{
if(hr<10){
lcd.print(" ");
}
lcd.print(hr, DEC);
lcd.print(":");
if(mn<10){
lcd.print("0");
}
lcd.print(mn, DEC);
lcd.print(":");
if(sec<10){
lcd.print("0");
}
lcd.print(sec, DEC);
}
void ovrSetAll(int pct){
analogWrite(channel[0].Led, map(pct,0,100,0,255));
analogWrite(channel[1].Led, map(pct,0,100,0,255));
analogWrite(channel[2].Led, map(pct,0,100,0,255));
analogWrite(channel[3].Led, map(pct,0,100,0,255));
}
byte buttonCheck(Button *button) {
if (button->uniquePress()) {
return buttonUniquePress;
}
else if (button->isPressed()) {
return buttonIsPressed;
}
else {
return buttonNotPressed;
}
}
boolean checkButtonAction(Button *button) {
byte buttonState = buttonCheck(button);
unsigned long mil = millis();
if (buttonState == buttonUniquePress) {
intervalCounter = slowCount;
currMil = mil;
return true;
}
else if (buttonState == buttonIsPressed) {
if (intervalCounter > 0) {
if (currMil < (mil - slowDelay)) {
intervalCounter--;
currMil = mil;
return true;
}
}
else {
if (currMil < (mil - fastDelay)) {
currMil = mil;
return true;
}
}
}
return false;
}
/**** Setup ****/
/***************/
void setup() {
// Initialize channel variables. Set LED channel pin and retrieve values from EEPROM
channel[0].Led = 9;
channel[0].StartMins = oneStartMins;
channel[0].PhotoPeriod = onePhotoPeriod;
channel[0].Max = oneMax;
channel[0].FadeDuration = oneFadeDuration;
channel[1].Led = 10;
channel[1].StartMins = twoStartMins;
channel[1].PhotoPeriod = twoPhotoPeriod;
channel[1].Max = twoMax;
channel[1].FadeDuration = twoFadeDuration;
channel[2].Led = 11;
channel[2].StartMins = threeStartMins;
channel[2].PhotoPeriod = threePhotoPeriod;
channel[2].Max = threeMax;
channel[2].FadeDuration = threeFadeDuration;
channel[3].Led = 3;
channel[3].StartMins = fourStartMins;
channel[3].PhotoPeriod = fourPhotoPeriod;
channel[3].Max = fourMax;
channel[3].FadeDuration = fourFadeDuration;
// Title & Credits added
Wire.begin();
pinMode(bkl, OUTPUT);
lcd.begin(16, 2);
digitalWrite(bkl, HIGH);
lcd.setCursor(0,0); //Modified by NetSurge
lcd.print("Typhon Reef LED");
lcd.setCursor(0,1);
lcd.print("Controller");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("by N. Enders &");
lcd.setCursor(0,1);
lcd.print("R. Ensminger ");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Brought to you ");
lcd.setCursor(0,1);
lcd.print("by BoostLED ");
delay(2000);
lcd.clear();
analogWrite(bkl,bklIdle);
}
/***** Loop *****/
/****************/
void loop() {
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDate(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
oldMinCounter = minCounter;
minCounter = hour * 60 + minute;
int i;
for (i=0; i<4; i++) {
//check & set fade durations
if(channel[i].FadeDuration > channel[i].PhotoPeriod/2 && channel[i].PhotoPeriod >0) {
channel[i].FadeDuration = channel[i].PhotoPeriod/2;
}
if(channel[i].FadeDuration<1){
channel[i].FadeDuration=1;
}
}
//check & set any time functions
//set outputs
if(!override){
oneVal = setLed(minCounter, channel[0].Led, channel[0].StartMins, channel[0].PhotoPeriod, channel[0].FadeDuration, channel[0].Max);
twoVal = setLed(minCounter, channel[1].Led, channel[1].StartMins, channel[1].PhotoPeriod, channel[1].FadeDuration, channel[1].Max);
threeVal = setLed(minCounter, channel[2].Led, channel[2].StartMins, channel[2].PhotoPeriod, channel[2].FadeDuration, channel[2].Max);
fourVal = setLed(minCounter, channel[3].Led, channel[3].StartMins, channel[3].PhotoPeriod, channel[3].FadeDuration, channel[3].Max);
}
else{
oneVal = overpercent;
twoVal = overpercent;
threeVal = overpercent;
fourVal = overpercent;
ovrSetAll(overpercent);
}
// Update EEProms with any values that may have changed
if (channel[0].StartMins != oneStartMins) {
oneStartMins = channel[0].StartMins;
}
if (channel[0].PhotoPeriod != onePhotoPeriod) {
onePhotoPeriod = channel[0].PhotoPeriod;
}
if (channel[0].Max != oneMax) {
oneMax = channel[0].Max;
}
if (channel[0].FadeDuration != oneFadeDuration) {
oneFadeDuration = channel[0].FadeDuration;
}
if (channel[1].StartMins != twoStartMins) {
twoStartMins = channel[1].StartMins;
}
if (channel[1].PhotoPeriod != twoPhotoPeriod) {
twoPhotoPeriod = channel[1].PhotoPeriod;
}
if (channel[1].Max != twoMax) {
twoMax = channel[1].Max;
}
if (channel[1].FadeDuration != twoFadeDuration) {
twoFadeDuration = channel[1].FadeDuration;
}
if (channel[2].StartMins != threeStartMins) {
threeStartMins = channel[2].StartMins;
}
if (channel[2].PhotoPeriod != threePhotoPeriod) {
threePhotoPeriod = channel[2].PhotoPeriod;
}
if (channel[2].Max != threeMax) {
threeMax = channel[2].Max;
}
if (channel[2].FadeDuration != threeFadeDuration) {
threeFadeDuration = channel[2].FadeDuration;
}
if (channel[3].StartMins != fourStartMins) {
fourStartMins = channel[3].StartMins;
}
if (channel[3].PhotoPeriod != fourPhotoPeriod) {
fourPhotoPeriod = channel[3].PhotoPeriod;
}
if (channel[3].Max != fourMax) {
fourMax = channel[3].Max;
}
if (channel[3].FadeDuration != fourFadeDuration) {
fourFadeDuration = channel[3].FadeDuration;
}
// if (intervalCounter > 0) {
// unsigned long milsec = millis();
// if ((currMil < (milsec - 1000)) || (currMil > milsec)) {
// currMil = milsec;
// intervalCounter--;
// }
// }
//turn the backlight off and reset the menu if the idle time has elapsed
if(bklTime + bklDelay < millis() && bklTime > 0 ){
analogWrite(bkl,bklIdle);
menuCount = 1;
lcd.clear();
bklTime = 0;
}
//iterate through the menus
if(menu.uniquePress()){
analogWrite(bkl,bklOn);
bklTime = millis();
if(menuCount < 21){ //Modified by NetSurge
menuCount++;
}
else {
menuCount = 1;
}
lcd.clear();
}
switch (menuCount) {
case 1:
doMainMenu(minCounter, oldMinCounter, hour, minute, second,
oneVal, twoVal, threeVal, fourVal);
break;
case 2:
doOverride(second);
break;
case 3:
doStartTime(0);
break;
case 4:
doEndTime(0);
break;
case 5:
doFadeDuration(0);
break;
case 6:
doMaxIntensity(0);
break;
case 7:
doStartTime(1);
break;
case 8:
doEndTime(1);
break;
case 9:
doFadeDuration(1);
break;
case 10:
doMaxIntensity(1);
break;
case 11:
doStartTime(2);
break;
case 12:
doEndTime(2);
break;
case 13:
doFadeDuration(2);
break;
case 14:
doMaxIntensity(2);
break;
case 15:
doStartTime(3);
break;
case 16:
doEndTime(3);
break;
case 17:
doFadeDuration(3);
break;
case 18:
doMaxIntensity(3);
break;
case 19:
setHour(&hour, minute, second, dayOfWeek, dayOfMonth, month, year);
break;
case 20:
setMinute(hour, &minute, second, dayOfWeek, dayOfMonth, month, year);
break;
case 21:
doinvertPWM();
break;
}
}
void doMainMenu(int minCounter,
int oldMinCounter,
byte hour,
byte minute,
byte second,
int oneVal,
int twoVal,
int threeVal,
int fourVal) {
//main screen turn on!!!
if (minCounter > oldMinCounter){
lcd.clear();
}
lcd.setCursor(0,0);
//Take out display time and uncomment in the led funtion for PWM value debugging
//NetSurge
lcd.print("Time: "); // Displays Time.
printHMS(hour, minute, second);
lcd.setCursor(0,1);
lcd.print(oneVal);
lcd.setCursor(4,1);
lcd.print(twoVal);
lcd.setCursor(8,1);
lcd.print(threeVal);
lcd.setCursor(12,1);
lcd.print(fourVal);
if(inverted){
lcd.setCursor(15,0);
lcd.print("V");
}
//debugging function to use the select button to advance the timer by 1 minute
//if(select.uniquePress()){setDate(second, minute+1, hour, dayOfWeek, dayOfMonth, month, year);}
}
void doOverride(byte second) {
//Manual Override Menu
lcd.setCursor(0,0);
lcd.print("SETTING MODE: "); // Changed by BoostLED
lcd.setCursor(0,1);
//if(menuSelect ==4){
//menuSelect = 0; //modified by NetSurge
//}
if(select.uniquePress()){
if(menuSelect < 4){
menuSelect++;
}
else{
menuSelect = 0;
}
bklTime = millis();
}
if(menuSelect == 0){
lcd.print("Timer "); // Changed by BoostLED
override = false;
}
if(menuSelect == 1){
lcd.print("All Channels ON "); // Changed by BoostLED
overpercent = 100;
override = true;
}
if(menuSelect == 2){
lcd.print("All Channels OFF"); // Changed by BoostLED
overpercent = 0;
override = true;
}
if(menuSelect == 3){
override = true;
lcd.print("Custom "); // Added by BoostLED
lcd.print(overpercent,DEC);
lcd.print("% ");
if (overpercent < 100) {
if (checkButtonAction(&plus)) {
overpercent++;
bklTime = millis();
}
}
if (overpercent > 0) {
if (checkButtonAction(&minus)) {
overpercent--;
bklTime = millis();
}
}
}
//invert PWM
//Modified by NetSurge
/* Moved to Main Menu and not in Overide Menu
if(menuSelect == 4){
if(inverted == true)
lcd.print("PWM Inverted:YES ");
if(inverted == false)
lcd.print("PWM Inverted:NO ");
if (checkButtonAction(&minus) || checkButtonAction(&plus)) {
inverted = !inverted;
}
override = false;
}
*/
}
void doStartTime(int val) {
//set start time
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" Start");
lcd.setCursor(0,1);
printMins(channel[val].StartMins, true);
if (channel[val].StartMins < 1440) {
if (checkButtonAction(&plus)) {
channel[val].StartMins++;
if (channel[val].PhotoPeriod > 0) {
channel[val].PhotoPeriod--;
}
else {
channel[val].PhotoPeriod = 1439;
}
bklTime = millis();
}
}
if (channel[val].StartMins > 0) {
if (checkButtonAction(&minus)) {
channel[val].StartMins--;
if (channel[val].PhotoPeriod < 1439) {
channel[val].PhotoPeriod++;
}
else {
channel[val].PhotoPeriod=0;
}
bklTime = millis();
}
}
}
void doEndTime(int val) {
//set end time
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" End");
lcd.setCursor(0,1);
printMins(channel[val].StartMins+channel[val].PhotoPeriod, true);
if (checkButtonAction(&plus)) {
if(channel[val].PhotoPeriod < 1439){
channel[val].PhotoPeriod++;
}
else {
channel[val].PhotoPeriod=0;
}
bklTime = millis();
}
if (checkButtonAction(&minus)) {
if(channel[val].PhotoPeriod > 0){
channel[val].PhotoPeriod--;
}
else {
channel[val].PhotoPeriod = 1439;
}
bklTime = millis();
}
}
void doFadeDuration(int val) {
//set fade duration
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" Fade");
lcd.setCursor(0,1);
lcd.print("Duration ");
printMins(channel[val].FadeDuration, false);
if (channel[val].FadeDuration < channel[val].PhotoPeriod/2 || channel[val].FadeDuration == 0) {
if (checkButtonAction(&plus)) {
channel[val].FadeDuration++;
bklTime = millis();
}
}
if (channel[val].FadeDuration > 1) {
if (checkButtonAction(&minus)) {
channel[val].FadeDuration--;
bklTime = millis();
}
}
}
void doMaxIntensity(int val) {
//set intensity
lcd.setCursor(0,0);
lcd.print("Channel ");
lcd.print(val+1);
lcd.print(" Max");
lcd.setCursor(0,1);
lcd.print("Level: "); // Added by BoostLED
lcd.print(channel[val].Max);
lcd.print("% "); // Added by BoostLED
if (channel[val].Max < 100) {
if (checkButtonAction(&plus)) {
lcd.clear();
channel[val].Max++;
bklTime = millis();
}
}
if (channel[val].Max > 0) {
if (checkButtonAction(&minus)) {
lcd.clear();
channel[val].Max--;
bklTime = millis();
}
}
}
//Select Inverted PWM or not
//Added By NetSurge
void doinvertPWM() {
lcd.setCursor(0,0);
lcd.print("PWM Inverted... ");
lcd.setCursor(0,1);
if(inverted == true)
lcd.print("YES ");
if(inverted == false)
lcd.print("NO ");
if (checkButtonAction(&minus) || checkButtonAction(&plus)) {
inverted = !inverted;
}
}
void setHour(byte *hour, byte minute, byte second,
byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
//set hours
lcd.setCursor(0,0);
lcd.print("Set Time: Hrs");
lcd.setCursor(0,1);
printHMS(*hour, minute, second);
if (checkButtonAction(&plus)) {
if (*hour < 23) {
(*hour)++;
}
else {
*hour = 0;
}
bklTime = millis();
}
if (checkButtonAction(&minus)) {
if (*hour > 0) {
(*hour)--;
}
else {
*hour = 23;
}
bklTime = millis();
}
setDate(second, minute, *hour, dayOfWeek, dayOfMonth, month, year);
}
void setMinute(byte hour, byte *minute, byte second,
byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
//set minutes
lcd.setCursor(0,0);
lcd.print("Set Time: Mins");
lcd.setCursor(0,1);
printHMS(hour, *minute, second);
if (checkButtonAction(&plus)) {
if (*minute < 59) {
(*minute)++;
}
else {
*minute = 0;
}
bklTime = millis();
}
if (checkButtonAction(&minus)) {
if (*minute > 0) {
(*minute)--;
}
else {
*minute = 59;
}
bklTime = millis();
}
setDate(second, *minute, hour, dayOfWeek, dayOfMonth, month, year);
}