// Ugi's Dawn-Light Alarm Clock Sketch. // Test sketch for RTC module with 4-digit display but set from serial (no inputs) // MIT Licence // Ugi Dec 2012 // Written for Arduino 022 running on ATmega328. // We need the following libraries: // Wire // Arduino Pin connections: // A4 - 1307 (I2C data) // A5 - 1307 (I2C clock) // D0 - Serial Tx // D1 - Serial Rx // D6 - Buzzer // D7 - 7219 Clock // D8 - 7219 Data // D9 - 7219 Latch // General clock settings: #include - // usees analogue pins A4 (SDA - pin 27) & A5 (SCL- pin 28) for 2-wire data. const byte DS1307_Address = 0x68; byte seconds = 45, oldseconds=0, minutes=52, hours=23, date=8, month=12, day=4, year=11, protect = 0; // defaults just to start somewhere. byte NEWseconds = 45, NEWminutes=52, NEWhours=23, NEWdate=8, NEWmonth=12, NEWday=4, NEWyear=11 ; // These are for setting. Probably don't need to be global any more. // 4 - digit display control settings: // Our 4-digit display is setup as in MAX 7219 datasheet but only the DP for digit 3 is wired to anything - use other (external) LEDs as indicators const int fourDigitClock = 7; // 4-digit clock pin to control 7219 const int fourDigitData = 8; // 4-digit data pin to control 7219 const int fourDigitLatch = 9; // 4-digit latch pin to control 7219 boolean fourDigitBlink = false; // Redundant? **** int LEDintensity = 3; // Intensity of display set by 7219 - range 0 to 15 boolean LEDcontrol = false; // This may now be redundant... **** unsigned long blinkTime = 0; // Used to control blinking of the HH:MM colon separator. // Display Charater Definitions: //Segments numbered clockwise from top MSB first with middle bar last. This takes 7 bits - MSB will be for decimal / indicator. // These are the characters that I consider unambiguously legible on a 7-seg display. Others might be contrived. Of these, W and M are the most missed. const byte character[36] = { B1111110, //0 B0110000, //1 B1101101, //2 B1111001, //3 B0110011, //4 B1011011, //5 B1011111, //6 B1110000, //7 B1111111, //8 B1111011, //9 B1000000, // Top Dash - 10 B0000001, // Middle Dash - 11 B0001000, // Bottom Dash - 12 B0000000, // Blank - 13 B1110111, // A - 14 // B - 8 B0011111, // b - 15 B1001110, // C - 16 B0001101, // c - 17 B0111101, // d - 18 B1001111, // E - 19 B1000111, // F - 20 B1111011, // g - 21 B0110111, // H - 22 B0010111, // h - 23 B0010000, // i - 24 B0001110, // L - 25 // l - 1 B0010101, // n - 26 // O - 0 B0011101, // o - 27 B1100111, // P - 28 B1100111, // q - 29 B0000101, // r - 30 // S - 5 B0001111, // t - 31 B0111110, // U - 32 B0011100, // u - 33 B0111011, // y - 34 B1101101, // Z - 35 }; const int buzzer=6; void setup(){ Serial.begin(9600); Serial.println(" DS1307 RTC based clock - Ugi Jan 2012"); delay(2000); // Give RTC some time to settle. Wire.begin(); // Need for RTC fourDigitSetup(); pinMode(buzzer, OUTPUT); RTCsetFromSerial(); } void loop() { RTCread(); RTCprintTime(); // sends time to serial. fourDigitShowTime(); // Displayt time on 4-digit display fourDigitWriteData(LEDintensity,10); // Set intensity. Probably don't need in main loop any more. } // End main loop // Various funcions below. Generally RTC then 4-digit display then lamp then alarm then eeprom then buzzer. // Read time from RTC into time variables. void RTCread(){ byte data[11]={0,0,0,0,0,0,0,0,0,0,0}; Wire.beginTransmission(DS1307_Address); Wire.send(0); // set register to beginning Wire.endTransmission(); Wire.requestFrom(DS1307_Address, (byte)10); // request 7 bytes from RTC into buffer. for (byte _loop=0; _loop<10; _loop++){ data[_loop]=(Wire.receive()); } seconds = (((data[0] & B01110000)>>4)*10)+(data[0] & B00001111); minutes = (((data[1] & B01110000)>>4)*10)+(data[1] & B00001111); hours = (((data[2] & B00110000)>>4)*10)+(data[2] & B00001111); day = (data[3] & B00000111); date = (((data[4] & B00110000)>>4)*10)+(data[4] & B00001111); month = (((data[5] & B00010000)>>4)*10)+(data[5] & B00001111); year = (((data[6] & B11110000)>>4)*10)+(data[6] & B00001111); } // Write current time to RTC void RTCwrite(){ // writes all current data to RTC - if you only want to write one parameter then just read the clock first! byte data[7]; data[0] = (seconds % 10) + ((seconds/10)<<4); data[1] = (minutes % 10) + ((minutes/10)<<4); data[2] = (hours % 10) + ((hours/10)<<4); data[3] = day; data[4] = (date % 10) + ((date/10)<<4); data[5] = (month % 10)+ ((month/10)<<4); data[6] = (year % 10) + ((year/10)<<4); Wire.beginTransmission(DS1307_Address); Wire.send(0); // set register to beginning for (byte _loop=0; _loop<7; _loop++){ Wire.send(data[_loop]); } Wire.endTransmission(); oldseconds=seconds; } // End RTC Write function // Print current time to Serial... void RTCprintTime(){ RTCread(); Serial.print("Time = "); Serial.print(hours, DEC); Serial.print(":");Serial.print(minutes, DEC);Serial.print(":"); Serial.println(seconds, DEC); Serial.print("Date = "); Serial.print(date, DEC); Serial.print("/");Serial.print(month, DEC);Serial.print("/20"); Serial.print(year, DEC); } byte RTCgetSerial(byte _val, String _Str){ Serial.println(" "); Serial.println(" *** "+_Str+" ***"); Serial.print("Current value = "); Serial.print(_val, DEC); Serial.println(" "+_Str); Serial.println("Enter new value (two digits e.g. '01'): "); Serial.flush(); byte NEW_val = -1; while (Serial.available() < 2){ delay(50); } NEW_val = ((Serial.read()-48)*10); NEW_val = NEW_val + (Serial.read()-48); Serial.flush(); Serial.print("New value = "); Serial.print(NEW_val, DEC); Serial.println(" "+_Str);Serial.println(" "); if (NEW_val >=0){return NEW_val;} else {return _val;} } boolean RTCconfirm(){ Serial.println(" "); Serial.println("Currently:"); RTCprintTime(); Serial.flush(); Serial.println(" "); Serial.println("Change to? (Y/N):"); Serial.print("time = "); Serial.print(NEWhours, DEC); Serial.print(":");Serial.print(NEWminutes, DEC);Serial.print(":"); Serial.println(NEWseconds, DEC); Serial.print("date = "); Serial.print(NEWdate, DEC); Serial.print("/");Serial.print(NEWmonth, DEC);Serial.print("/20");Serial.print(NEWyear, DEC); char _conf = -1; while (Serial.available()<1){ delay(50); } _conf = Serial.read(); Serial.flush(); Serial.print("confirm digit = "); Serial.println(_conf); if(_conf=='Y'){return true;} else{return false; } } boolean RTCsetFromSerial(){ // Get new time setting from serial port Serial.flush(); // avoid any random data in buffer. // See if we want to update char _input = 'X'; while (_input != 'R' && _input !='Q'){ while (Serial.available()<1){ RTCprintTime(); // We'll keep displaying current tiem and see whether it needs updating. Serial.println("Enter 'R' by serial input to re-set or Q to quit setting routine"); Serial.println(" "); delay(1000); } _input = Serial.read(); Serial.flush(); } // if(_input != 'R'){Serial.println(" "); Serial.println(" *** QUITTING ***"); Serial.println(" "); return false;} Serial.println(" "); Serial.println(" *** RESETTING RTC ***"); Serial.println(" "); RTCprintTime(); NEWyear = RTCgetSerial(year, "years"); RTCprintTime(); NEWday = RTCgetSerial(day, "days of the week"); RTCprintTime(); NEWmonth = RTCgetSerial(month, "months"); RTCprintTime(); NEWdate = RTCgetSerial(date, "days of the month"); RTCprintTime(); NEWhours = RTCgetSerial(hours, "Hours"); RTCprintTime(); NEWminutes = RTCgetSerial(minutes, "Minutes"); RTCprintTime(); NEWseconds = RTCgetSerial(seconds, "Seconds"); if (RTCconfirm()){ seconds = NEWseconds; minutes = NEWminutes; hours = NEWhours; date = NEWdate; month = NEWmonth; day = NEWday; year = NEWyear; RTCwrite(); Serial.println (" "); Serial.println (" *** RTC Updated ***"); return true; } else { Serial.println (" *** Update cancelled ***"); } return false; } // End of Set from Serial Routine void fourDigitSetup(){ pinMode(fourDigitLatch, OUTPUT); pinMode(fourDigitClock, OUTPUT); pinMode(fourDigitData, OUTPUT); fourDigitWriteData(1, 12); // turn off shutdown fourDigitWriteData(0, 15); // test mode off fourDigitWriteData(0,9); // Turn off decode mode fourDigitWriteData(3,11); // Set scan limit to our 4 digits. We can set it higher to reduce brighness if we wish. fourDigitWriteData(LEDintensity,10); // Set initial intensity byte _str[9]={22,19,25,25,0,13,13,13,13}; // say hello! fourDigitScroll(_str,9,250); } // End four-digit display setup // Write a digit to 4-digit display.. void fourDigitWrite(byte _char, byte _digit, boolean _dp){ byte _header = B00000000 | _digit; // redundant but we might need a header or other manipulation later. digitalWrite(fourDigitLatch, LOW); shiftOut(fourDigitData, fourDigitClock, MSBFIRST, _header);// Serial.print("Writing Header -");Serial.print(_header, HEX); byte _data = (character[_char]|(B10000000*_dp)); // Retrieve font definition and add decimal (colon separator or indicator LED) if appropriate. shiftOut(fourDigitData, fourDigitClock, MSBFIRST, _data );// Serial.print (" Writing Data -"); Serial.println (_data, BIN); digitalWrite(fourDigitLatch, HIGH); } // end character write // Need also to write control digits to appropriate registers. // Reg 10 - intensity // Reg 11 - scan limit // Reg 12 - shutdown control (1 to turn off shutdown) // Reg 15 - Test mode control (0 for test mode off) void fourDigitWriteData(byte _data, byte _register){ digitalWrite(fourDigitLatch, LOW); shiftOut(fourDigitData, fourDigitClock, MSBFIRST, _register); // Serial.print("register "); Serial.print(_register, HEX); shiftOut(fourDigitData, fourDigitClock, MSBFIRST, _data); // Serial.print(" data "); Serial.println(_data, BIN); digitalWrite(fourDigitLatch, HIGH); } // end data write // Display Time on four digit display: void fourDigitShowTime(){ byte _blink= true; if (seconds!=oldseconds){ // blink digit divider once a second. blinkTime = millis(); oldseconds=seconds; } _blink=true; if ((millis()-blinkTime)<250){_blink=false;} // blink for 250 ms every second. fourDigitWrite((hours/10),1, false); fourDigitWrite((hours%10),2, _blink); // colon separator on this digit fourDigitWrite((minutes/10),3, false); fourDigitWrite((minutes%10),4, false); // armed indicator on this digit } void fourDigitDisplayBlink(){ // flashes whole display off for 50 ms fourDigitWriteData(0,12); delay(50); fourDigitWriteData(1,12); } void fourDigitScroll(byte*_str, byte _len, byte _del){ // takes array of char definitions ending in four 13s (spaces) byte _data[4]={13,13,13,13}; for (byte _loop=0; _loop<_len; _loop++){ _data[3]=_data[2]; _data[2]=_data[1]; _data[1]=_data[0]; _data[0]=_str[_loop]; fourDigitWrite(_data[3],1, false); fourDigitWrite(_data[2],2, false); fourDigitWrite(_data[1],3, false); fourDigitWrite(_data[0],4, false); delay(_del); } }