#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <math.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
#define DS1307_ADDRESS 0x68
// Arrays for creating segments and customizing numbers
byte segment[8][8] =
{
{ B01111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 },
{ B11111, B11111, B11111, B00000, B00000, B00000, B00000, B00000 },
{ B11110, B11111, B11111, B11111, B11111, B11111, B11111, B11111 },
{ B11111, B11111, B11111, B11111, B11111, B11111, B11111, B01111 },
{ B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111 },
{ B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11110 },
{ B11111, B11111, B11111, B00000, B00000, B00000, B11111, B11111 },
{ B11111, B00000, B00000, B00000, B00000, B11111, B11111, B11111 }
};
byte zero = 0x00;
int col = 0;
int number, lastMin1, lastMin2, lastHour1, lastHour2;
void setup()
{
Wire.begin();
// Initializes the LCD
lcd.init();
lcd.backlight();
// Associates each created segment with a number
for (byte i = 0; i < 8; i++) {
lcd.createChar(i, segment[i]);
}
// The line below can be removed after setting the date and time
// setDateTime();
}
void loop()
{
// Extracts the time from the DS1307 and shows it on the LCD
showClock();
delay(1000);
}
byte convertToBCD(byte val) { // Converts the decimal number to BCD
return ( (val / 10 * 16) + (val % 10) );
}
byte convertToDecimal(byte val) { // Converts from BCD to decimal
return ( (val / 16 * 10) + (val % 16) );
}
void digit0() // Set the segments to the number 0
{
lcd.setCursor(col, 0); // Select the top line
lcd.write((byte)0); // Segment 0 selected
lcd.write(1); // Segment 1 selected
lcd.write(2);
lcd.setCursor(col, 1); // Select the bottom line
lcd.write(3);
lcd.write(4);
lcd.write(5);
}
void digit1() // Set the segments to the number 1
{
lcd.setCursor(col, 0);
lcd.write(1);
lcd.write(2);
lcd.setCursor(col + 1, 1);
lcd.write(5);
}
void digit2() // Set the segments to the number 2
{
lcd.setCursor(col, 0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(col, 1);
lcd.write(3);
lcd.write(7);
lcd.write(7);
}
void digit3() // Set the segments to the number 3
{
lcd.setCursor(col, 0);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(col, 1);
lcd.write(7);
lcd.write(7);
lcd.write(5);
}
void digit4() // Set the segments to the number 4
{
lcd.setCursor(col, 0);
lcd.write(3);
lcd.write(4);
lcd.write(2);
lcd.setCursor(col + 2, 1);
lcd.write(5);
}
void digit5() // Set the segments to the number 5
{
lcd.setCursor(col, 0);
lcd.write((byte)0);
lcd.write(6);
lcd.write(6);
lcd.setCursor(col, 1);
lcd.write(7);
lcd.write(7);
lcd.write(5);
}
void digit6() // Set the segments to the number 6
{
lcd.setCursor(col, 0);
lcd.write((byte)0);
lcd.write(6);
lcd.write(6);
lcd.setCursor(col, 1);
lcd.write(3);
lcd.write(7);
lcd.write(5);
}
void digit7() // Set the segments to the number 7
{
lcd.setCursor(col, 0);
lcd.write(1);
lcd.write(1);
lcd.write(2);
lcd.setCursor(col + 1, 1);
lcd.write((byte)0);
}
void digit8() // Set the segments to the number 8
{
lcd.setCursor(col, 0);
lcd.write((byte)0);
lcd.write((byte)6);
lcd.write(2);
lcd.setCursor(col, 1);
lcd.write(3);
lcd.write(7);
lcd.write(5);
}
void digit9() // Set the segments to the number 9
{
lcd.setCursor(col, 0);
lcd.write((byte)0);
lcd.write((byte)6);
lcd.write((byte)2);
lcd.setCursor(col + 2, 1);
lcd.write((byte)5);
}
void showDigit() // Shows the number in the position defined by "X"
{
switch (number) {
case 0: digit0();
break;
case 1: digit1();
break;
case 2: digit2();
break;
case 3: digit3();
break;
case 4: digit4();
break;
case 5: digit5();
break;
case 6: digit6();
break;
case 7: digit7();
break;
case 8: digit8();
break;
case 9: digit9();
break;
}
}
void showClock()
{
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
int seconds = convertToDecimal(Wire.read());
int minutes = convertToDecimal(Wire.read());
int hours = convertToDecimal(Wire.read() & 0b111111);
int dayWeek = convertToDecimal(Wire.read());
int dayMonth = convertToDecimal(Wire.read());
int month = convertToDecimal(Wire.read());
int year = convertToDecimal(Wire.read());
if (seconds & 1) {
lcd.setCursor(7, 0);
lcd.print(".");
lcd.setCursor(7, 1);
lcd.print(".");
} else {
lcd.setCursor(7, 0);
lcd.print(" ");
lcd.setCursor(7, 1);
lcd.print(" ");
}
col = 0;
number = hours / 10;
// Conditional to avoid overlapping characters
if (lastHour1 != minutes % 10) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lastHour1 = minutes % 10;
}
showDigit(); // Show the customized number on the display
col = 4;
number = hours % 10;
if (lastHour2 != minutes % 10) {
lcd.setCursor(4, 0);
lcd.print(" ");
lcd.setCursor(4, 1);
lcd.print(" ");
lastHour2 = minutes % 10;
}
showDigit();
col = 9;
number = minutes / 10;
if (lastMin1 != minutes % 10) {
lcd.setCursor(9, 0);
lcd.print(" ");
lcd.setCursor(9, 1);
lcd.print(" ");
lastMin1 = minutes % 10;
}
showDigit();
col = 13;
number = minutes % 10;
if (lastMin2 != minutes % 10) {
lcd.setCursor(13, 0);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.print(" ");
lastMin2 = minutes % 10;
}
showDigit();
}
void setDateTime() // Set the date and time of the DS1307
{
byte seconds = 00; // Values from 0 to 59
byte minutes = 00; // Values from 0 to 59
byte hours = 00; // Values from 0 to 23
byte dayWeek = 1; // Values from 0 to 6, where 0 = Domgino, 1 = Monday
byte dayMonth = 17; // Values from 1 to 31
byte month = 5; // Values from 1 to 12
byte year = 21; // Values from 0 to 99
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(zero); // Stop at CI so that it can receive data
// The lines below write the values of date and
// time they were placed in the variables above
Wire.write(convertToBCD(seconds));
Wire.write(convertToBCD(minutes));
Wire.write(convertToBCD(hours));
Wire.write(convertToBCD(dayWeek));
Wire.write(convertToBCD(dayMonth));
Wire.write(convertToBCD(month));
Wire.write(convertToBCD(year));
Wire.write(zero); // Start at CI
Wire.endTransmission();
}