#include #include #include #include "DS1307.h" //#define DEBUG // Supplies debug code for testing the time chip via Arduino Serial // // Analog Pins // #define I2C_SDA 4 // Define the I2C Pins (documentation only) #define I2C_SDC 5 // Used only by WIRE for I2C int rtc_bcd[7]; // secs, min, hr, dow, date, mth, yr int clock_bcd[6]; // h h m m s s (each digit in BCD) #define resetTimer 600 // ID Timer: Count 10 minutes = 10 * 60 seconds = 600 clock-ticks // // Digital Pins // // Define the LCD #define rw 4 // Could tie RW to 0.0 volts (write to LCD only), but it's RW here. #define enable 11 #define d0 7 #define d1 8 #define d2 9 #define d3 10 #define rs 12 #define idOn 6 // Switched ON or OFF for 10-minute timer // idOn will also be tied to the Blanking for the Timer Digit. // if 'LOW' then Identify Timer is OFF and Digit will be blanked; // if 'HIGH', then Identify Timer is ON and Digit will be displayed. #define pinIDalarm 5 // Identify Signal OUT... LiquidCrystal lcd( rs, rw, enable, d0, d1, d2, d3 ); void setup() { Wire.begin(); // Always be available for Clock Set instructions... Serial.begin(9600); // Startup the LCD... lcd.clear(); // Put any fancy startup digit animation here... lcd.setCursor( 0, 0 ); lcd.print( "SB-630: " ); delay( 750 ); // Delay ... for effect! lcd.setCursor( 0, 1 ); lcd.print( "Station Console " ); delay( 3500 ); // 3 1/2 seconds here is long enough to wait... lcd.clear(); pinMode( idOn, INPUT); digitalWrite( idOn, HIGH ); // Turn on the internal Pull-Up pinMode( pinIDalarm, OUTPUT); digitalWrite( pinIDalarm, LOW ); // Setup our Serial Port Serial.begin(9600); } // Setup some things for the loop... boolean isTimer = false; int idSeconds = resetTimer; #define alarmSecs 1 int alarmTime = alarmSecs; void loop() { byte second, minute, hour, dayOfWeek, day, month, year; // Check for any time Sync via NTP Protocol from a PC if( getPCtime()) { lcd.clear(); lcd.print( "Clock Synced via" ); lcd.setCursor( 0, 1 ); lcd.print( " NTP Protocol "); delay( 2000 ); lcd.clear(); } // This fetches the current time DS1307_read( &second, &minute, &hour, &dayOfWeek, &day, &month, &year ); #ifdef DEBUG // printDate is only for TESTING w/o an LCD... printDate( second, minute, hour, dayOfWeek, day, month, year ); #endif displayDate( second, minute, hour, dayOfWeek, day, month, year ); if ( alarmTime > 0 ) { alarmTime = alarmTime - 1; } else { // Turn OFF the alarm... digitalWrite( pinIDalarm, LOW ); } if ( digitalRead( idOn ) == LOW) { if (isTimer) { boolean isTimeout = countTimer( &idSeconds ); if ( isTimeout ) { idSeconds = resetTimer; alarmTime = alarmSecs; digitalWrite( pinIDalarm, HIGH ); isTimeout = false; } } else { isTimer = true; idSeconds = resetTimer; } displayTimer( idSeconds ); } else { if (isTimer) { isTimer = false; } lcd.setCursor( 11, 0 ); lcd.print( " UTC " ); lcd.setCursor( 11, 1 ); lcd.print( " " ); } delay(1000); } // // Acquire data from the RTC chip in BCD format // void DS1307_read( byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *day, byte *month, byte *year ) { // Use the Wire lib to connect to the RTC // Reset the register pointer to zero Wire.beginTransmission( DS1307_CTRL_ID ); Wire.send( 0x00 ); Wire.endTransmission(); // Now Fetch the 7 bytes of data (secs, min, hr, dow, date. mth, yr) Wire.requestFrom( DS1307_CTRL_ID, 7 ); for ( int i = 0; i < 7; i++ ) { rtc_bcd[i] = Wire.receive(); // store data in raw bcd format } *second = bcdToDec(rtc_bcd[0] & 0x7f); *minute = bcdToDec(rtc_bcd[1]); *hour = bcdToDec(rtc_bcd[2] & 0x3f); // Need to change this if 12 hour am/pm *dayOfWeek = bcdToDec(rtc_bcd[3]); *day = bcdToDec(rtc_bcd[4]); *month = bcdToDec(rtc_bcd[5]); *year = bcdToDec(rtc_bcd[6]); } void DS1307_write( void ) { Wire.beginTransmission( DS1307_CTRL_ID ); Wire.send(0); // rtc_bcd[7]; // secs, min, hr, dow, date, mth, yr Wire.send(decToBcd(rtc_bcd[0])); // 0 to bit 7 starts the clock Wire.send(decToBcd(rtc_bcd[1])); Wire.send(decToBcd(rtc_bcd[2])); // 24-hour if bit 6 = 0 Wire.send(decToBcd(rtc_bcd[3])); Wire.send(decToBcd(rtc_bcd[4])); Wire.send(decToBcd(rtc_bcd[5])); Wire.send(decToBcd(rtc_bcd[6])); Wire.endTransmission(); } // // Output the Clock_BCD to the 7-Segment Display Latches // void Display_write( void ) { // Write all 6 Clock Digits... for ( int i = 0; i < 6; i++ ) { BCD_write( i ); } } void BCD_write( int clockIndex ) { int aBit; int bcdVal = clock_bcd[clockIndex]; //digitalWrite( latchPins[ clockIndex ], LOW ); // NOT LE --> Low Enables BCD Bus for this digit // Slam out a BCD Digit on the Bus for ( int i = 0; i < 4; i++ ) { aBit = bcdVal & 1; // isolate lowest bit of the BCD digit //digitalWrite( bcdPins[ i ], aBit); // send to correct pin bcdVal = bcdVal >> 1; // shift the bits RIGHT so the next bit is in position } //digitalWrite( latchPins[clockIndex], HIGH ); // NOT LE --> High Disables BCD Bus for this digit } #ifdef DEBUG // // Convert normal decimal numbers to binary coded decimal // void printDate( byte second, byte minute, byte hour, byte dayOfWeek, byte day, byte month, byte year ) { char* dow[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; //// secs, min, hr, dow, date, mth, yr Serial.print( hour, DEC ); Serial.print(":" ); if ( minute < 10 ) { Serial.print( "0" ); } Serial.print( minute, DEC ); Serial.print( ":" ); if ( second < 10 ) { Serial.print( "0" ); } Serial.print( second, DEC ); Serial.print( " " ); Serial.print( month, DEC ); Serial.print( "/" ); if ( day < 10 ) { Serial.print( "0" ); } Serial.print( day, DEC ); Serial.print( "/" ); Serial.print( "20" ); if ( year < 10 ) { Serial.print( "0" ); } Serial.print( year, DEC ); Serial.print(", Day_of_week:" ); int dowIndex = dayOfWeek - 1; Serial.println( dow[dowIndex] ); } #endif void displayDate( byte second, byte minute, byte hour, byte dayOfWeek, byte day, byte month, byte year ) { lcd.setCursor(0, 0); char* dow1[] = { "S", "M", "T", "W", "T", "F", "S" }; char* dow2[] = { "U", "O", "U", "E", "H", "R", "A" }; //// secs, min, hr, dow, date, mth, yr if ( hour == 0 ) { lcd.print( "0" ); } else if ( hour < 10 ) { lcd.print( " " ); } lcd.print( hour, DEC ); lcd.print(":" ); if ( minute < 10 ) { lcd.print( "0" ); } lcd.print( minute, DEC ); lcd.print( ":" ); if ( second < 10 ) { lcd.print( "0" ); } lcd.print( second, DEC ); int dowIndex = dayOfWeek - 1; lcd.print( " " ); lcd.print( dow1[dowIndex] ); lcd.setCursor(0, 1); if ( month < 10 ) lcd.print( " " ); lcd.print( month, DEC ); lcd.print( "/" ); if ( day < 10 ) { lcd.print( "0" ); } lcd.print( day, DEC ); lcd.print( "/" ); if ( year < 10 ) { lcd.print( "0" ); } lcd.print( year, DEC ); lcd.print( " " ); lcd.print( dow2[dowIndex] ); } boolean countTimer( int *seconds ) { *seconds = *seconds - 1; if ( *seconds == 0 ) { return true; } else { return false; } } void displayTimer( int idseconds ) { char buf[12]; // "-2147483648\0" lcd.setCursor( 11, 0 ); lcd.print( "IDENT" ); int minutes, seconds; minutes = idseconds / 60; seconds = idseconds % 60; lcd.setCursor( 11, 1 ); if ( minutes < 10 ) lcd.print( " " ); lcd.print( minutes, DEC ); lcd.print( ":" ); if ( seconds < 10 ) lcd.print( "0" ); lcd.print( seconds, DEC ); } void clearTimer( void ) { // Clear the area where the ID Timer was Displayed... lcd.setCursor( 10, 0 ); lcd.print( " " ); lcd.setCursor( 10, 1 ); lcd.print( " " ); } // 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) ); } #define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by unix time_t as ten ascii digits #define TIME_HEADER 'x' // Header tag for serial time sync message boolean getPCtime() { // if time available from serial port, sync the DateTime library //... Uses a Unix-Style Timestamp. while ( Serial.available() >= TIME_MSG_LEN ){ // time message consists of a header and ten ascii digits if ( Serial.read() == TIME_HEADER ) { time_t pctime = 0; for ( int i = 0; i < TIME_MSG_LEN -1; i++ ) { char c= Serial.read(); if( c >= '0' && c <= '9'){ pctime = (10 * pctime) + (c - '0'); // convert digits to a number } } pctime += 1; // tack on a second for time in transit.... //Serial.println( pctime, DEC ); DateTime.sync( pctime ); // Sync DateTime clock to the time received on the serial port DateTime.available(); // Now, can use the DateTime to Sync the DS1307 chip... setDateDs1307( DateTime.Second, DateTime.Minute, DateTime.Hour, DateTime.DayofWeek+1, DateTime.Day, DateTime.Month+1, DateTime.Year-100 ); return true; } } return false; } // // 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 / no range check // void setDateDs1307 ( byte second, // 0-59 byte minute, // 0-59 byte hour, // 1-23 byte dayOfWeek, // 1-7 byte day, // 1-28/29/30/31 byte month, // 1-12 byte year ) // 0-99 { Wire.beginTransmission( DS1307_CTRL_ID ); 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(day) ); Wire.send( decToBcd(month) ); Wire.send( decToBcd(year) ); Wire.send( decToBcd(10) ); // Don't forget the SQWE (Square Wave Output) Wire.endTransmission(); }