Részletekre fogom bontani a programot és igyekszem a legérthetőbben elmagyarázni, mi is történik.
Definiciók:
Itt történnek a könyvtárak meghívásai, mely sorrendben:
- Wire.h -> Az I2C kommunikációért felelős könyvtár
- DS3231.h -> A DS3231-es modulért felelős könyvtár
- #define DS3231 B1101000 -> A DS3231 modul I2C címe
- A DS3231-es modulon lévő EEPROM-ot (AT24C32) nem használtam, de azért deklaráltam a címét és példaként memóriacímeket is.
Konstansok:
const int pinTest = 10; // Teszt gomb
Szegmensekhez tartozó bájt: (Kommentben a port neve és száma, hogy hová csatlakozik)
byte segment[] = {
2, // segmA = PD2
3, // segmB = PD3
4, // segmC = PD4
5, // segmD = PD5
6, // segmE = PD6
7, // segmF = PD7
8 // segmG = PB0
};
LED-ekhez tartozó bájt: (Kommentben a port neve és száma, hogy hová csatlakozik)
byte leds[] = {
A0, // Hours 1st place = PC0
A1, // Hours 2nd place = PC1
A2, // Minutes 3rd place = PC2
A3}; // Minutes 4th place = PC3
byte second=0, minute=0, hour=0, weekday=0, day=0, month=0, year=0; // Óra, perc, a hét napja, nap, hónap, év bájtjai
int test_delay = 200; // Tesztmód során a késleltetés
void updateTime(); // updateTime() alprogram meghívása
void printTime(); // printTime() alprogram meghívása
void print7Digit(byte number); // print7Digit(byte number) alprogram meghívása
byte DECTOBCD(byte val); // Decimálist BCD-re konvertáló bájt
byte BCDTODEC(byte val); // BCD-t decimálisra konvertáló bájt
// Nyári és téli időszámításhoz szükséges programrész
bool isDaylightSavingTime(int year, int month, int day, int weekday) {
// The Daylight saving time will starts at the last sunday of March
if (month == 3 && (day + 7 - weekday) > 31) {
return true;
}
// The daylight saving time will ends at the last sunday of October
if (month == 10 && (day + 7 - weekday) > 31) {
return false;
}
// From April to September it is always daylight saving time
if (month > 3 && month < 10) {
return true;
}
//The default is the winter time
return false;
}
A void setup() minden esetben csak egyetlen egyszer fut le, épp ezért ha bekapcsolásnál a "TEST" gombot nyomva tartjuk akkor fog a program beugrani a tesztmódba, amit fentebb már taglaltam. Azon felül a LED-ek és a szegmensek bájtjának inicializálása történik itt, valamint az I2C (Wire.begin()) kommunikációnak az elindítása.
byte init_segm;
byte init_leds;
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
// Serial.begin(9600); // Begin Serial Port
Wire.begin(); // Begin I2C communication
// Initialize segments and pull them down
for (init_segm = 0; init_segm < 8; init_segm++) {
pinMode(segment[init_segm], OUTPUT);
digitalWrite(segment[init_segm], HIGH);
}
// Initialize leds and pull them down
for (init_leds = 0; init_leds < 3; init_leds++) {
pinMode(leds[init_leds], OUTPUT);
digitalWrite(leds[init_leds], LOW);
}
// Test all the segments and leds when holding the "TEST" button during powering up (When the for cycle finishes it will return to the loop)
if (digitalRead(pinTest) == HIGH) {
int led = 0;
int segm = 0;
for (segm = 0; segm < 8; segm++) {
digitalWrite(segment[segm], LOW);
delay(test_delay);
}
for (led = 0; led < 4; led++) {
digitalWrite(leds[led], HIGH);
delay(test_delay);
}
}
}
A void loop() minden ciklusban lefut, így ebbe helyeztem el két fontos alprogramot, melyek sorrendben updateTime(), valamint printTime(). Az updateTime() alprogramban az idő kerül kiolvasásra, és értelemszerűen a printTime() alprogramban pedig kijelzésre kerül az idő, mely kiolvasásra került.
void loop() {
updateTime(); // Call updateTime subroutine
printTime(); // Call printTime subroutine
}
Az updateTime() alprogramban BCD-ből DEC-be való konvertálás történik valamint az idő kiolvasása a DS3231-es RTC modulból és az idő felbontása másodpercekre, percre és órára, hét napjaira, napra, hónapra és évre a nyári és téli időszámítás alkalmazása miatt.
void updateTime() {
Wire.beginTransmission(DS3231);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(DS3231, 7);
second = BCDTODEC(Wire.read());
minute = BCDTODEC(Wire.read());
hour = BCDTODEC(Wire.read());
weekday = BCDTODEC(Wire.read());
day = BCDTODEC(Wire.read());
month = BCDTODEC(Wire.read() & 0x1f);
year = BCDTODEC(Wire.read() + 2000);
if (isDaylightSavingTime(year, month, day, weekday)) {
hour +=1;
if (hour == 24) {
hour = 0;
}
}
}
A printTime() alporgramban történik a 24 órás formátum beállítása, valamint a LED-ek vezérlése mely az óráknál és a percek kijelzésekor villan fel a könnyebb leolvasás érdekében. Az órák (hh) és percek (mm) kijelzését követően egy 2 másodperces késleltetés következik.
byte printTimeVar;
// Convert from 24 hour to 12 hour mode
byte temphour = hour;
if (temphour == 0) {
// Not zero based, not one based, but 24 based.
temphour = 24;
}
// Hours 1
if (temphour > 0) {
print7Digit(temphour / 10);
digitalWrite(A0, HIGH); // Hours 1
digitalWrite(A1, LOW); // Hours 2
digitalWrite(A2, LOW); // Minutes 1
digitalWrite(A3, LOW); // Minutes 2
delay(500);
for (printTimeVar = 0; printTimeVar < 8; printTimeVar++) {
digitalWrite(segment[printTimeVar], HIGH);
}
delay(100);
}
// Hours 2
print7Digit(temphour % 10);
digitalWrite(A0, LOW); // Hours 1
digitalWrite(A1, HIGH); // Hours 2
digitalWrite(A2, LOW); // Minutes 1
digitalWrite(A3, LOW); // Minutes 2
delay(500);
for (printTimeVar = 0; printTimeVar < 8; printTimeVar++) {
digitalWrite(segment[printTimeVar], HIGH);
}
delay(100);
// Minutes 1
print7Digit(minute / 10);
digitalWrite(A0, LOW); // Hours 1
digitalWrite(A1, LOW); // Hours 2
digitalWrite(A2, HIGH); // Minutes 1
digitalWrite(A3, LOW); // Minutes 2
delay(500);
for (printTimeVar = 0; printTimeVar < 8; printTimeVar++) {
digitalWrite(segment[printTimeVar], HIGH);
}
delay(100);
// Minutes 2
print7Digit(minute % 10);
digitalWrite(A0, LOW); // Hours 1
digitalWrite(A1, LOW); // Hours 2
digitalWrite(A2, LOW); // Minutes 1
digitalWrite(A3, HIGH); // Minutes 2
delay(500);
for (printTimeVar = 0; printTimeVar < 8; printTimeVar++) {
digitalWrite(segment[printTimeVar], HIGH);
}
digitalWrite(A0, LOW); // Hours 1
digitalWrite(A1, LOW); // Hours 2
digitalWrite(A2, LOW); // Minutes 1
digitalWrite(A3, LOW); // Minutes 2
delay(1000);
}
A print7Digit() alprogramban egy bitmező került kialakításra a kijelző egyes szegmenseinek a vezérlésére.
void print7Digit(byte number) {
// Bitfield for digits 0-9
const byte numtable[] = {
B01000000, // 0
B01111001, // 1
B00100100, // 2
B00110000, // 3
B00011001, // 4
B00010010, // 5
B00000010, // 6
B01111000, // 7
B00000000, // 8
B00010000 // 9
};
byte litpins = numtable[number];
byte nums;
for (nums = 0; nums < 8; nums++) {
digitalWrite(segment[nums], (litpins >> nums) & 1);
}
}
A program végén pedig decimálisból bináris kódba valamint bináris kódból decimálisba való alakítás történik
byte DECTOBCD(byte val) {
return ((val / 10) << 4) + (val % 10);
}
byte BCDTODEC(byte val) {
return (val >> 4) * 10 + (val & 0xf);
}
Ennyit a programról. Természetesen a cikkem végén közzéteszem az .ino fájlt ha valaki szeretné szerkeszteni, vagy csak tanulni belőle.
A cikk még nem ért véget, lapozz!