DS3231 óra riasztás használata

Tartalom:

  • A DS3231 RTC óra chip regisztereinek felépítése
  • Dátum és óra beállítása az adatregiszterek írásával, dátum és idő kiolvasása
  • Ébresztési (riasztási) időpontok beállítása, ébresztés időpont lekérdezése, riasztás az INT kimenettel
  • Hőmérséklet kiolvasása
  • Négyszöghullám kimenet beállításai
  • Megszakítás beállítások
  • Példa forráskód, modul kapcsolási rajz

————————————————————————————

Nem gondoltam, hogy valaha szükségem lesz a DS3231 óra alapos megismerésére, azonban mindennek eljön egyszer az ideje. Szeretnék egy beállítható idővel működő mérés adatgyűjtőt készíteni, ami adatokat rögzít SD kártyára. Ráadásul szeretném, ha akkumulátorról működne, amihez az Arduino-t alvás állapotában kell tartani két mérés között. Ehhez a DS3231 óra megszakítás funkciójára lesz szükség. Be kell programozni egy időpontot, és amikor ez elérkezik az óra felébreszti az Arduino-t, illetve ez biztosan egy ATmega328P chip lesz, mert az Arduino nano, vagy uno nagyon sokat fogyaszt. A DS3231 működésének megismerése bonyolultabb volt, mint gondoltam.

Lássuk először a részletes működést. Elővettem az adatlapját, és lefordítottam magamnak a szükséges részeket. Sajnos a fordítás során több mindent félreértettem, ezeket a hibákat javítottam, ahol kiderült. Bízom benne, hogy már jó a szöveganyag, és lehet vele dolgozni. Talán másnak is hasznos!

A DS3231 címezhető regiszterei:

Az alábbi ábra a DS3231 regisztereit mutatja. Több bájtos hozzáférés során, amikor a cím mutatója eléri a regiszter terület végét (12h), a következő beolvasott regiszter újra a 00h lesz. Az I2C START esetén, vagy ha több bájt olvasásakor a cím újra 00h címre kerül, az aktuális idő átkerül egy második regiszterkészletbe. Az időinformációt ezekből a másodlagos regiszterekből olvassa ki, miközben az óra továbbra is futhat. Ez kiküszöböli azt a problémát, hogy a regiszterek olvasása közben egyes bitek megváltozhatnak, ami miatt a kiolvasott érték nem lesz következetes (pl. 59 másodperc kiolvasása után az eltelt rövid időben a perc kiolvasásakor a perc már 1-el megnövekedhet, míg a másodperc 00-ra változik, ezért a kiolvasott érték 1 perccel későbbi időpontot mutatna).

Idő is dátum regiszterek (00h-06h):

Az idő és a naptár adatait a megfelelő regiszter bájtok kiolvasásával kapjuk meg. Az idő és a dátum adatokat a megfelelő regiszter bájtok írásával lehet beállítani. Az idő- és naptár regiszterek tartalma bináris kódolású decimális (BCD) formátumban kerül tárolásra.Magyarázatok a regiszterekben található jelző bitetekhez (12/24, AM/PM, Century), és a regiszter értékek kezeléséhez:

  • A DS3231 12 vagy 24 órás üzemmódban is működtethető. Az aktuális idő óráját mutató regiszter (02h) 6. bitje határozza meg, hogy 12 vagy 24 órás üzemmódban működik az óra. Ha ez 1, akkor a 12 órás üzemmód érvényes. 12 órás üzemmódban az 5. bit az AM/PM bit határozza meg, hogy a mutatott idő óra értéke délelőttöt vagy délutánt jelent. Amikor értéke 1, az délutánt (PM) jelent. 24 órás módban az 5. bit a második 10 órás bit, mert ekkor az óra tízes számjegye már nem csak 0 és 1 (0-12 óráig), hanem 2 is lehet (20–23 óráig), amihez két bitre van szükség.
  • Az évek kijelzésekor csak az év utolsó két számjegye kerül tárolásra. Az itt található értéket alapértelmezetten 2000-hez kell hozzáadni. Az évszázad bitjét (a 05h hónap regiszter 7. bitjét) akkor kell használni, ha 2099 után 2100 következik, mert ekkor ez a bit bebillen 1-be. Ha valaki ezzel foglalkozni akar, akkor innen tudhatja, hogy az években található 00 már nem 2000-et, hanem 2100-at jelent. Nyilván ebben a távoli jövőbeni pillanatban érdemes a bit-et törölni, és ekkor 2200-ban is megfejthetjük a pontos dátumot. Ezzel azonban már csak R. Daneel Olivaw-nak kell foglalkoznia, aki majd kb. 20.000 évig fogja szolgálni az emberiséget Asimov Alapítványában.
  • A hét napjának változtatása éjfélkor történik. A hét napjának megfelelő értékeket a felhasználó határozza meg, de szekvenciának kell lennie (azaz ha 1 egyenlő vasárnap, akkor 2 egyenlő hétfővel és így tovább).
  • A nem logikus idő, dátumbevitel és hét napjának beírása meghatározatlan működést eredményez.
  • Az idő- és dátumregiszterek olvasásakor vagy írásakor a DS3231 másodlagos (felhasználói) puffereket használ a hibák elkerülésére a belső regiszterek frissítésekor. A visszaszámláló láncot a másodperc regiszter írása törli. Az átfutási problémák elkerülése érdekében az óra, perc és dátum regisztereket 1 másodpercen belül be kell állítani. Az 1 Hz-es négyszöghullámú kimenet, ha engedélyezve van, a másodperc érték beírását követő 500 ms után vált, feltéve, hogy az oszcillátor már fut.

Riasztási regiszterek (07h-0Dh):

Kétféle módon jelzi a DS3231 ha riasztás történt. Egyrészt lekérdezhető a status regiszter (0Fh) A1F és A2F bitjeiből, melyek 1-el jelzik, ha volt riasztás, másrészt ha az INT/SQW kimenet nem a négyszögjel kimenetnek van állítva, akkor alacsony szinttel jelzi a riasztási eseményt. Az INT/SQW névben az INT-et aláhúzassal kellene jelölni, mert ez jelöli, hogy az alacsony szint az aktív. Azonban az aláhúzás a weblapon nem jelent meg, nem küzdöttem vele. A DS3231 két dátum/idő riasztást tartalmaz. A riasztások bekapcsolhatók a riasztás engedélyezésével (AI1E és AI2E a kontroll regiszterben) és a kontrollregiszter INTCN bitjével. Az INT/SQW kimenet aktiválásához egyeznie kell a beállított biteknek az aktuális idő megfelelő bitjeivel (00h-02h, 03h vagy 04h). Az 1. riasztást úgy lehet beállítani, hogy a 07h-tól 0Ah-ig terjedő regiszterek bitjeit állítjuk be:

Az egyes dátum/idő riasztási regiszterek 7. bitjei maszkbitek. Ha az összes riasztáshoz tartozó maszk bit 0, akkor minden beállított értéket figyel az óra. Akkor lesz ilyen esetben riasztás, ha az aktuális idő megfelelő regisztereinek bitjei megegyeznek a dátum/idő riasztás regiszterekben tárolt bitekkel. Ha a maszk biteket 1-re állítjuk, akkor az adott időpont adatot nem nem vesz részt a riasztásban. például, ha az A1M1 maszk bit 1, akkor a hét vagy hónap napjának egyezőségét nem figyeli a rendszer, azaz bármilyen napon bekövetkezik a riasztás, ha az óra, perc és másodperc értékek megegyeznek. A lehetséges beálltásokat az alábbi táblázat tartalmazza.

A fenti táblázat a lehetséges beállításokat mutatja. A táblázatban nem felsorolt ​​konfigurációk logikátlan működést eredményeznek. A DY/DT bit (a hét napja vagy hónap napja regiszter 6. bitje) beállítja, hogy a regiszter 0–5 bitjeiben tárolt riasztási érték a hét napját vagy a hónap dátumát jelenti. Ha a DY/DT = 0, akkor a riasztás a hónap napjával való egyeztetéskor következik be. Ha a DY/DT = 1, akkor a riasztás a hét napjával való egyezéskor következik be.
Ha az aktuális idő regisztereinek bitjei megegyeznek a riasztási regiszter bitjeivel, akkor a megfelelő A1F vagy A2F riasztási jelzőbit 1-re billen. Ha a bit értéke 1, az aktiválja INT/SQW jelet. Az egyezést másodpercenként teszteli a DS3231. Ha azt szeretnénk, hogy a riasztást követően az INT/SQW kimenet újra magas legyen, akkor törölni kell a riasztást az A1F és az A2F bitekben is. Ha nem töröljük, akkor egy következő ciklikus riasztást nem tud jelezni a DS3231.

A 2. riasztást úgy lehet beállítani, hogy a 0Bh – 0Dh regiszterek bitjeit állítjuk be:

Ez a riasztási regiszter abban különbözik az 1. riasztási regisztertől, hogy a másodperc egyezését nem figyeli. A lehetséges riasztási eseteket a következő táblázat tartalmazza:

Control Register (0Eh)

7. bit: Oszcillátor (EOSC) engedélyezése. Ha 0-ra állítjuk, az oszcillátor működik. Ha 1-re állítjuk és a VBAT kivezetésről kap feszültséget a DS3231, akkor az oszcillátor leáll. Ez a bit 0, amikor az IC tápfeszültségét bekapcsoljuk. Ha a DS3231 IC-t a VCC kivezetés táplálja, az oszcillátor mindig be van kapcsolva, az EOSC bit állapotától függetlenül. Ha az EOSC le van tiltva (értéke 1), és a VBAT-ról működik a chip, az összes regiszter tartalma statikus az óra nem jár, de az utolsó érvényes időt őrzik a regiszterek, amíg az elem teljesen le nem merül.

6. bit: Négyszöghullám kimenet engedélyezése (BBSQW) akkumulátoros táplálás esetén. Ha az 1-re van állítva, és a DS3231 a VBAT kivezetésen keresztül kap feszültséget, az INT/SQW kimeneten megjelenik a négyszögjel, akkor is ha nincs feszültség a VCC kivezetésen. Az adatlap eredeti szövegének következő mondata ennek a bitnek a magyarázatához: “When BBSQW is logic 0, the INT/SQW pin goes high impedance when VCC falls below the power-fail trip point.”
Én ezt így fordítottam (értelmeztem): Amikor a BBSQW  0, az INT/SQW kivezetés nagy impedanciát mutat, amikor a VCC a minimális feszültségszint alá esik (kikapcsoljuk a tápfeszt és elemről tápláljuk az IC-t). Arra számítottam, hogy ez utóbbi mondat akkor is igaz, ha nem négyszögjel jön ki a vezetéken, hanem a megszakítás jelet szeretném felhasználni. A kísérleteim alapján azonban ez nem igaz. A mikor lekapcsolom a feszültséget a Vcc lábról, és az IC a Vbat bemeneten kap feszültséget elemről, az INT/SQW kimenet azonnal földre húzza magát. Nem hinném, hogy valamit elrontottam, mert ez egy nagyon egyszerű kapcsolás volt. Az INT/SQW kimenetet egy Arduino lábra kötöttem, ami bemenet. Ezt a bemenetet folyamatosan kérdezgettem, és néztem az állapotát. A DS3231 modulon van beépített felhúzó ellenállás, de gondoltam, hátha rossz, ezért kívülről raktam rá egyet. Ekkor is lemegy földre. Kipróbáltam úgy is, hogy ez a bit 1, de a ugyanaz az eredmény. Ha vissza adom a tápfeszt, azonnal magasra megy, és a risztás is bekövetkezik, tehát az IC működése rendben van attól, hogy egy időre nem volt tápfesz csak elemről. Ez elkeserítő számomra, mert ezek szerint elemről táplált állapotban nem képes megszakítás lábbal riasztani. Bár a leírás csak a négyszögjel kibocsátásról szól, de reménykedtem, hogy ettől még a megszakítás üzemmódban is működik a láb. Úgy tűnik nem. Egyébként a leírás szerint ez a bit 0, amikor a tápfeszültséget bekapcsoljuk.

5. bit: Hőmérséklet (CONV) konvertálása. Ennek a bitnek az 1-re állítása elindítja a hőmérséklet mérést, és a hőmérséklet regiszter (11h és 12h) értékének frissítését, és végrehajtja a TCXO algoritmust, hogy frissítse a kapacitási tömböt az oszcillátorban (ez nem tudom, hogy pontosan mit jelent, de feltehetőleg az óra pontosságának javításához van köze). Ez csak akkor történhet meg, ha az átalakítás még nem zajlik. A felhasználónak ellenőriznie kell a BSY állapotbitet, mielőtt a vezérlőt új TCXO végrehajtás elindítására kényszeríti. A felhasználó által kezdeményezett hőmérséklet-átalakítás nem befolyásolja a belső 64 másodperces frissítési ciklust. A felhasználó által kezdeményezett hőmérséklet-átalakítás kb. 2ms-ig nem befolyásolja a BSY-bitet. A CONV bit az íródástól az átalakítás befejezéséig 1-en marad, ez után CONV és  BSY 0-ra megy. A CONV bitet kell használni a felhasználó által kezdeményezett konverzió állapotának figyelésére.

Bit 4. és 3.: Rate Select (RS2 és RS1). Ezek a bitek szabályozzák a négyszöghullám frekvenciáját, amikor a négyszöghullám engedélyezve van. Az alábbi táblázat bemutatja az RS bittel választható négyszöghullámú frekvenciákat. Mindkét bit alapértelmezetten 1 (8,192 kHz), amikor a tápfeszültséget bekapcsoljuk.

Bit 2: Megszakító vezérlés (INTCN). Ez a bit vezérli az INT/SQW kivezetést. Ha az INTCN bit értéke 0, négyszög jelet ad ki az INT/SQW kivezetés. Ha az INTCN bit értéke 1, akkor az aktuális idő regiszterek és a riasztási regiszterek közötti egyeztetés 0-ra állítja az INT/SQW kimenetet (ha a riasztás szintén engedélyezve van). A megfelelő riasztási jelzőt mindig az INTCN bit állapotától függetlenül állítják be. Az INTCN bit értéke alapértelmezetten 1, amikor a tápfeszültséget bekapcsoljuk.

Bit 1: 2. riasztás megszakítás engedélyezése (A2IE). Ha az 1-re van állítva ez a bit, az lehetővé teszi a 2. riasztás jelző (A2F) számára, hogy INT/SQW kimenetet 0-ra állítsa megszakításkor (ha INTCN = 1). Ha az A2IE bit értéke 0 vagy az INTCN értéke 0, akkor az A2F bit nem kezdeményez megszakítási jelet az INT/SQW kivezetésen. Az A2IE bit alapértelmezetten le van tiltva (0), amikor a tápfeszültséget bekapcsoljuk.

Bit 0: 2. riasztás megszakítás engedélyezése (A1IE). Ha az 1-re van állítva ez a bit, az lehetővé teszi a 1. riasztás jelző (A1F) számára, hogy INT/SQW kimenetet 0-ra állítsa megszakításkor (ha INTCN = 1). Ha az A1IE bit értéke 0 vagy az INTCN értéke 0, akkor az A2F bit nem kezdeményez megszakítási jelet az INT/SQW kivezetésen. Az A1IE bit alapértelmezetten le van tiltva (0), amikor a tápfeszültséget bekapcsoljuk.

Status Register (0Fh)

7. bit: Oszcillátor Stop Flag (OSF). Ebben a bitben az 1 azt jelzi, hogy az oszcillátor vagy leállt, vagy egy ideig leállt. Ez felhasználható az az óra pontosságának megítélésére. Az alábbiakban esetekben válthat az OSF 1-re:

  1. A tápellátás most kapcsoltuk be.
  2. A VCC-n és a VBAT-n egyike sem elegendő az oszcillátor működéséhez.
  3. Az EOSC bit kikapcsolt akkumulátorral támogatott módban volt miközben VBAT-ról történt a táplálás.
  4. A kristályra gyakorolt külső hatások (azaz zaj, szivárgás stb.) miatt leállt az osszcillátor.

Ez a bit az 1-en marad, amíg nem töröljük.

3. bit: Engedélyezi a 32 kHz-es kimenetet (EN32 kHz). Ez a bit vezérli a 32 kHz-es kivezetés állapotát. Ha az 1-re van állítva, a 32 kHz-es kivezetés engedélyezve van, és 32,768 kHz négyszöghullámú jelet ad ki. Ha 0-ra állítjuk, a 32 kHz-es kivezetés nagy impedanciájú állapotba kerül. Ennek a bitnek a kezdeti bekapcsolási állapota 1, és egy 32,768 kHz négyszöghullámú jel jelenik meg a 32 kHz-es kivezetésnél a DS3231 bekapcsolása után (ha az oszcillátor működik).

2. bit: Foglalt (BSY). Ez a bit azt jelzi, hogy az eszköz elfoglalt a TCXO funkciók végrehajtásában. 1-re állítódik, amikor a hőmérséklet-érzékelőre történő átalakítási folyamatban van, majd törlődik, amikor az eszköz 1 perces szünetet tart a következő mérésig.

1. bit: 2. riasztás jelző (A2F). Azt jelzi, hogy a 2. riasztáshoz tartozó idő megegyezett az óra aktuális idejével. Ha az A2IE bit 1, és az INTCN bit 1, akkor az INT/SQW kivezetés megszakítást jelez ennek a bitnek a hatására. Az A2F bitet törölni kell egy riasztást követően. Ezt a bitet csak a 0-ra lehet írni. Ha megpróbáljuk 1-re írni, az érték változatlan marad.

0. bit: 1. riasztás jelző (A1F). Azt jelzi, hogy a 2. riasztáshoz tartozó idő megegyezett az óra aktuális idejével. Ha az A1IE bit 1, és az INTCN bit 1, akkor az INT/SQW kivezetés megszakítást jelez ennek a bitnek a hatására. Az A1F bitet törölni kell egy riasztást követően. Ezt a bitet csak a 0-ra lehet írni. Ha megpróbáljuk 1-re írni, az érték változatlan marad.

Példa program az INT/SQW kimenet megszakításokkal történő használatára:

A programot bőven elláttam kommentekkel. Sok magyarázatot nem is fűznék hozzá. Ez a program még nem küldi alvásba az ATmega328P chip-et, és még a DS3231 elemes működése sincs benne megoldva. Annyit érdemes tudni, hogy elemes táplálás esetén alapértelmezetten az INT/SQW kimenet magas impedanciás állapotba kerül, azaz nincs rajta megszakítás jel. Ezt külön be kell kapcsolni, hogy működjön, és az általam használt DS3231 könyvtár ezt nem tartalmazza, tehát meg kell írni. Erre még nem volt időm, bár egyáltalán nem látszik bonyolultnak. Még érdemes megnézni a DS3231 könyvtár forráskódját is Github-on. Link a forrás első sorában. Ez volt az első amit letöltöttem magamnak. A leírások és példa programok elég szerények, de használható. Rengeteg DS3231 kezelő könyvtár létezik, de egyikben sem találtam állítási lehetőséget az elemes táplálásban történő INT/SQW kimenet beállítására, így maradtam ennél a könyvtárnál. Ha készen lesz a függvény, még annyit fog változni a program, hogy az ATmega chip egyik lábáról fogja a tápfeszt kapni a DS3231, hogy az I2C kommunikáció idejére be lehessen kapcsolni, amikor a következő riasztási időpontot beállítom majd.

#include <DS3231.h> // https://github.com/NorthernWidget/DS3231 beépített függvénnek forrása a linken megnézhető
#include <Wire.h>
DS3231 Clock;

byte Year,Month,Date,Hour,Minute,Second,DoW; //óra beállításkor illetve óra kiolvasás segéd változói, Dow a hét napja (1-7)
bool Century=false; //évszázad jelzése, ha 0 akkor 2000-2099, ha 1 akkor 2100-2199 
bool h12; //24 órás időpontot használunk
bool PM; //ha 12 órást használnánk, ez jelezné a délutánt (1-el)
byte ADay; //riasztásban a hét napja (1-7), vagy a hónap napja (1-31)
byte AHour, AMinute, ASecond, ABits;  //riasztási időpont változói
bool ADy; //risztásban ez jelzi, hogy hét napja (1) vagy hónap napja (0) lesz figyelve
bool A12h, Apm; //12 órás üzemmód esetén A12h true, jelen programban 24 órás üzemmódot használunk


void setup() {
  Wire.begin();
  Serial.begin(9600);

  pinMode(13, OUTPUT); //a 13-as kivezetésen van a LED
  digitalWrite(13, LOW); //led nem világít

 /******************************************************************************************* 
  * óra beállítás, csak egyszer kell beállítani aztán az elem őrzi az időt a DS3231-en   
  * miután egyszer lefordítottuk és le töltöttük a programot, az alábbi rész kikommentezhető
  *******************************************************************************************/
  /* Clock.setClockMode(false); //óra üzemmód 24 órás
    Clock.setSecond(0);
    Clock.setMinute(14);
    Clock.setHour(7);
    Clock.setDate(5);
    Clock.setMonth(7);
    Clock.setYear(20);
    Clock.setDoW(7); 
  */
    
  // kiolvassuk az időt és kiírjuk a sorosportra
  Serial.println("Ora időpontja");
  Serial.println("-------------");
  //kiolvassuk az óra idopontját
  Year=Clock.getYear();
  Month=Clock.getMonth(Century);
  Date=Clock.getDate();
  Hour =Clock.getHour(h12, PM);
  Minute =Clock.getMinute();
  Second =Clock.getSecond();
  DoW=Clock.getDoW();
  //kiírjuk a sorosportra, hogy lássuk is
  Serial.print("Het napja:");Serial.print(DoW, DEC);Serial.print(" datum:");
  Serial.print("2");if (Century) {Serial.print("1");} else {Serial.print("0");}
  Serial.print(Year, DEC);Serial.print("-");Serial.print(Month, DEC);Serial.print("-");Serial.print(Date, DEC);
  Serial.print(" ido:");
  Serial.print(Hour, DEC);Serial.print(':');Serial.print(Minute, DEC);Serial.print(':');Serial.print(Second, DEC);
  if (h12) {if (PM) {Serial.print(" PM ");} else {Serial.print(" AM ");}} else {Serial.println(" 24h ");}
  Serial.println();
  
  /******************************************************************************************************
  * riasztás beállító függvény paraméterezéséhez segítség:
  * setA1Time(nap/hét napja, óra, perc, másodperc, alarm mód, map/hét napja flag, H12 flag, PM flag)
  * nap/hét napja = 0-30 vagy 0-7
  * óra = 0-12 vagy 0-24 (H12=1 essetén 12 órás)
  * perc=0-59
  * másodperc=0-59
  * alarm mód:
  *  0b1111 - minden másodpercben riaszt
  *  0b1110 - mikor a másodperc megegyezik riaszt
  *  0b1100 - mikor a perc és a másodperc megegyezik riaszt
  *  0b1000 - mikor az óra, perc és a másodperc megegyezik riaszt
  *  0b0000 - mikor a hét napja vagy a hónap napja, az óra, perc és a másodperc megegyezik riaszt 
  * nap/hét napja flag:
  *  0 - hónap napján riaszt (1-31)
  *  1 - hét napján riaszt (1-7)
  * H12 falg:
  *  0 - 12 órás idő megadás
  *  1 - 24 órás idő megadás
  * PM flag (csak akkor, ha H12=1):
  *  0 - délelőtt
  *  1 - délután
  **********************************************************************************************************/
  //Riasztási funkciók beállítása
  
  // beállítási példa: a hét ugyanazon napán (beállítás napja), a pillanatnyi idő + 1 perc időpontban lesz risztás, 24 órás üzemmód
  // Vigyázni, mert ha pont óra 59. percében adjuk ki, akkor a riasztásban a perc 60 lesz, ami hülyeség
  //Clock.setA1Time(DoW, Hour, Minute+1, Second, 0b0000, true, false, false);
  
  //beállítási példa: a hét napja vagy a hónap napja nem számít, óra nem számít, perc nem számí, ha másodperc megegyezik, akkor lesz riasztás, 24 órás üzemmód
  // Vigyázni, mert ha pont óra 59. percében adjuk ki, akkor a riasztásban a perc 60 lesz, ami hülyeség
  Clock.setA1Time(DoW, Hour, Minute+1, Second, 0b1110, true, false, false);
  
  Clock.turnOnAlarm(1);  //engedélyezzük a 1. risztást 
  Clock.turnOffAlarm(2); //a 2. riasztást most nem használjuk
    
  //lekérdezzük a riasztási időpontot és kiírjuk a sor sportra
  Serial.println("Riasztási idopont");
  Serial.println("-----------------");
  Clock.getA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm); //lekérdezzük a risztási adatokat
  if (ADy) {Serial.print("Het napja:");} else {Serial.print("Honap napja:");} Serial.print(ADay, DEC);
  Serial.print(" Idopont:");Serial.print(AHour, DEC);Serial.print(':');Serial.print(AMinute, DEC);Serial.print(':');Serial.print(ASecond, DEC);Serial.print(' ');
  if (A12h==LOW) {Serial.print("24h ");} else {if (Apm) {Serial.print("PM ");} else {Serial.print("AM ");}}
  if (Clock.checkAlarmEnabled(1)) {Serial.print("Risztas engedelyezve");} else {Serial.print("Riasztas tiltva");}
  Serial.print(" Alarm bits:");Serial.println(ABits,BIN);Serial.println();



 /*****************************************************************************************
  * Megszakítási bemenetek előkészítése
  * belső felhúzó ellenállás bekapcsolva, mert a DS3231 INT/SQW kimenete
  * magas impedanciás állapotban van ha nincs riasztás, és a felhúzó ellenállás húzza fel 1-re,
  * riasztáskor földre húzza az INT/SQW kimenetet 
  *****************************************************************************************/
  delay(500);
  pinMode(2,INPUT); //megszakítás 0 bemenet, erre kötjük a DS3231 INT/SQW kimenetét
  digitalWrite(2,HIGH);
  pinMode(3,INPUT); //megszakítás 1 bemenet, ezen nyomógomb lesz a riasztásjelzés törléséhez
  digitalWrite(3,HIGH);

  /*****************************************************************************************************************
   megszakítások beállításának paraméterezéséhez segítség:
   attachInterrupt(kivezetés száma, meghívott függvény, esemény mód)
   esemény módok:
     LOW: az interrupt bemenet alacsony állapotban van
     CHANGE: ha a bemenet értéke változik, magasról alacsonyra vagy alacsonyról magasra
     RISING: ha a bemeneti jel alacsonyról magasra változik
     FALLING: ha a bemeneti jel magasról alacsonyra vált.
   A megszakítás közben a késleltetés [delay()] nem működik, és a millis() által visszaadott érték nem növekszik.
   A megszakítás végrehajtása közben a soros portra érkező adatok elveszhetnek.
   Valamennyi változót, amelyet módosítani szeretne a megszakításban, volatile-ként kell definiálnia.
   ****************************************************************************************************************/
  attachInterrupt(0, int_0, FALLING); //a kettes bemeneten lefutó élre (1->0) meghívódik a int_0 függvény (INT/SQW riasztást ad)
  attachInterrupt(1, int_1, FALLING); //a hármas bemeneten lefutó élre (1->0) meghívódik a int_1 függvény (megnyomtuk a nyomógombot)

  /*
   * nem tudok rájönni, hogy miért, de a program elindulásakor egyszer meghívódik az int_0() függvény, és kigyullad a led
   * Ezért kénytelen vagyok kikapcsolni a led-et azzal, hogy meghívom az int_1() függvényt. Lehetne úgy is, hogy simán 
   * kikapcsolom a led-et a kimenet LOW-ra állításával. Kinek hogyan teszik jobban. Ettől kezdve a megszakítás jól működik
   */
  //int_1();
  digitalWrite(13,LOW);    
}

void loop() {
  //lekérdezzük a D2 állapotát, vajon risztás után magas, vagy alacson (alacsony)
  if (digitalRead(2)) {Serial.println("2 high");} else {Serial.println("2 low");}
  
  // lekérdezi a riasztás jelző állapotát, és egyben törli is a risztás jelző bitet IDS3231 status regiszter (0Fh) A1F
  // ha nem töröljük a riasztás jelző bitet, akkor az INT/SQW kivezetés magas marad, és nem történik következő riasztás
  // ezt az int_0() függvénybe kellett volna rakni, de akkor nem tudtam volna lekérdezni a D2 bemenet állapotát
  // így látható, hogy riztás után mindaddig magas az INT/SQW, amíg nem töröljük
  Clock.checkIfAlarm(1); 
   
  delay(1000);
}

void int_0() {
  // a 2-es bemeneten érkezett egy 0 jelszint, beállítjuk a led állapot jelzést 1-re
  Serial.println("Megszakitas 0, led be");
  digitalWrite(13, HIGH);
}

void int_1() {
  // a 3-es bemeneten érkezett egy 0 jelszint, beállítjuk a led állapot jelzést 0-ra
  Serial.println("Megszakitas 1, led ki");
  digitalWrite(13, LOW);
}

Mint azt a kontrol regiszter 6. bitjénél (BBSQW) leírtam, nekem nem sikerült a DS3231-et elemmel táplált üzemmódban arra rábírnom, hogy az INT/SQW lábon megszakítás jelet küldjön. Vagyis a modult csak bekapcsolt Vcc állapotban lehet használni. Ez egyébként önmagában még nem baj, mert az áramfelvétele még így is igen kicsi a DS3231 chip-nek. A leírás szerint ha nem kommunikálok vele I2C buszon keresztül, 200 mikroA körüli áramot fogyaszt. Már ez is elegendően kicsi érték lenne. De nézzük, mit tud a DS3231 modul. Gyanítható, hogy a rajta lévő led, ami bekapcsolt Vcc esetén világít, már eleve használhatatlanná teszi a modult. És igen, 8 mA az áramfelvétel, de nem túl pontos árammérőm van, ezért ez csak nagyságrend. Ha kiforrasztom a led-et, akkor ez kisebb lesz pár milliA-el. De biztosan nem megy le 200 mikroA környékére. Ezért nézegetni kezdtem a modul kapcsolási rajzát, ami szerencsére fellelhető a neten:

Az R2 ellenállás értéke 1 Kohm, tehát itt 1mA alatti áramokra lehet számítani. Semmi más nincs ami fogyasszon. Illetve ott van még az AT24C32 eeprom. Azonban az adatlapja alapján ha nem írom és nem olvasom, akkor 35mikroA az áramfelvétele. Itt elakadtam. Vagy szétbarmolom a modult, és tönkre teszem a led-et, vagy keresek egy másik modult, amin csak óra van, nincs rajta led. Ezt tettem. Most várom, hogy megérkezzen aliexpresz-en. Addig pihi van!

Ha azonban nem lényeges az áramfelvétel, a fenti kapcsolás tökéletesen működik!


Eltelt közben elég sok idő, és elfelejtettem beírni a végső tapasztalatokat. Kiderült, hogy az IC INT kimenetét sehogyan sem tudtam elemes táplálás esetén bekapcsolni. Vagyis elemes táplálás esetén nem lehet vele riasztást kiadni. Kerestem ezért egy másik chip-et, a PCF8563 óra IC-t. Sajnos ez kevésbé pontos, mert nem hőmérséklet kompenzált, az áramfelvétele is kisebb, de a céljaimnak tökéletesen megfelelt. Leírását itt olvashatod!

Közben megérkezett a másik, elemmel egybeépített DS3231 modul. Sajna ezen meg nincs kivezetve a riasztás kimenet, így az elképzeléseimhez ez sem használható, pedig az áramfelvétele alapján igen jól használható lenne. Persze ahol csak az időt kell lekérdezni, oda ez tökéletes. Így néz ki:

Mennyire volt hasznos amit olvastál? Értékelés után szövegesen is leírhatod megjegyzéseidet és véleményedet!

Kattints egy csillagra az értékeléshez!

Szövegesen is leírhatod véleményedet! Ha kérdésed van, ne felejtsd el megadni az email címedet!