#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
//#include <RTCtime.h>
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
byte _day, _month, _hour24, _hour12, _minute, _second, _dtw;
int _year;
byte hr24;
char st[2];
char _nameoftheDay[9];
char _monthsName[3];
unsigned long currentMillisGetTimeDate;
boolean Run_State = true;
const char daysOfTheWeek_0[] PROGMEM = "Sunday";
const char daysOfTheWeek_1[] PROGMEM = "Monday";
const char daysOfTheWeek_2[] PROGMEM = "Tuesday";
const char daysOfTheWeek_3[] PROGMEM = "Wednesday";
const char daysOfTheWeek_4[] PROGMEM = "Thursday";
const char daysOfTheWeek_5[] PROGMEM = "Friday";
const char daysOfTheWeek_6[] PROGMEM = "Saturday";
int counter1, counter2, counter3;
const char* const daysOfTheWeek_table[] PROGMEM = {daysOfTheWeek_0, daysOfTheWeek_1, daysOfTheWeek_2, daysOfTheWeek_3, daysOfTheWeek_4, daysOfTheWeek_5, daysOfTheWeek_6};
bool State = true;
unsigned long Time;
const char months_name_0[] PROGMEM = "Jan";
const char months_name_1[] PROGMEM = "Feb";
const char months_name_2[] PROGMEM = "Mar";
const char months_name_3[] PROGMEM = "Apr";
const char months_name_4[] PROGMEM = "May";
const char months_name_5[] PROGMEM = "Jun";
const char months_name_6[] PROGMEM = "Jul";
const char months_name_7[] PROGMEM = "Aug";
const char months_name_8[] PROGMEM = "Sep";
const char months_name_9[] PROGMEM = "Oct";
const char months_name_10[] PROGMEM = "Nov";
const char months_name_11[] PROGMEM = "Dec";
const char* const months_name_table[] PROGMEM = {months_name_0, months_name_1, months_name_2, months_name_3,
months_name_4, months_name_5, months_name_6, months_name_7,
months_name_8, months_name_9, months_name_10, months_name_11,
};
byte clockCenterX = 31;
byte clockCenterY = 31;
const unsigned char Clock_Frame [] PROGMEM = {
0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x18, 0x70, 0x1e, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x28, 0x88, 0x07, 0x80, 0x00,
0x00, 0x07, 0x00, 0x08, 0x08, 0x01, 0xc0, 0x00, 0x00, 0x1c, 0x00, 0x08, 0x10, 0x00, 0x70, 0x00,
0x00, 0x38, 0x20, 0x08, 0x20, 0x10, 0x38, 0x00, 0x00, 0x70, 0x20, 0x08, 0x40, 0x10, 0x1c, 0x00,
0x00, 0xe0, 0x10, 0x3e, 0xf8, 0x20, 0x0e, 0x00, 0x01, 0xc0, 0x10, 0x00, 0x00, 0x20, 0x07, 0x00,
0x01, 0x80, 0x08, 0x00, 0x00, 0x40, 0x03, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x40, 0x01, 0x80,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x38, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38,
0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0xc7, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xc6, 0xc8, 0x80, 0x00, 0x07, 0xc0, 0x00, 0x02, 0x26,
0xc8, 0x80, 0x00, 0x0c, 0x60, 0x00, 0x00, 0x26, 0xc7, 0x80, 0x00, 0x0c, 0x60, 0x00, 0x00, 0xc6,
0xc0, 0x80, 0x00, 0x0c, 0x60, 0x00, 0x00, 0x26, 0xc1, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x02, 0x26,
0xce, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xc6, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x38, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x08, 0x00, 0x00, 0x20, 0x01, 0x80,
0x01, 0x80, 0x08, 0x00, 0x00, 0x20, 0x03, 0x00, 0x01, 0xc0, 0x10, 0x00, 0x00, 0x10, 0x07, 0x00,
0x00, 0xe0, 0x10, 0x03, 0x80, 0x10, 0x0e, 0x00, 0x00, 0x70, 0x20, 0x06, 0x00, 0x08, 0x1c, 0x00,
0x00, 0x38, 0x20, 0x04, 0x00, 0x08, 0x38, 0x00, 0x00, 0x1c, 0x00, 0x07, 0x80, 0x00, 0x70, 0x00,
0x00, 0x07, 0x00, 0x04, 0x40, 0x01, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x04, 0x40, 0x07, 0x80, 0x00,
0x00, 0x00, 0xf0, 0x03, 0x80, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00
};
unsigned long previousMillisGetTimeDate = 0;
const long intervalGetTimeDate = 1000;
uint8_t mode = 0;
boolean start = false;
uint16_t count_f=0;
int PIN_BTN = 2;
int state_btn=0;
uint16_t btn_count=0;
uint32_t loop1=0;
String cmdStr="";
int index=0;
int pinstate=1;
void setup() {
Serial.begin(115200);
pinMode(2, INPUT_PULLUP);
if (! rtc.begin()) {
Serial.println(F("Couldn't find RTC"));
Serial.flush();
abort();
}
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.display();
previousMillisGetTimeDate = millis();
Serial.println(F("Enter: set dd/mm/yyyy hh:mm:ss"));
mode=0;
}
unsigned long Time_counter;
uint32_t pevMillis=0;
int lastState = HIGH;
int TIME_DELAY = 50; //ms
int btnState=0;
int btnState2=0;
void loop() {
uint16_t timeleek;
uint16_t now = millis();
int value = digitalRead(2);
if(lastState != value) {
lastState = value;
}
if(now >loop1)
{
loop1+=2;
if(lastState == LOW){
Serial.println(btn_count);
if(mode==0)timeleek = TIME_DELAY*3;
else timeleek = TIME_DELAY;
if((++btn_count > timeleek) && (btnState2==0)) {
btnState2 = 1;
if(mode==0) {
mode =1;
pevMillis =now;
Run_State = false;
}
else {
mode=0;
}
}
} else{btn_count=0;btnState=0;btnState2=0;}
}
if(mode==0){
currentMillisGetTimeDate = millis();
if (currentMillisGetTimeDate - previousMillisGetTimeDate >= intervalGetTimeDate) {
previousMillisGetTimeDate = currentMillisGetTimeDate;
GetDateTime();
display.clearDisplay();
Draw_Clock_Frame();
Analog_Clock(_hour12, _minute, _second);
Digital_Clock_and_Date(_hour24, _minute, _second, _dtw, _day, _month, _year);
display.display();
}
Time_counter=0;
}
else if (mode==1){
if ((btn_count >=2 )&&(btnState==0)) {
btnState=1;
if(Run_State==true){
Run_State=false;
pevMillis =now;
}
else{
Run_State=true;
}
}
if (Run_State == false) { //start
Time_counter += (now - pevMillis);
pevMillis = now;
counter1 = int((Time_counter % 1000) / 10);
counter2 = int((Time_counter / 1000) % 60);
counter3 = int(((Time_counter / 1000) / 60) % 60);
}
String text = "";
if (counter3 < 10)text = text + "0" + counter3 + ":";
else text = text + counter3 + ":";
if (counter2 < 10)text = text + "0" + counter2 + ":";
else text = text + counter2 + ":";
if (counter1 < 10)text = text + "0" + counter1;
else text = text + counter1;
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 45);
display.println(text);
display.setTextSize(2);
display.setCursor(40, 20);
if (Run_State == true) {
display.println("STOP");
}
else {
display.println("RUN");
}
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(35, 0);
display.println("Stop-Watch");
display.display();
}
while(Serial.available()){
char c = Serial.read();
if (c=='\n'){
if (cmdStr.length()< 22){Serial.println("Wrong type, please type again");}
if(mode==0){
//Serial.println(cmdStr);
uint16_t dd = cmdStr.substring(4,6).toInt();
// Serial.print("dd=");Serial.println(dd);
uint16_t mm = cmdStr.substring(7,9).toInt();
//Serial.print("mm=");Serial.println(mm);
uint16_t yy = cmdStr.substring(10,14).toInt();
// Serial.print("yy=");Serial.println(yy);
uint16_t hh = cmdStr.substring(15,17).toInt();
//Serial.print("hh=");Serial.println(hh);
uint16_t mmt = cmdStr.substring(18,20).toInt();
// Serial.print("mm=");Serial.println(mmt);
uint16_t ss = cmdStr.substring(21,23).toInt();
//Serial.print("ss=");Serial.println(ss);
// check data input
rtc.adjust(DateTime(yy, mm, dd, hh, mmt, ss));
Serial.println(F("Time set."));
}else{ Serial.println(F("Back to clock mode before set"));}
cmdStr="";
}else{
cmdStr += c;
}
}
}
int bcd2dec(byte num)
{
return ((num / 16 * 10) + (num % 16));
}
int dec2bcd(byte num)
{
return ((num / 10 * 16) + (num % 10));
}
void GetDateTime() {
String Time = "";
int Time_Read[7] = {};
memset(Time_Read, 0, sizeof(Time_Read));
Wire.beginTransmission(0x68);
Wire.write((byte)0x00);
Wire.endTransmission();
Wire.requestFrom(0x68, 7);
Time_Read[5] = bcd2dec(Wire.read() & 0x7f);
Time_Read[4] = bcd2dec(Wire.read() );
Time_Read[3] = bcd2dec(Wire.read() & 0x3f); // chế độ 24h.
Time_Read[6] = bcd2dec(Wire.read() );
Time_Read[0] = bcd2dec(Wire.read() );
Time_Read[1] = bcd2dec(Wire.read() );
Time_Read[2] = 2000 + bcd2dec(Wire.read() );
_day = Time_Read[0];
_month = Time_Read[1];
_year = Time_Read[2];
_hour24 = Time_Read[3];
_minute = Time_Read[4];
_second = Time_Read[5];
_dtw = Time_Read[6];
hr24 = _hour24;
if (hr24 > 12) {
_hour12 = hr24 - 12;
}
else if (hr24 == 0) {
_hour12 = 12;
}
else {
_hour12 = hr24;
}
}
void Analog_Clock(byte h, byte m, byte s) {
Draw_Line_Seconds(s);
Draw_Line_Minutes(m);
Draw_Line_Hours(h, m);
for (byte i = 30; i < 33; i++) {
display.drawPixel(i, 30, SSD1306_BLACK);
display.drawPixel(i, 31, SSD1306_BLACK);
display.drawPixel(i, 32, SSD1306_BLACK);
}
}
void Draw_Line_Seconds(int s) {
float angle = s * 6 ;
angle = (angle / 57.29577951);
int xS = (clockCenterX + (sin(angle) * (16)));
int yS = (clockCenterY - (cos(angle) * (16)));
if (s == 15) {
display.drawLine(clockCenterX, clockCenterY, xS, yS + 1, WHITE);
} else {
display.drawLine(clockCenterX, clockCenterY, xS, yS, WHITE);
}
}
void Draw_Line_Minutes(int m) {
float angle = m * 6 ;
angle = (angle / 57.29577951) ;
int xM = (clockCenterX + (sin(angle) * (17)));
int yM = (clockCenterY - (cos(angle) * (17)));
if (m == 15) {
display.drawLine(clockCenterX, clockCenterY - 1, xM, yM + 1, WHITE);
display.drawLine(clockCenterX - 1, clockCenterY, xM, yM + 1, WHITE);
display.drawLine(clockCenterX, clockCenterY, xM, yM + 1, WHITE);
display.drawLine(clockCenterX + 1, clockCenterY, xM, yM + 1, WHITE);
display.drawLine(clockCenterX, clockCenterY + 1, xM, yM + 1, WHITE);
} else {
display.drawLine(clockCenterX, clockCenterY - 1, xM, yM, WHITE);
display.drawLine(clockCenterX - 1, clockCenterY, xM, yM, WHITE);
display.drawLine(clockCenterX, clockCenterY, xM, yM, WHITE);
display.drawLine(clockCenterX + 1, clockCenterY, xM, yM, WHITE);
display.drawLine(clockCenterX, clockCenterY + 1, xM, yM, WHITE);
}
}
void Draw_Line_Hours(int h, int m) {
float angle = h * 30 + int((m / 12) * 6);
angle = (angle / 57.29577951) ;
int xH = (clockCenterX + (sin(angle) * (12)));
int yH = (clockCenterY - (cos(angle) * (12)));
if (h == 12 && m < 12) {
display.drawLine(clockCenterX, clockCenterY - 2, xH + 1, yH, WHITE);
display.drawLine(clockCenterX - 2, clockCenterY, xH + 1, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY - 1, xH + 1, yH, WHITE);
display.drawLine(clockCenterX - 1, clockCenterY, xH + 1, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY, xH + 1, yH, WHITE);
display.drawLine(clockCenterX + 1, clockCenterY, xH + 1, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY + 1, xH + 1, yH, WHITE);
display.drawLine(clockCenterX + 2, clockCenterY, xH + 1, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY + 2, xH + 1, yH, WHITE);
} else {
display.drawLine(clockCenterX, clockCenterY - 2, xH, yH, WHITE);
display.drawLine(clockCenterX - 2, clockCenterY, xH, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY - 1, xH, yH, WHITE);
display.drawLine(clockCenterX - 1, clockCenterY, xH, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY, xH, yH, WHITE);
display.drawLine(clockCenterX + 1, clockCenterY, xH, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY + 1, xH, yH, WHITE);
display.drawLine(clockCenterX + 2, clockCenterY, xH, yH, WHITE);
display.drawLine(clockCenterX, clockCenterY + 2, xH, yH, WHITE);
}
}
void Draw_Clock_Frame() {
display.drawBitmap(0, 0, Clock_Frame, 63, 63, WHITE);
}
void Digital_Clock_and_Date(byte h, byte m, byte s, byte dtw, byte dy, byte mt, int yr) {
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(73, 0);
if (h < 10) {
display.print("0");
display.print(h);
} else {
display.print(h);
}
display.print(":");
if (m < 10) {
display.print("0");
display.print(m);
} else {
display.print(m);
}
display.print(":");
if (s < 10) {
display.print("0");
display.print(s);
} else {
display.print(s);
}
strcpy_P(_nameoftheDay, (char*)pgm_read_word(&(daysOfTheWeek_table[dtw])));
byte display_center_area = (127 - 65) / 2;
byte center_text = (strlen(_nameoftheDay) * 6) / 2;
byte x_text = 66 + (display_center_area - center_text);
display.setCursor(x_text, 23);
display.println(_nameoftheDay);
strcpy_P(_monthsName, (char*)pgm_read_word(&(months_name_table[mt - 1])));
display.setCursor(76, 45);
if (dy < 10) {
display.print("0");
display.print(dy);
} else {
display.print(dy);
}
display.print(", ");
display.print(_monthsName);
display.setCursor(85, 55);
display.print(yr);
}