#include #include #include "Wire.h" #define DS1307_I2C_ADDRESS 0x68 int ldrPin = 2; // pin for the LDR to sense light in the room volatile boolean started = true; // boolean to indicate that we have just awakened from sleep int fullYear; // full year (ie 2009) to be retrieved from EEPROM byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // date and time retrieved from DS1307 RTC module int addr = 0; byte reader = 0; byte update[7]; boolean needsUpdate = false; void setup() { // arduino setup routine Serial.begin(19200); // open serial communications to PC for updates Wire.begin(); // begin communication with DS1307 RTC module delay(1000); pinMode(ldrPin, INPUT); // configure the LDR pin as input pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); /* for (int i = 0; i < 7; i++) { Serial.print("address: "); Serial.print(i); Serial.print(" data: "); Serial.println(EEPROM.read(i), DEC); } Serial.println("DONE DONE DONE DONE DONE"); */ addr = 0; //attachInterrupt(0, wakeNow, LOW); // use interrupt 0 (pin 2) and run function // wakeUpNow when pin 2 goes LOW } void loop() { //Serial.println("IN THE LOOP"); while(Serial.available()) { reader = Serial.read(); if(reader == 255) { // do nothing - dummy byte //Serial.println("DUMMY"); } else { //EEPROM.write(addr, reader); needsUpdate = true; //Serial.println(reader); update[addr] = reader; addr += 1; } } if((needsUpdate) && (addr >= 5)) { if(addr == 6) { setDateDs1307(0, update[0], update[1], update[2], update[3], update[4], update[5]); EEPROM.write(6, update[5]); } else if(addr == 7) { setDateDs1307(update[0], update[1], update[2], update[3], update[4], update[5], update[6]); EEPROM.write(6, update[6]); } else { // do nothing } delay(100); needsUpdate = false; addr = 0; } if(digitalRead(ldrPin)) { // if ldrPin is high, the room is too bright to operate //Serial.println("going to sleep"); updateMoon(0); delay(10); sleepNow(); // so we sleep to arduino to conserve battery } if(started) { // if the device has just awakened from sleep started = false; // it has no longer 'just' awakened, so this // code should only be run once getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // retreive the date from the DS1307 RTC module fullYear = (2000 + EEPROM.read(6)); // get the full four year date stored in EEPROM /* Serial.print("second "); Serial.println(second, DEC); Serial.print("minute "); Serial.println(minute, DEC); Serial.print("hour "); Serial.println(hour, DEC); Serial.print("dayofweek "); Serial.println(dayOfWeek, DEC); Serial.print("dayOfMonth "); Serial.println(dayOfMonth, DEC); Serial.print("month "); Serial.println(month, DEC); Serial.print("fullyear "); Serial.println(fullYear, DEC); */ updateMoon(getPhase(fullYear, int(month), int(dayOfMonth))); } } void wakeNow() { // here the interrupt is handled after wakeup started = true; // variable establishes that we have just awakened } void sleepNow() { // put the arduino to sleep started = false; //set_sleep_mode(SLEEP_MODE_PWR_DOWN); set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); // enables the sleep bit in the mcucr register // so sleep is possible. just a safety pin attachInterrupt(0,wakeNow, LOW); // use interrupt 0 (pin 2) and run function wakeNow sleep_mode(); // put the arduino to sleep! // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP sleep_disable(); // first thing after waking from sleep detachInterrupt(0); // disables interrupt 0 on pin 2 so the // wakeUpNow code will not be executed delay(10); // during normal operation and wait a bit } byte getPhase(int Y, int M, int D) { // calculate the current phase of the moon double AG, IP; // based on the current date byte phase; // algorithm adapted from Stephen R. Schmitt's // Lunar Phase Computation program, originally long YY, MM, K1, K2, K3, JD; // written in the Zeno programming language // http://home.att.net/~srschmitt/lunarphasecalc.html // calculate julian date YY = Y - floor((12 - M) / 10); MM = M + 9; if(MM >= 12) MM = MM - 12; K1 = floor(365.25 * (YY + 4712)); K2 = floor(30.6 * MM + 0.5); K3 = floor(floor((YY / 100) + 49) * 0.75) - 38; JD = K1 + K2 + D + 59; if(JD > 2299160) JD = JD -K3; IP = normalize((JD - 2451550.1) / 29.530588853); AG = IP*29.53; if(AG < 1.20369) phase = B00000000; else if(AG < 3.61108) phase = B00000001; else if(AG < 6.01846) phase = B00000011; else if(AG < 8.42595) phase = B00000111; else if(AG < 10.83323) phase = B00001111; else if(AG < 13.24062) phase = B00011111; else if(AG < 15.64800) phase = B00111111; else if(AG < 18.05539) phase = B00111110; else if(AG < 20.46277) phase = B00111100; else if(AG < 22.87016) phase = B00111000; else if(AG < 25.27754) phase = B00110000; else if(AG < 27.68493) phase = B00100000; else phase = 0; return phase; } double normalize(double v) { // normalize moon calculation between 0-1 v = v - floor(v); if (v < 0) v = v + 1; return v; } byte decToBcd(byte val) { // Convert normal decimal numbers to binary coded decimal return ((val / 10 * 16) + (val % 10)); } byte bcdToDec(byte val) { // Convert binary coded decimal to normal decimal numbers return ((val / 16 * 10) + (val % 16)); } // 1) Sets the date and time on the ds1307 // 2) Starts the clock // 3) Sets hour mode to 24 hour clock // Assumes you're passing in valid numbers void setDateDs1307(byte second, // 0-59 byte minute, // 0-59 byte hour, // 1-23 byte dayOfWeek, // 1-7 byte dayOfMonth, // 1-28/29/30/31 byte month, // 1-12 byte year) // 0-99 { Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.send(0); 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 getDateDs1307(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { // Reset the register pointer Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.send(0); Wire.endTransmission(); delay(10); 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()); } void updateMoon(byte thePhase) { for(byte mask = 00000001, j=7; mask<01000000, j<13; mask<<=1, j++) { if((thePhase & mask)) digitalWrite(j, HIGH); // turn on the LED else digitalWrite(j, LOW); // turn off the LED } }