/* RTC Clock with arduino nano v3 tested with arduino nano v3 cloce & tiny rtc with ds1307 chip based on: RTC: DS1307 https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit?view=all SCL is the i2c clock pin - its required to talk to the RTC SDA is the i2c data pin - its required to talk to the RTC nano: I2C: A4 (SDA) and A5 (SCL). Support I2C (TWI) communication using the Wire library (documentation on the Wiring website http://playground.arduino.cc/Main/LedControl LedControl.h Now we need a LedControl to work with. ***** These pin numbers will probably not work with your hardware ***** pin 12 is connected to the DataIn pin 11 is connected to the CLK pin 10 is connected to LOAD We have only a single MAX72XX. used encoder example with 2 interrupts, full resolution http://playground.arduino.cc/Main/RotaryEncoders#Example3 on nano v3: int0 = D2 int1 = D3 attention: this is an alpha version, I'm still testing and working on this sketch version 008 = menu updates & intensity, seconds, minutes, hours & days adjustable todo: menu works, but could be better encoder sometimes drops values ... .. . */ // Tiny RTC: date & time functions using a DS1307 RTC connected via I2C and Wire lib #include #include "RTClib.h" RTC_DS1307 rtc; // 4x7 segment: LED control lib #include "LedControl.h" // arduino pins to setup led control LedControl lc = LedControl(12, 11, 10, 1); /* we always wait a bit between updates of the display */ unsigned long delaytime = 250; // encoder pin definition #define encoder0PinA 2 #define encoder0PinB 3 #define encoder0Push 4 // position of encoder volatile int encoder0Pos = 0; volatile int tmpTime = 0; // acticate encoder setting boolean encoder0act; // menu position pointer byte menuState = 0; void setup() { // set & test clock Serial.begin(9600); // start wire bus & rtc #ifdef AVR Wire.begin(); #else Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due #endif rtc.begin(); // automatically set timer, the first time that it runs if (! rtc.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(__DATE__, __TIME__)); } /* // manual set time // first run: uncommemnt & compile & upload rtc.adjust(DateTime(__DATE__, "20:52:00")); // set timer using unix time in seconds rtc.adjust(DateTime(1435875098)); rtc.adjust(DateTime(__DATE__, __TIME__)); */ // rtc.adjust(DateTime(__DATE__, __TIME__)); /* The MAX72XX is in power-saving mode on startup, we have to do a wakeup call */ lc.shutdown(0, false); // set the brightness : only values between 0(darkest) and 15(brightest) are valid lc.setIntensity(0, 15); /* and clear the display */ lc.clearDisplay(0); /* // lc.setChar(device, digit, a..f dp, true or flase); // lc.setChar(a, b, c)0=Device), 3210 digits, 0...7 (7=a, 6=b, 5=c, 4=d, 3=e, 2=f, 1=g, 0=dp), true/false (true = LED on; fals e= LED off) delay(1000); lc.setLed(0, 3, 0, true); delay(250); lc.setLed(0, 2, 0, true); delay(250); lc.setLed(0, 1, 0, true); delay(250); lc.setLed(0, 0, 0, true); delay(1000); lc.clearDisplay(0); */ // init encoder & menu state encoder0act = false; menuState = 0; // encoder pins setup pinMode(encoder0PinA, INPUT); pinMode(encoder0PinB, INPUT); pinMode(encoder0Push, INPUT); // encoder pin on interrupt 0 (pin 2) attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 1 (pin 3) attachInterrupt(1, doEncoderB, CHANGE); } void loop() { // read time from RTC DateTime now = rtc.now(); // set display to new time, if menu is deactivated if (encoder0act == false) { if (digitalRead(encoder0Push) == LOW) { // menu: active encoder0act = true; digitalWrite(13, HIGH); } else { // display time hhmm writeTime4x7seg(now.hour() * 100 + now.minute()); delay(delaytime); menuState = 0; // end menu digitalWrite(13, LOW); encoder0Pos = 0; } } else { if (digitalRead(encoder0Push) == LOW) { // change switch (menuState) { case 0: menuState = encoder0Pos; writeMenu(menuState, 'P', 'S'); encoder0Pos = 0; break; case 1: // adjust 4x7 segment intensity 0..15 0=lowest 15=highest values writeMenu(encoder0Pos, 'c', '1'); encoder0act = false; break; case 2: // adjust seconds rtc.adjust(DateTime(now.unixtime() + encoder0Pos)); writeMenu(now.minute() + encoder0Pos, 'c', '2'); encoder0act = false; break; case 3: // adjust minute rtc.adjust(DateTime(now.unixtime() + encoder0Pos * 60)); encoder0act = false; writeMenu(now.minute() + encoder0Pos, 'c', '3'); break; case 4: // adjust hour rtc.adjust(DateTime(now.unixtime() + encoder0Pos * 3600)); encoder0act = false; writeMenu(now.hour() + encoder0Pos, 'c', '4'); break; case 5: // adjust day rtc.adjust(DateTime(now.unixtime() + encoder0Pos * 86400L)); encoder0act = false; writeMenu(now.day() + encoder0Pos, 'c', '5'); break; default: encoder0act = false; writeMenu(00, 'c', ' '); break; } delay(1000); } else { switch (menuState) { case 0: encoder0Pos = constrain(encoder0Pos, 0, 10); writeMenu(encoder0Pos, 'P', ' '); break; case 1: // adjust 4x7 segment intensity encoder0Pos = constrain(encoder0Pos, 0, 15); writeMenu(encoder0Pos, 'P', '1'); lc.setIntensity(0, encoder0Pos); break; case 2: // adjust seconds encoder0Pos = constrain(encoder0Pos, -59, 59); tmpTime = now.second() + encoder0Pos; if (tmpTime > 59) { tmpTime = tmpTime - 60; } writeMenu(tmpTime, 'P', '2'); break; case 3: // adjust minutes encoder0Pos = constrain(encoder0Pos, -59, 59); tmpTime = now.minute() + encoder0Pos; if (tmpTime > 59) { tmpTime = tmpTime - 60; } writeMenu(now.minute() + encoder0Pos, 'P', '3'); break; case 4: // adjust hours encoder0Pos = constrain(encoder0Pos, -11, 11); tmpTime = now.hour() + encoder0Pos; if (tmpTime > 23) { tmpTime = tmpTime - 24; } writeMenu(now.hour() + encoder0Pos , 'P', '4'); break; case 5: // adjust day // adjust hours encoder0Pos = constrain(encoder0Pos, -30, 30); tmpTime = now.day() + encoder0Pos; if (tmpTime > 31) { tmpTime = tmpTime - 31; } writeMenu(tmpTime, 'P', '5'); break; default: // display encoder value writeMenu(encoder0Pos, 'P', '0'); break; } delay(delaytime); } } delay(delaytime); // print date & time Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); Serial.print(" since midnight 1/1/1970 = "); Serial.print(now.unixtime()); Serial.print("s = "); Serial.print(now.unixtime() / 86400L); Serial.println("d"); delay(delaytime); } void writeMenu(int menuValue, char menuChar, char menuNow) { int i = 0; int digit = 0; while (i != 2) { digit = menuValue % 10; //Serial.println(menuValue); menuValue = menuValue / 10; //Serial.println(menuValue); lc.setChar(0, i, digit, false); i++; } lc.setChar(0, 3, menuChar, false); lc.setChar(0, 2, menuNow, true); } void writeTime4x7seg(int nowDezTime) { int i = 0; int digit = 0; while (i != 4) { digit = nowDezTime % 10; //Serial.println(nowDezTime); nowDezTime = nowDezTime / 10; //Serial.println(nowDezTime); lc.setChar(0, i, digit, false); i++; } lc.setLed(0, 2, 0, true); } void doEncoderA() { if (encoder0act == true) { // look for a low-to-high on channel A if (digitalRead(encoder0PinA) == HIGH) { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } else // must be a high-to-low edge on channel A { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == HIGH) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } } Serial.println (encoder0Pos, DEC); // use for debugging - remember to comment out } void doEncoderB() { if (encoder0act == true) { // look for a low-to-high on channel B if (digitalRead(encoder0PinB) == HIGH) { // check channel A to see which way encoder is turning if (digitalRead(encoder0PinA) == HIGH) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } // Look for a high-to-low on channel B else { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinA) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } } //Serial.println (encoder0Pos, DEC); // use for debugging - remember to comment out }