// DS1307 RTC read / write registers display time & date, temp set alarm // T.Reynolds Jan 2017 #include #include #include boolean colon = true ; const int CLK = 9; //Set the CLK pin connection to the display const int DIO = 8; //Set the DIO pin connection to the display uint8_t segto; int value; int sx; int alarm2=0; // alarm2 triggerred flag TM1637Display display(CLK, DIO); //set up the 4-Digit Display. // attach RTC SQW O/P to pin 2 Arduino (interrupt 0) // attach RTC SDA to Arduino A4 // attach RTC SCL to Arduino A5 // attach GND & 5v const byte s7sAddress = 0x71; //rtc boolean toggle1 = 0; #define DS3231_I2C_ADDRESS 0x68 // rtc address cannot be changed // rtc data used BCD so these routines very useful // 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) ); } int n=0; //Temp read device temp //https://arduinodiy.wordpress.com/2015/11/10/the-ds3231-rtc-temperature-sensor/ uint8_t UBYTE ; // = readRegister(REG_TEMPM); //Two's complement form uint8_t LRBYTE; // = readRegister(REG_TEMPL); //Fractional part void setup() { pinMode(7,INPUT_PULLUP); // show date pinMode(6,INPUT_PULLUP); // show temp display.setBrightness(0x0a); //set the diplay to maximum brightnessput your setup code here, to run once: Wire.begin(); Serial.begin(9600); set_td(14,6); delay(100); // set_td(0,1); // seconds // set_td(1,6); // set mins // set_td(2,15); // set hours // set_td(3,1); // set day 1 = Sun, 2 = Mon // set_td(4,28);// set date 1-31 // set_td(5,1); // set month // set_td(6,17); // set year //set alarm 2 every minute // http://pdf1.alldatasheet.com/datasheet-pdf/view/112132/DALLAS/DS3231.html // set_td(11,128); // set_td(12,128); // set_td(13,129); attachInterrupt(0,disp,CHANGE); // update disp every second attachInterrupt(1,disp2,CHANGE); // alarm interrupt // 4 digit:display info //http://cdn.instructables.com/ORIG/FDU/3O5V/IN96AJH6/FDU3O5VIN96AJH6.pdf clearDisplayI2C(); // Clears display, resets cursor //////// set interrupt timer 1 /// cli();//stop interrupts pinMode(13, OUTPUT); //timer interrupt info http://www.instructables.com/id/Arduino-Timer-Interrupts/step2/Structuring-Timer-Interrupts/ //set timer1 interrupt at 1Hz TCCR1A = 0;// set entire TCCR1A register to 0 TCCR1B = 0;// same for TCCR1B TCNT1 = 0;//initialize counter value to 0 // set compare match register for 1hz increments OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS12 and CS10 bits for 1024 prescaler TCCR1B |= (1 << CS12) | (1 << CS10); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); sei();//allow interrupts //////// //DS3231_init(DS3231_INTCN); // DS3231_clear_a2f(); // clr alarm 2 flag disp2(); //Clear alarm 2 flag rtc reg 0Fh set_td(15,1); // should really read rtc OFh and & with 01 but I know the value } ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED) //generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low) if (toggle1){ digitalWrite(13,HIGH); toggle1 = 0; } else{ digitalWrite(13,LOW); toggle1 = 1; } } void loop() { n=0; delay(50); if(n>0) // n is incremented in ISR disp -> attachInterrupt(0,disp,RISING); { regis(); // show register information displayTime(); // display date & time // DS3231_clear_a2f(); // clr alarm 2 flag if(alarm2==1) { set_td(15,1); Serial.println("*********** Alarm INTERRUPT ***************"); alarm2=0; } } } void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes of data from DS3231 starting from register 00h *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()); } void displayTime() { byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // retrieve data from DS3231 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // send it to the serial monitor Serial.print(" "); Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC); Serial.print(" - "); switch(dayOfWeek){ case(1): Serial.print("Sunday"); break; case(2): Serial.print("Monday"); break; case(3): Serial.print("Tuesday"); break; case(4): Serial.print("Wednesday"); break; case(5): Serial.print("Thuursday"); break; case(6): Serial.print("Friday"); break; case(7): Serial.print("Saturday"); break; } // Serial.print(dayOfWeek, DEC); Serial.print(" , "); Serial.print(dayOfMonth, DEC); Serial.print(":"); Serial.print(month, DEC); Serial.print(":"); Serial.print(year, DEC); Serial.println(); Serial.println(); Serial.println(getTemperature()); } void set_td(int x,int t) // set time and date individually { // Serial.println(t); Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(x); Wire.write(decToBcd(t)); // set hours Wire.endTransmission(); } void disp() { n++; } void regis() { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 18); for(int j=0;j<19;j++) { int inf=bcdToDec(Wire.read() ); if(j==0) { sx=inf%2; } Serial.print(j, HEX); Serial.print(" "); Serial.println(inf,BIN); // hold digital pin 7 to 0v to show date instead of time if(j==4 && digitalRead(7)==0) { display.showNumberDec(inf,true,2,0); } if(j==5 && digitalRead(7)==0) { display.showNumberDec(inf,true,2,2); } if( digitalRead(6)==1 && digitalRead(7)==1) // { if(j==1 && digitalRead(7)==1 ) { display.showNumberDec(inf,true,2,2); } if(j==2&& digitalRead(7)==1) { display.showNumberDec(inf,true,2,0); // uint8_t segto; value = inf; if(sx==1) // flash the colon : (sets bit 7 of 2 digit to 1) { segto = 0x80 | display.encodeDigit((value %10)); display.setSegments(&segto,1,1); } } } if( j==17) { UBYTE=inf; } if( j==18) { LRBYTE=inf; } // for 19 degrees, serial.print shows -237 !! however, // 7 segment shows OK ?? int inf3; if(digitalRead(6)==0 && j==17) // temp high reg display.showNumberDec(inf,true,2,0); if(digitalRead(6)==0 && j==18) // temp low reg { inf3=inf >> 6 ; // only need bits 6 & 7 inf3=inf3 * 25; display.showNumberDec(inf3,true,2,2); } } } // Send the clear display command (0x76) // This will clear the display and reset the cursor void clearDisplayI2C() { Wire.beginTransmission(s7sAddress); Wire.write(0x76); // Clear display command Wire.endTransmission(); } // This custom function works somewhat like a serial.print. // You can send it an array of chars (string) and it'll print // the first 4 characters in the array. void s7sSendStringI2C(String toSend) { Wire.beginTransmission(s7sAddress); for (int i=0; i<4; i++) { Wire.write(toSend[i]); } Wire.endTransmission(); } void disp2() // alarm interrupt { alarm2=1; /* Cannot have too much happening in here due to timer interrupt & alarm interrupt So we just set a flag and let the loop() do the work */ } float getTemperature() { // info from https://arduinodiy.wordpress.com/2015/11/10/the-ds3231-rtc-temperature-sensor/ int temperatureCelsius; float fTemperatureCelsius; // UBYTE = readRegister(REG_TEMPM); //Two's complement form // LRBYTE = readRegister(REG_TEMPL); //Fractional part if (UBYTE & 0b10000000 !=0) //check if -ve number { UBYTE ^= 0b11111111; UBYTE += 0x1; fTemperatureCelsius = UBYTE + ((LRBYTE >> 6) * 0.25); fTemperatureCelsius = fTemperatureCelsius * -1; } else { fTemperatureCelsius = UBYTE + ((LRBYTE >> 6) * 0.25); } return (fTemperatureCelsius); }