DIY: Arduino Real Time Clock
Ένα γρήγορο Real Time Clock (RTC) με Arduino και μπόλικο κώδικα! Ένα γρήγορο Real Time Clock (RTC) με Arduino και μπόλικο κώδικα!
Στο σημερινό DIY φτιάχνουμε ένα απλό αλλά πολύ χρήσιμο ρολόι από ένα περισσευούμενο Arduino UNO! Το project μας λειτουργεί χάρη στο DS1307 IC το οποίο θα παίξει τον ρόλο του RTC, δηλαδή θα είναι μπορεί να κρατάει την ώρα και είναι ιδιαίτερα αποτελεσματικό καθώς "χάνει" περίπου ένα λεπτό τον μήνα! Για να εξαλείψουμε αυτό το θέμα υπάρχει και το DS3234 το οποίο χάνει ένα λεπτό τον χρόνο. Για τη κατασκευή θα χρειαστούμε:
Κύρια Components
DS 1307.
8-Pin DIP Socket.
CR 2032 Button Cell.
Button Battery Holder.
4-Pin Connector.
10k Resistor 1/4 Watt.
32.768kHz Oscillator Crystals.
Prototype Board.
Δευτερεύοντα Components
Solder Wire.
Soldering Iron.
Arduino UNO.
16x2 LCD Character Display.
Jumper Wires (Female to Female)
Βήμα 1. Τα κομμάτια του project μας. Στις δύο τελευταίες εικόνες βλέπουμε δύο σχεδιαγράμματα, το ένα μας δείχνει το IC και το άλλο ολόκληρο το project, ενώ η τρίτη από το τέλος, τη συνδεσμολογία μέσα από το πρόγραμμα fritzing.
Βήμα 2. Αρχικά κόβουμε τη prototype board στο μέγεθος που επιθυμούμε και κολλάμε το στοιχείο συγκράτησης της μπαταρίας. Τοποθετούμε το DIP socket για το IC μας και έπειτα τον crystal Oscillator ενώ μη ξεχάσετε να κολλήσετε το casing του με μια γείωση. Σειρά έχει το 4 pin connector και γ σχετική εικόνα (Note 1) μας δείχνει τη συνδεσμολογία που θα ακολουθήσουμε στο Arduino.
Βήμα 3. Συνεχίζουμε τις κολλήσεις όπως φαίνονται στη φωτογραφία.
Βήμα 4. Στη συνέχεια ελέγχουμε το κύκλωμα και ενώνουμε και την οθόνη όπως δείχνει η προ-τελευταία φωτογραφία του DIY. Θυμηθείτε, υπάρχει τρόπος η οθόνη LCD να συνδεθεί με λιγότερα από 6 καλώδια (2 συγκεκριμένα) στο Arduino μέσω ενός Serial Interface Board Module το οποίο πωλείται ξεχωριστά από το ebay αλλά εμείς θα ακολουθήσουμε την πρώτη οδό. Ανοίγουμε τοIDE πρόγραμμα στον υπολογιστή μας και συνδέουμε το Arduino. Ύστερα κατεβάζουμε το RealTimeClockDS1307 στο desktop, και από το IDE διαλέγουμε Sketch => Import Library => Add Library και βάζουμε τον κώδικα που βρίσκεται στο spoiler πατώντας compile. Εάν ολοκληρωθεί τότε το ρολόι μας λειτουργεί κανονικά! Το μόνο που μένει να κάνουμε είναι να προγραμματίσουμε την ώρα. Στη πηγή υπάρχει ένας αναλυτικός οδηγός για τον συγκεκριμένο κώδικα και σας συνιστούμε να του ρίξετε μια γρήγορη ματιά για να δείτε πως λειτουργεί.
[SPOILER]#include
#include
//RealTimeClock RTC;//=new RealTimeClock();
#define Display_Clock_Every_N_Seconds 10 // n.secs to show date/time
#define Display_ShortHelp_Every_N_Seconds 60 // n.secs to show hint for help
//#define TEST_Squarewave
//#define TEST_StopStart
//#define TEST_1224Switch
int count=0;
char formatted[] = "00-00-00 00:00:00x";
void setup() {
// Wire.begin();
Serial.begin(9600);
pinMode(A3, OUTPUT); //*** pin 16 (Analog pin 2) as OUTPUT ***
digitalWrite(A3, HIGH); //*** pin 16 (Analog pin 2) set to LOW ***
pinMode(A2, OUTPUT); //*** pin 17 (Analog pin 3) as OUTPUT ***
digitalWrite(A2, LOW); //*** pin 17 (Analog pin 3) set to HIGH ***
//*** Analog Pin settings to power RTC module ***
}
void loop() {
if(Serial.available())
{
processCommand();
}
RTC.readClock();
count++;
if(count % Display_Clock_Every_N_Seconds == 0){
Serial.print(count);
Serial.print(": ");
RTC.getFormatted(formatted);
Serial.print(formatted);
Serial.println();
}
if(count % Display_ShortHelp_Every_N_Seconds == 0) {
Serial.println("Send ? for a list of commands.");
}
#ifdef TEST_Squarewave
if(count%10 == 0)
{
switch(count/10 % 6)
{
case 0:
Serial.print("Squarewave disabled (low impedance): ");
RTC.sqwDisable(0);
Serial.println((int) RTC.readData(7));
break;
case 1:
Serial.print("Squarewave disabled (high impedance): ");
RTC.sqwDisable(1);
Serial.println((int) RTC.readData(7));
break;
case 2:
Serial.println("Squarewave enabled at 1 Hz");
RTC.sqwEnable(RTC.SQW_1Hz);
break;
case 3:
Serial.println("Squarewave enabled at 4.096 kHz");
RTC.sqwEnable(RTC.SQW_4kHz);
break;
case 4:
Serial.println("Squarewave enabled at 8.192 kHz");
RTC.sqwEnable(RTC.SQW_8kHz);
break;
case 5:
Serial.println("Squarewave enabled at 32.768 kHz");
RTC.sqwEnable(RTC.SQW_32kHz);
break;
default:
Serial.println("Squarewave test not defined");
}//switch
}
#endif
#ifdef TEST_StopStart
if(count%10 == 0)
{
if(!RTC.isStopped())
{
if(RTC.getSeconds() < 45)
{
Serial.println("Stopping clock for 10 seconds");
RTC.stop();
}//if we have enough time
} else {
RTC.setSeconds(RTC.getSeconds()+11);
RTC.start();
Serial.println("Adding 11 seconds and restarting clock");
}
}//if on a multiple of 10 counts
#endif
#ifdef TEST_1224Switch
if(count%10 == 0)
{
if(count %20 == 0)
{
Serial.println("switching to 12-hour time");
RTC.switchTo12h();
RTC.setClock();
}
else
{
Serial.println("switching to 24-hour time");
RTC.switchTo24h();
RTC.setClock();
}
}
#endif
}
void processCommand() {
if(!Serial.available()) { return; }
char command = Serial.read();
int in,in2;
switch(command)
{
case 'H':
case 'h':
in=SerialReadPosInt();
RTC.setHours(in);
RTC.setClock();
Serial.print("Setting hours to ");
Serial.println(in);
break;
case 'I':
case 'i':
in=SerialReadPosInt();
RTC.setMinutes(in);
RTC.setClock();
Serial.print("Setting minutes to ");
Serial.println(in);
break;
case 'S':
case 's':
in=SerialReadPosInt();
RTC.setSeconds(in);
RTC.setClock();
Serial.print("Setting seconds to ");
Serial.println(in);
break;
case 'Y':
case 'y':
in=SerialReadPosInt();
RTC.setYear(in);
RTC.setClock();
Serial.print("Setting year to ");
Serial.println(in);
break;
case 'M':
case 'm':
in=SerialReadPosInt();
RTC.setMonth(in);
RTC.setClock();
Serial.print("Setting month to ");
Serial.println(in);
break;
case 'D':
case 'd':
in=SerialReadPosInt();
RTC.setDate(in);
RTC.setClock();
Serial.print("Setting date to ");
Serial.println(in);
break;
case 'W':
Serial.print("Day of week is ");
Serial.println((int) RTC.getDayOfWeek());
break;
case 'w':
in=SerialReadPosInt();
RTC.setDayOfWeek(in);
RTC.setClock();
Serial.print("Setting day of week to ");
Serial.println(in);
break;
case 't':
case 'T':
if(RTC.is12hour()) {
RTC.switchTo24h();
Serial.println("Switching to 24-hour clock.");
} else {
RTC.switchTo12h();
Serial.println("Switching to 12-hour clock.");
}
RTC.setClock();
break;
case 'A':
case 'a':
if(RTC.is12hour()) {
RTC.setAM();
RTC.setClock();
Serial.println("Set AM.");
} else {
Serial.println("(Set hours only in 24-hour mode.)");
}
break;
case 'P':
case 'p':
if(RTC.is12hour()) {
RTC.setPM();
RTC.setClock();
Serial.println("Set PM.");
} else {
Serial.println("(Set hours only in 24-hour mode.)");
}
break;
case 'q':
RTC.sqwEnable(RTC.SQW_1Hz);
Serial.println("Square wave output set to 1Hz");
break;
case 'Q':
RTC.sqwDisable(0);
Serial.println("Square wave output disabled (low)");
break;
case 'z':
RTC.start();
Serial.println("Clock oscillator started.");
break;
case 'Z':
RTC.stop();
Serial.println("Clock oscillator stopped.");
break;
case '>':
in=SerialReadPosInt();
in2=SerialReadPosInt();
RTC.writeData(in, in2);
Serial.print("Write to register ");
Serial.print(in);
Serial.print(" the value ");
Serial.println(in2);
break;
case '<':
in=SerialReadPosInt();
in2=RTC.readData(in);
Serial.print("Read from register ");
Serial.print(in);
Serial.print(" the value ");
Serial.println(in2);
break;
default:
Serial.println("Unknown command. Try these:");
Serial.println(" h## - set Hours [range 1..12 or 0..24]");
Serial.println(" i## - set mInutes [range 0..59]");
Serial.println(" s## - set Seconds [range 0..59]");
Serial.println(" d## - set Date [range 1..31]");
Serial.println(" m## - set Month [range 1..12]");
Serial.println(" y## - set Year [range 0..99]");
Serial.println(" w## - set arbitrary day of Week [range 1..7]");
Serial.println(" t - toggle 24-hour mode");
Serial.println(" a - set AM p - set PM");
Serial.println();
Serial.println(" z - start clock Z - stop clock");
Serial.println(" q - SQW/OUT = 1Hz Q - stop SQW/OUT");
Serial.println();
Serial.println(" >##,### - write to register ## the value ###");
Serial.println(" <## - read the value in register ##");
}//switch on command
}
//read in numeric characters until something else
//or no more data is available on serial.
int SerialReadPosInt() {
int i = 0;
boolean done=false;
while(Serial.available() && !done)
{
char c = Serial.read();
if (c >= '0' && c <='9')
{
i = i * 10 + (c-'0');
}
else
{
done = true;
}
}
return i;
}[/SPOILER]
[video=youtube;Y_bzUAdFxbk]https://www.youtube.com/watch?&v=Y_bzUAdFxbk[/video]
Στο σημερινό DIY φτιάχνουμε ένα απλό αλλά πολύ χρήσιμο ρολόι από ένα περισσευούμενο Arduino UNO! Το project μας λειτουργεί χάρη στο DS1307 IC το οποίο θα παίξει τον ρόλο του RTC, δηλαδή θα είναι μπορεί να κρατάει την ώρα και είναι ιδιαίτερα αποτελεσματικό καθώς "χάνει" περίπου ένα λεπτό τον μήνα! Για να εξαλείψουμε αυτό το θέμα υπάρχει και το DS3234 το οποίο χάνει ένα λεπτό τον χρόνο. Για τη κατασκευή θα χρειαστούμε:
Κύρια Components
DS 1307.
8-Pin DIP Socket.
CR 2032 Button Cell.
Button Battery Holder.
4-Pin Connector.
10k Resistor 1/4 Watt.
32.768kHz Oscillator Crystals.
Prototype Board.
Δευτερεύοντα Components
Solder Wire.
Soldering Iron.
Arduino UNO.
16x2 LCD Character Display.
Jumper Wires (Female to Female)
Βήμα 1. Τα κομμάτια του project μας. Στις δύο τελευταίες εικόνες βλέπουμε δύο σχεδιαγράμματα, το ένα μας δείχνει το IC και το άλλο ολόκληρο το project, ενώ η τρίτη από το τέλος, τη συνδεσμολογία μέσα από το πρόγραμμα fritzing.
Βήμα 2. Αρχικά κόβουμε τη prototype board στο μέγεθος που επιθυμούμε και κολλάμε το στοιχείο συγκράτησης της μπαταρίας. Τοποθετούμε το DIP socket για το IC μας και έπειτα τον crystal Oscillator ενώ μη ξεχάσετε να κολλήσετε το casing του με μια γείωση. Σειρά έχει το 4 pin connector και γ σχετική εικόνα (Note 1) μας δείχνει τη συνδεσμολογία που θα ακολουθήσουμε στο Arduino.
Βήμα 3. Συνεχίζουμε τις κολλήσεις όπως φαίνονται στη φωτογραφία.
Βήμα 4. Στη συνέχεια ελέγχουμε το κύκλωμα και ενώνουμε και την οθόνη όπως δείχνει η προ-τελευταία φωτογραφία του DIY. Θυμηθείτε, υπάρχει τρόπος η οθόνη LCD να συνδεθεί με λιγότερα από 6 καλώδια (2 συγκεκριμένα) στο Arduino μέσω ενός Serial Interface Board Module το οποίο πωλείται ξεχωριστά από το ebay αλλά εμείς θα ακολουθήσουμε την πρώτη οδό. Ανοίγουμε τοIDE πρόγραμμα στον υπολογιστή μας και συνδέουμε το Arduino. Ύστερα κατεβάζουμε το RealTimeClockDS1307 στο desktop, και από το IDE διαλέγουμε Sketch => Import Library => Add Library και βάζουμε τον κώδικα που βρίσκεται στο spoiler πατώντας compile. Εάν ολοκληρωθεί τότε το ρολόι μας λειτουργεί κανονικά! Το μόνο που μένει να κάνουμε είναι να προγραμματίσουμε την ώρα. Στη πηγή υπάρχει ένας αναλυτικός οδηγός για τον συγκεκριμένο κώδικα και σας συνιστούμε να του ρίξετε μια γρήγορη ματιά για να δείτε πως λειτουργεί.
[SPOILER]#include
#include
//RealTimeClock RTC;//=new RealTimeClock();
#define Display_Clock_Every_N_Seconds 10 // n.secs to show date/time
#define Display_ShortHelp_Every_N_Seconds 60 // n.secs to show hint for help
//#define TEST_Squarewave
//#define TEST_StopStart
//#define TEST_1224Switch
int count=0;
char formatted[] = "00-00-00 00:00:00x";
void setup() {
// Wire.begin();
Serial.begin(9600);
pinMode(A3, OUTPUT); //*** pin 16 (Analog pin 2) as OUTPUT ***
digitalWrite(A3, HIGH); //*** pin 16 (Analog pin 2) set to LOW ***
pinMode(A2, OUTPUT); //*** pin 17 (Analog pin 3) as OUTPUT ***
digitalWrite(A2, LOW); //*** pin 17 (Analog pin 3) set to HIGH ***
//*** Analog Pin settings to power RTC module ***
}
void loop() {
if(Serial.available())
{
processCommand();
}
RTC.readClock();
count++;
if(count % Display_Clock_Every_N_Seconds == 0){
Serial.print(count);
Serial.print(": ");
RTC.getFormatted(formatted);
Serial.print(formatted);
Serial.println();
}
if(count % Display_ShortHelp_Every_N_Seconds == 0) {
Serial.println("Send ? for a list of commands.");
}
#ifdef TEST_Squarewave
if(count%10 == 0)
{
switch(count/10 % 6)
{
case 0:
Serial.print("Squarewave disabled (low impedance): ");
RTC.sqwDisable(0);
Serial.println((int) RTC.readData(7));
break;
case 1:
Serial.print("Squarewave disabled (high impedance): ");
RTC.sqwDisable(1);
Serial.println((int) RTC.readData(7));
break;
case 2:
Serial.println("Squarewave enabled at 1 Hz");
RTC.sqwEnable(RTC.SQW_1Hz);
break;
case 3:
Serial.println("Squarewave enabled at 4.096 kHz");
RTC.sqwEnable(RTC.SQW_4kHz);
break;
case 4:
Serial.println("Squarewave enabled at 8.192 kHz");
RTC.sqwEnable(RTC.SQW_8kHz);
break;
case 5:
Serial.println("Squarewave enabled at 32.768 kHz");
RTC.sqwEnable(RTC.SQW_32kHz);
break;
default:
Serial.println("Squarewave test not defined");
}//switch
}
#endif
#ifdef TEST_StopStart
if(count%10 == 0)
{
if(!RTC.isStopped())
{
if(RTC.getSeconds() < 45)
{
Serial.println("Stopping clock for 10 seconds");
RTC.stop();
}//if we have enough time
} else {
RTC.setSeconds(RTC.getSeconds()+11);
RTC.start();
Serial.println("Adding 11 seconds and restarting clock");
}
}//if on a multiple of 10 counts
#endif
#ifdef TEST_1224Switch
if(count%10 == 0)
{
if(count %20 == 0)
{
Serial.println("switching to 12-hour time");
RTC.switchTo12h();
RTC.setClock();
}
else
{
Serial.println("switching to 24-hour time");
RTC.switchTo24h();
RTC.setClock();
}
}
#endif
}
void processCommand() {
if(!Serial.available()) { return; }
char command = Serial.read();
int in,in2;
switch(command)
{
case 'H':
case 'h':
in=SerialReadPosInt();
RTC.setHours(in);
RTC.setClock();
Serial.print("Setting hours to ");
Serial.println(in);
break;
case 'I':
case 'i':
in=SerialReadPosInt();
RTC.setMinutes(in);
RTC.setClock();
Serial.print("Setting minutes to ");
Serial.println(in);
break;
case 'S':
case 's':
in=SerialReadPosInt();
RTC.setSeconds(in);
RTC.setClock();
Serial.print("Setting seconds to ");
Serial.println(in);
break;
case 'Y':
case 'y':
in=SerialReadPosInt();
RTC.setYear(in);
RTC.setClock();
Serial.print("Setting year to ");
Serial.println(in);
break;
case 'M':
case 'm':
in=SerialReadPosInt();
RTC.setMonth(in);
RTC.setClock();
Serial.print("Setting month to ");
Serial.println(in);
break;
case 'D':
case 'd':
in=SerialReadPosInt();
RTC.setDate(in);
RTC.setClock();
Serial.print("Setting date to ");
Serial.println(in);
break;
case 'W':
Serial.print("Day of week is ");
Serial.println((int) RTC.getDayOfWeek());
break;
case 'w':
in=SerialReadPosInt();
RTC.setDayOfWeek(in);
RTC.setClock();
Serial.print("Setting day of week to ");
Serial.println(in);
break;
case 't':
case 'T':
if(RTC.is12hour()) {
RTC.switchTo24h();
Serial.println("Switching to 24-hour clock.");
} else {
RTC.switchTo12h();
Serial.println("Switching to 12-hour clock.");
}
RTC.setClock();
break;
case 'A':
case 'a':
if(RTC.is12hour()) {
RTC.setAM();
RTC.setClock();
Serial.println("Set AM.");
} else {
Serial.println("(Set hours only in 24-hour mode.)");
}
break;
case 'P':
case 'p':
if(RTC.is12hour()) {
RTC.setPM();
RTC.setClock();
Serial.println("Set PM.");
} else {
Serial.println("(Set hours only in 24-hour mode.)");
}
break;
case 'q':
RTC.sqwEnable(RTC.SQW_1Hz);
Serial.println("Square wave output set to 1Hz");
break;
case 'Q':
RTC.sqwDisable(0);
Serial.println("Square wave output disabled (low)");
break;
case 'z':
RTC.start();
Serial.println("Clock oscillator started.");
break;
case 'Z':
RTC.stop();
Serial.println("Clock oscillator stopped.");
break;
case '>':
in=SerialReadPosInt();
in2=SerialReadPosInt();
RTC.writeData(in, in2);
Serial.print("Write to register ");
Serial.print(in);
Serial.print(" the value ");
Serial.println(in2);
break;
case '<':
in=SerialReadPosInt();
in2=RTC.readData(in);
Serial.print("Read from register ");
Serial.print(in);
Serial.print(" the value ");
Serial.println(in2);
break;
default:
Serial.println("Unknown command. Try these:");
Serial.println(" h## - set Hours [range 1..12 or 0..24]");
Serial.println(" i## - set mInutes [range 0..59]");
Serial.println(" s## - set Seconds [range 0..59]");
Serial.println(" d## - set Date [range 1..31]");
Serial.println(" m## - set Month [range 1..12]");
Serial.println(" y## - set Year [range 0..99]");
Serial.println(" w## - set arbitrary day of Week [range 1..7]");
Serial.println(" t - toggle 24-hour mode");
Serial.println(" a - set AM p - set PM");
Serial.println();
Serial.println(" z - start clock Z - stop clock");
Serial.println(" q - SQW/OUT = 1Hz Q - stop SQW/OUT");
Serial.println();
Serial.println(" >##,### - write to register ## the value ###");
Serial.println(" <## - read the value in register ##");
}//switch on command
}
//read in numeric characters until something else
//or no more data is available on serial.
int SerialReadPosInt() {
int i = 0;
boolean done=false;
while(Serial.available() && !done)
{
char c = Serial.read();
if (c >= '0' && c <='9')
{
i = i * 10 + (c-'0');
}
else
{
done = true;
}
}
return i;
}[/SPOILER]
[video=youtube;Y_bzUAdFxbk]https://www.youtube.com/watch?&v=Y_bzUAdFxbk[/video]