Tartalom:
- Nagy számok a kijelzőn, környezeti megvilágításhoz alkalmazkodik
- Nappal egész óránként bemondja az időt
- Gombnyomásra kijelzi a dátumot és a hét napját, és ezeket az adatokat el is mondja
- Választható női és férfi hang, beállítható hangerő
- Szerelési tapasztalatok, forráskód
Régi elképzelésem volt, hogy készítsek egy beszélő mérőműszert, ami bemondja a mért feszültség és áram értékeket, így nem kell a műszerre nézni mérés közben. Végeztem előtanulmányokat és készítettem mp3 lejátszóval egy olyan programot, ami szavakból összerakja a mondandó adatot. A hangokat a Word és a Google felolvasó moduljától „loptam” el. Az előbbi linken megtalálhatók az mp3 állományok, nem kell megcsinálni! Nem szépen beszél, de érthetően. Elég sokféle adat bemondására felkészültem többek között az idő és dátum bemondásra is. Aztán kiderült, hogy anyukámnak szürkehályog műtétre lesz szüksége. Ha megműtik, akkor is csak nagyon homályosan fog látni egy másik gyógyíthatatlan szembetegség miatt. Hatalmas számjegyeket esetleg felismer majd. A magyar egészségügy a propaganda szerint gyorsan segít, a valóságban félig meg fog vakulni mire sorra kerül sürgősséggel. Jobb felkészülni a legrosszabbra! Nem akartam én beszélő órát csinálni! Először meg akartam venni. Magyarul beszélő óra azonban 25.000Ft-ért kapható, és épp tartósan nem volt készleten. Tiszta szocializmus! Így ugrott be az ötlet, hogy minden programom és alkatrészem meg van a feladathoz. Végre valami hasznosra fogom használni a szórakozásomat. Készítek egy órát, ami bemondja óránként (kivéve éjszaka) az időt, illetve gombnyomásra a dátumot és a hét napját is. Nagyon fontos a hét napja, mert aki egész nap otthon van, annak az unalmas hétköznapok tompítják az időérzékét. Tapasztaltuk, hogy anyukám már soha nem tudja milyen nap van. Nem is kell neki ez az infó, csak néha kellemetlenséget okoz, hogy azt hiszi, hét vége van, mi meg épp dolgozunk. Ez a beszélő óra hiteles története! Egyszer majd megfilmesítem! Engem Ray Liotta fog játszani. …basszus, már Ő is meghalt a múlt héten!
Egy kis reklám az óra tulajdonságaiból:
- MAX7219 meghajtókkal LED mátrix kijelzővel működő hatalmas kijelző
- A DS3231 chip-nek köszönhetően igen pontos, tapasztalatom szerint évi néhány másodperc az eltérés. Nem kell internetes időszerver hozzá!
- A hét napját magától tudja a dátumból, nem kell megadni
- Kezeli a szökőéveket
- Nyári időszámításra automatikusan átáll március utolsó vasárnapján, és vissza november utolsó vasárnapján.
- Bemondja óránként az időt egész órakor, amit egy rövid szignállal kezd. A bemondás csak egy beállítható időszakban történik. Éjszaka lehet aludni tőle!
- Gombnyomásra megmutatja a dátumot és a hét napját, valamint a pillanatnyi hőmérsékletet. Ugyanekkor be is mondja a pontos időt, a dátumot és a hét napját! Bemondás hangereje beállítható.
- A kijelző fényerejét beállítja a szoba fényviszonyaihoz.
- Gondozásmentes óra! Be kell dugni egy telefontöltő konnektorba dugható 5V-os tápjába, és évekig elvan magának!
Túl sok magyarázatot nem érdemel az óra működése. Az alapötlet már régi, és félig készen is volt! Vettem egy 4 tagból álló 8×8-as led mátrix kijelzőt, amit MAX7219 IC-k hajtanak meg. Ennek a hátsó felületére szereltem egy Arduino Nano-t, egy DS3231 óra modult, és egy DFRobot mp3 lejátszót. Járulékos anyag még egy TEP4400 fotótranzisztor, ami a megvilágítást méri, és beállítja a fényerőt. Éjszaka még a legkisebb fényerő is majdnem sok, nappal meg az árnyékos szoba ellenére maximumot állítottam be, mert ez gyengén látóknak segítség, bár engem már enyhén vakít!
A dobozt nyáklemezból csináltam. Levágtam a megfelelő méretű lapokat, és az éleknél simán összeforrasztottam. A fenéklemezt, ahol szerelhető a belseje, a doboz oldalfalához forrasztott anyacsavarokhoz lehet rögzíteni. Régi bevált technika málam. Az óra méret így 14x4x3.5 cm lett. Kellett még csiszolni, festeni. A doboz tartott legtovább!
Néhány fotó a kivitelről:
Összeszerelve:
A mátrix kijelző saját bontásból származik, utólag forasztgattam össze a négy tagot. Eredetileg az időjárás állomásom első verziójában szolgált nyugdíjazásáig! A doboz tetejére került egy nyomógomb, ez már a képen nem látszik, mert beleolvad a fekete színbe. Azért a doboz tetejére került, hogy könnyű legyen kitapogatni szükség esetén.
Az óra setup lehetőségekkel is fel lett vértezve! Be lehet állítani a dátumot, az időt! Beállítható, hogy automatikusan álljon-e át a nyári óraállításkor az idő (állítólag megszüntetik az óraállítást)! Beállítható a hangszóró hangereje. A hangszóró bármi lehet, nálam egy Genius számítógép hangszóró passzív része, amit az ócskapiacon vettem 200Ft-ért. Pont jó!
Beállítható a kezdő időpontja (órája) az óránkénti hangbemondásnak. Ugyanígy beállítható a záró időpont is. Pl. ha a kezdetet 8-ra állítom, a végét meg 20-ra, akkor csak reggel 8 és este 8 között mondja óránként az időt. Az óránkénti bemondásnál értelem szerűen csak az órát mondja (pl. tizennégy óra). Ez azonban annyira rövid időnként, hogy sokszor lemaradtam a szövegről, csak azt halottam, hogy megint morog valamit az óra. Ezért feleségem ötlete alapján az óránkénti bemondás előtt egy szignál hangzik el. Pont olyan lett, mint egy pályaudvar hangosbemondója! A szignál a Windows egyik beépített hangja lett. Nem vacakoltam sokat a keresgéléssel, ott volt a gépen!
Ha a nyomógombot megnyomják, akkor két-két másodperces időtartamig megmutatja a dátumot, a hét napját, és a hőmérsékletet. Tapasztalatom szerint a zárt dobozban meleg van, így a DS3231 hőmérője egy-két fokkal többet mutat. Kár!
A nyomógomb megnyomásakor a kijelzőn történő „mutogatással” együtt bemondja a pontos időt, az aktuális dátumot évek nélkül (csak hónap és nap), valamint a hét napját. Itt nincs szignál, aki megnyomja, tudja, hogy az óra beszélni fog, tehát figyel.
Beállítható még, hogy férfi vagy női hang mondja be az időt. A nő Google a férfi Word. Nem túl kellemes a hangzás! Sokat lehetne javítani, mert pl. az óránkénti bemondáshoz egyben fel tudná olvasni mindkét program az időt szépen hangsúlyozva, de ennyi munkát nem szántam rá. Mindent újra felvenni és audió editorral összeszerkeszteni elég sok idő. Ha majd valaki sorozatban gyártja az órát, akkor érdemes lesz ezzel vacakolni. Vagy bele kell tenni egy 50.000Ft-os számítógépet hangszintetizátorral, és az tökéletes lesz. Nekem 5000Ft-os költségvetésből erre tellett!
A setup folyamat a nyomógomb 5 másodpercig tartó megnyomásával indul. Villogni kezd a setup felirat, ekkor rövid gombnyomásra mutatja az első beállítható adatot, az évet. Az évszám utolsó két jegye vibrálva villog, ezzel mutatja, hogy most ezt lehet beállítani. Ha ekkor hosszan nyomom a gombot, akkor az évszám felfelé számol egészen 2050-ig, ott visszaugrik 2021-re és újra felfelé számol. Az aktuális évnél el kell engedni a nyomógombot. Rövid gombnyomásra jön a következő adat, a hónap. Hosszú gombnyomással számolgatunk januártól decemberig. És így megy tovább minden dátum és idő és egyéb paraméter beállítása. Az értékek a következő adat megjelenésekor azonnal tárolásra kerülnek a DS3231 chip-ben, illetve az eeprom-ban. Néhány fotó a setup képernyőkről (sorrendben)
Mivel a képeken nem látható, hogy a nyomógomb elengedett állapotában mi villódzik igen gyorsan (vibrál), bekarikáztam az érintett képernyő részletet.
Így néz ki az óra a padlásról begyűjtött régi Philips hangfalon, amivel igen jól szólt!
Ezzel a hangfallal túl sok volt a basszus, ezért nagyon jót tett a Genius dobozhang az érthetőségnek. Sajnos a Géniusz hangszóróval még küzdök, mert az 4 ohm-os, és ha rádugom az mp3 hangszóró kimenetére, akkor nem indul el az óra bekapcsoláskor. Utólag rádugva működik! A Philips 8 ohm-os, ezért ez fejlesztéskor nem okozott gondot. Lehet, hogy kerítenem kell egy 4 ohm körüli soros ellenállást a Geniusz hangszóróba, és ezzel oldom meg a problémát. Amúgy sem kell nagy hangerő, 25-ös hangerő szinten a 30-ból már szinte túl hangos!
Közben a fenti problémára is meg lett a megoldás! Nem a 4 ohm-os Genius hangszóró a hibás. Az 5V-os tápot egy selejtezett Nokia telefon töltője szolgáltatta. Ez még az ógörög korból való, és csak 400mA áramot adott. Kicseréltem egy 2A-es modernebb darabra, és már bekapcsol az óra a hangfallal. Sokat szívok mostanában a tápegységekkel, még ha jók, akkor is!
És végül az alaposan felkommentezett forráskód! Ez egy hosszabb 1500 soros program. Itt most egybemásoltam, de fejlesztéskor már az Arduino IDE lapjain tartom logikusan szétvágott darabokban. A hozzám hasonló kezdőknek adnám át praktikus tanácsként, hogy a forrást szedjék szét darabokra, így könnyebb navigálni a függvények között. Ehhez az IDE szerkesztőjében az állománynév sorában a jobb szélen található egy kicsike „pöcök”, ott lehet új füzetlapot nyitni. Ezért kerül egy megkezdett program forrás állomány mindig alkönyvtárba, hogy abban legyenek a forrás állományok, amiket így létrehozunk! AZ alábbi képen látható, hogy néz ki a részekre szedett forrás lapokra bontva. Az említett pöcök a lap fülekkel egy sorban jobbra, a képen épp rákattintottam:
/*********************************** * Ledmatrix kivezetések bekötése: * * D3 - CS * * D4 - CLK * * D5 - DIN * * D2 - Nyomógomb * * D6 - Mp3 busy jel bemenet * * D10 - RX * * D11 - TX * * A0 - TEKT4400 fototanzisztor * ************************************/ #include <EEPROM.h> #include <Wire.h> #include "Arduino.h" #include "SoftwareSerial.h" //használunk egy szoftveres soros portot, hogy megmaradjon a valódi soros port a fejlesztéshez, hibakereséshez #include "DFRobotDFPlayerMini.h" //MP3 lejátszó programkönyvtára SoftwareSerial mySoftwareSerial(10, 11); // RX, TX //beállítjuk a szoftveres soros portot, csak a TX kimenetet fogjuk használni belőle, mert az mp3 lejátszó nem küld semmit DFRobotDFPlayerMini myDFPlayer; //myDFPlayer néven fogunk hivatkozni erre az mp3 lejátszó példányra //Az óra használatához szükséges dolgok #define CLOCK_ADDRESS 0x68 //a modulon található óra IC címe az I2C buszon. struct dat_ido { // a dátum és idő beállításához illetve kiolvasásához létrehozunk egy struktúrát dat_ido néven (változó típus) int ev; //év tárolása a struktúrában (évszázadokkal kell megadni, illetve így kapjuk meg az eredményt a dátum kiolvasásakor) byte ho; //ho tárolása a struktúrában byte nap; //nap tárolása a struktúrában byte het_napja; //hét napja a struktúrában (1-hétfő....7-vasárnap) byte ora; //óra tárolása a struktúrában (24 órás üzemmódot fogunk használni) byte perc; //perc tárolása a struktúrában byte masodperc; //másodperc tárolása a struktúrában bool pontos; //ez a változó fogja megadni az IDO kiolvasását követően, hogy pontos-e a kiolvasott időpont //(ha elemes működés közben leáll a DS3231 oszcillátora, akkor az "OSF" flag bebillen, és ezt olvassuk ki }; dat_ido ds3231; //létrehozzuk az dat_ido típusú változónkat DS3231 változó néven const byte font[] = { //karakterképek 8x8 bites karaktertérképen balra rendezve (utolsó két oszlop üres) //minden byte egy-egy sor egymás alatt, legelső a legfelső 120,204,204,204,204,204,204,120, //0 karakterkép 48,112,48,48,48,48,48,120, //1 karakterkép 120,204,12,24,48,96,192,252, //2 karakterkép 120,204,12,120,12,12,204,120, //3 karakterkép 28,60,108,204,204,252,12,12, //4 karakterkép 252,192,192,248,204,12,204,120, //5 karakterkép 56,96,192,248,204,204,204,120, //6 karakterkép 252,204,12,24,48,96,192,192, //7 karakterkép 120,204,204,120,204,204,204,120, //8 karakterkép 120,204,204,124,12,12,204,120, //9 karakterkép 0,0,0,0,0,0,0,0}; //üres karakterkép const byte honap_font[]= { //A hónap rövidített feliratai 8x16 képpontban (egy sor két egymást követő byte) 0,0,51,34,20,178,20,178,23,170,20,166,148,166,100,162, //JAN 0,0,238,206,136,169,136,169,204,206,136,169,136,169,142,201, //FEBR 0,128,136,28,217,146,170,82,138,92,139,210,138,82,138,82, //MÁR 32,0,7,56,100,164,148,164,151,56,244,36,148,36,148,36, //ÁPR 0,128,136,6,217,130,170,66,138,66,139,194,138,82,138,76, //MÁJ 1,0,48,34,20,178,20,178,20,170,20,166,148,166,99,34, //JÚN 1,0,48,32,20,160,20,160,20,160,20,160,148,160,99,60, //JÚL 0,0,100,152,148,164,148,160,244,172,148,164,148,164,147,28, //AUG 0,0,111,118,129,69,129,69,66,118,36,68,40,68,207,116, //SZEP 0,0,100,190,148,136,149,8,150,8,149,8,148,136,100,136, //OKT 0,0,137,145,202,81,202,81,170,81,154,74,154,74,137,132, //NOV 0,0,231,152,148,36,148,32,151,32,148,32,148,36,231,152, //DEC 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //üres const byte het_font[]= { //hét napjainak rövidített feliratai 8x16 képpontban 1,0,144,62,151,136,148,8,247,8,148,8,148,8,151,136, //HET 0,0,151,184,148,36,164,36,199,36,164,36,148,36,151,184, //KED 0,0,119,188,128,160,128,160,97,56,18,32,20,32,231,188, //SZE 0,36,99,128,148,36,132,36,131,36,128,164,144,164,103,24, //CSÜ 1,0,224,34,151,178,148,50,231,42,132,38,132,38,135,162, //PÉN 0,0,119,152,128,164,128,164,97,36,18,36,20,36,231,152, //SZO 0,0,137,142,138,80,138,80,139,204,82,66,82,66,34,92, //VAS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //üres const byte start_font[]= { //START felirat 8x32 képpontban 0,0,0,0,115,231,57,240,128,136,164,64,128,136,164,64, 112,143,184,64,8,136,164,64,8,136,164,64,112,136,164,64}; const byte setup_font[]= { //SETUP felirat 8x32 képpontban 0,0,0,0,115,239,162,240,130,2,34,136,130,2,34,136, 115,194,34,240,10,2,34,128,10,2,34,128,115,226,28,128}; const byte aut_font[]= { //NYÁRI: felirat 8x24 képpontban, és utolsó kijelzőn BE,KI felirat 0,0,0,0,0,0,16,0,231,132,0,0,0,148,148,149,38,64,148,164, 213,85,80,231,196,242,118,64,148,164,178,85,80,148,148, 146,85,64,231,148}; const byte ev_font[]= { //az év beállításhoz használt felirat 8x24 képpontban 0,49,128,64,74,64,0,10,64,212,10,64, //ÉV:20 149,18,64,212,34,64,137,66,64,200,121,128}; const byte hang_font[]= { //a hangerő beállításához használt felirat 8x24 képpontban 16,1,0, 48,16,128, 240,136,64, 244,68,64, //Hangszóró ikon hanghullámokkal 244,68,64, 240,136,64, 48,16,128, 16,1,0}; const byte bsta_font[]= { //az óránkénti idő bemondás első időpontja (órája) 0,0,0, 16,192,0, 52,193,0, 242,193,128, //hangszóró ikon faltól induló nyíl 242,255,192, 242,193,128, 52,193,0, 16,192,0}; const byte bsto_font[]= { //az óránkénti idő bemondás utolsó időpontja (órája) 0,0,0, 16,0,192, 52,4,192, 242,6,192, //hangszóró ikon falnak ütköző nyíl 242,255,192, 242,6,192, 52,4,192, 16,0,192}; const byte ff_no_font[]= { //hangszóró ikon, férfi és nő jel, utolsó kijelzőn FF,NŐ felirat 0,0,0,0,5, 16,112,16,0,5, 52,136,32,0,0, 242,137,192,238,146, 242,82,32,136,213, 242,34,32,204,245, 52,114,32,136,181, 16,33,192,136,146}; const byte cfok_font[]= {0,70,169,72,8,8,9,6,}; //celsius fok karakterképe 8x8 képpontban const byte ho_tabla[] { //Március utolsó vasárnapjának dátuma és október utolsó vasárnapjának dátuma 2021-2050-ig 2 byte-on 28,31,27,30,26,29,31,27,30,26,29,25,28,31,26,29, 25,28,31,27,30,26,28,31,27,30,26,29,25,28,30,26, 29,25,28,31,27,30,25,28,31,27,30,26,29,25,27,30, 26,29,25,28,31,27,29,25,28,31,27,30 }; //A MAX7219 chip paramcsai const byte decode_mode=9; //MAX7219 beállításakor a decode mód regiszter címe const byte scan_limit=11; //MAX7219 beállításakor scan imit regiszter címe const byte intenzity=10; //MAX7219 beállításakor intenzitás regiszter címe const byte shut_down=12; //MAX7219 beállításakor shut down mód regiszter címe const byte disp_test=15; //MAX7219 beállításakor a disp test regiszter címe //A MAX7219 chip felé menő kivezetések const byte adat_kimenet=5; //MAX7219 adat in bemenetének vezérlésére szolgáló Arduino kimenet száma const byte cs_kimenet=3; //MAX7219 CS bemenetének vezérlésére szolgáló Arduino kimenet száma const byte clk_kimenet=4; //MAX7219 CLK bemenetének vezérlésére szolgáló Arduino kimenet száma const byte idozites=10; //Késleltetetés ideje mikrosec-ben a MAX7219 adat beírás bitjei között const byte sw=2; //Fénymérés TEPT4400 fotó tranzisztorral. A rövidebb láb a kollektor, ez megy a tápfesz 5V-ra //A hosszabb láb az emitter, ez egy 1Kohm ellenálláson keresztül megy a földre. Az emitterből //vezetem a mérendő feszültséget az A6 bemenetre. Sötétben a mért fesz 0 körül, napsütésben //1000 körül. Megvilágítva nyit ki a tranzisztor és felhúzza a jelvezetéket a tápfeszre. //A méréskor a tápfeszt veszem referenciának! Ez a program egy árnyékos szobában fog órát //működtetni, ezért soha nem nyit ki a tranzisztor, mert nem süt rá a nap. Ezért 0 és //200-300 körüli értékek fordulnak elő. Sötétedéskor 0 és 10 körüli értékek fordulnak elő //ezért nagyon nem lineárisan lettek elosztva a fényerő szintek. int mert_fenyero[10]={0,0,0,0,0,0,0,0,0,0}; //az utolsó 10 mért fényerő értéke int fenyertek=0; //az utolsó 10 mért fényerő érték átlaga int pill_fenyero,elozo_fenyero; byte aut_atall=1; byte hang; //hangerő értéke az idő és dátum kimondásakor byte bsta; //óránkénti bemondás első időpontja (órája) byte bsto; //óránkénti bemondás utolsó időpontja (órája) bool ff_no=0; //ha ennek értéke 1, akkor az mp3 által lejátszandó file indexéhez 95-öt hozzáadok, mert onnan kezdődnek ugyanazok a szavak, csak férfi hangon bool szoko_ev; //szökőév jelzéséhez float homerseklet; long ido_tmp=millis(); //egy másodperces óra lekérdezéshez segédváltozó, óra setup alatt az állított érték villogtatásához long ido_tmp1=millis(); bool pont=0; bool ora_setup=0; //ha hosszú ideig nyomjuk a gombot, akkor az óra átmegy setup módba, ekkor értéke 1 byte setup_fazis=0; //az óra beállítás fázisait jelzi 0-év,1-hó,2-nap,3-óra,4-perc,5-aut.nyári átállás, //6-hangerő, 7-bemondást kezdő időpontja (órája), 8-bemondás záró időpontja (órája), 9-Férfi női hang bool sw_allapot1; //nyomógomb állapot ciklus elején byte lassit; //segédváltozó ahhoz, hogy setup-ban a nyári óraállítás BE illetve KI felirata ne váltson olyan gyorsan long sw_time; //nyomógomb lenyomás idejének figyeléséhez segédváltozó bool sw_allapot=0; //nyomógomb lenyomott állapota esetén 1 long vissza_time; //visszakapcsolás óra kijelzés üzemmódba segédváltozója (20 sec időzítéséhez használom) bool ism_tilt1=0; //1-es gombon a hosszan nyomva tartás ismétlésének akadályozására. Akkor lesz 1, ha még nem engedte el a nyomógombot, de már egyszer letelt a 800msec byte uzemmod=0; //nyomógomb rövid megnyomásakor lezajló folyamat követésére. 0-időkijelzés,1-dátum kijelzés,2-hőmérséklet kijelzés byte szamol=0; //ezzel lassítom az üzemmód váltást, mert egy adatot 2 sec ideig akarok kint tartani, de a ciklus másodpercenként fut byte szo[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //ebben a tömbben gyűjtöm össze a kimondandó szó részek indexeit. //Maximum 15 állományt fogunk tudni lejátszani, ha már nincs több lejátszandó, //akkor a következő tömbelem 0. Ha van 15 lejátszandó, akkor az index érték lesz //15, és innen tudjuk, hogy le kell állítani a lejátszást byte index=0; //ez mondja meg, hogy éppen melyik állományt kell lejátszani. Ha értéke 15, akkor //nincs lejátszás illetve már befejeztük. 15-re állítjuk az utolsó lejátszott állomány esetén is. //A lejátszás indításakor 0-ra kell állítani a kezd nevű változót pedig 1-re. long varakozas=millis(); //amikor elindítom a lejátszást, a lejátszón a busy jelvezeték nem vált azonnal 1-re, illetve //rövid ideig még változik is. Ezért várok egy kis időt, amíg figyelni kezdem. Ehhez kell! //ezek a konstansok csak a program könnyebb értelmezése miatt kellenek const byte januar=60,elso=29,honap=87,hetfo=53,ora=84,perc=85,szunet=95; const byte minusz=45,nulla=1,egy=2,ketto=3,tiz=11,husz=12,szaz=20,tizen=42,huszon=43,ezer=46,millio=47,milliard=48,egesz=49,ezred=50,szazad=51,tized=52; byte bemond_fazis=0; long setup_kilep=millis(); void setup() { Wire.begin(); Serial.begin(115200); pinMode(6,INPUT); //ide kötöttem az mp3 lejátszó busy jelét mySoftwareSerial.begin(9600); //inicializáljuk a szoftveres soros portot if (!myDFPlayer.begin(mySoftwareSerial)) { //mp3 lejátszó inicializálása. Ha nem sikerült, akkor 0 //Serial.println("MP3 player hiba!"); //valami hiba volt, nincs jól csatlakoztatva az mp3 lejátszó a 10 és 11-es kimenetekhez, vagy nincs benne sd kártya //mivel a soros port visszatérő ágát már be sem kötöttem (Arduino RX, ebben a programban 10-es kivezetés), ezért itt már //nem igazán várhatok valós hibajelzést :-), ezért nem is kell ez a sor } //Serial.println("MP3 player OK!"); //mp3 lejátszó kész a működésre, csak fejlesztéskor kell ez a sor pinMode(adat_kimenet,OUTPUT); //MAX7219 adatbemenete felé menő kimenet pinMode(cs_kimenet,OUTPUT); //MAX7219 CS bemenete felé menő kimenet pinMode(clk_kimenet,OUTPUT); //MAX7219 órajel bemenet felé menő kimenet digitalWrite(cs_kimenet,1); //a max7219 CS bemenete 1-en van, amikor nincs kiválasztva, és nem kommunikálunk vele //MAX7219 alapértelmezett beállításai matrix_setup(disp_test,0); //Display test kikapcsolva (minden led világítana, ha nem kapcsoljuk ki) matrix_setup(decode_mode,0); //Decode mód kikapcsolása matrix_setup(scan_limit,7); //Scan limit regiszter beállítása (8 számjegy kijelzését kapcsoljuk be) matrix_setup(shut_down,1); //Shutdown kikapcsolva matrix_setup(intenzity,15); //Intenzitás maximum //Kijelző törlése for (byte sor=0;sor<8;sor++) { //Minden kijelzőn egyszerre írjuk ugyanazt a led sort digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,0); kileptet(sor+1,0); kileptet(sor+1,0); kileptet(sor+1,0); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve //ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } pinMode(sw,INPUT); //nyomógomb bemenete digitalWrite(sw,HIGH); //felhúzó ellenállás be //************* Legelső óra beállítás és eeprom tartalom feltöltés ************************************/ //EEPROM.put(0,(byte)1); //alapértelmezetten be van kapcsolva az automatikus nyári óraállítás //(és november utolsó vasárnapján a kikapcsolása) //EEPROM.put(1,(byte)1); //az adott napon épp van nyári időszámítás //EEPROM.put(2,(byte)15); //hangerő az időpont kimondáskor //EEPROM.put(3,(byte)7); //óránkénti idő kimondás kezdő időpontja (órája) //EEPROM.put(4,(byte)18); //óránkénti idő kimondás záró időpontja (órája) //EEPROM.put(5,(byte)1); //Alapértelmezetten férfi hangon beszéljen az óra //figyelni kell, hogy a beállított dátumon épp van-e nyári időszámítás, és azzal szinkronban kell //beállítani az eeprom tartalmat az 1-es eeprom címen //ds3231.masodperc=30; //ds3231.perc=59; //ds3231.ora=8; //ds3231.het_napja=6; //ds3231.nap=28; //ds3231.ho=5; //ds3231.ev=2022; //setTime24(); //óra beállítása: négyszög kimenő jelet kikapcsolja, //32Khz-s kimenetet kikapcsolja és 24 órás üzemmódot állít be. //Beállítja a pontos időt a fenti változók értékével //*************************************************/ analogReference(DEFAULT); //A tápfeszt veszi referenciának (5V) //eepromből áttültjük memória változókba az alapvető működési paramétereket EEPROM.get(0, aut_atall); //automatikus nyári óraállítás EEPROM.get(2, hang); //bemondási hangerő EEPROM.get(3, bsta); //időbemondás kezdő órája EEPROM.get(4, bsto); //időbemondás záró órája EEPROM.get(5, ff_no); //férfi vagy női hang //bekapcsoláskor megmutatunk minden paramétert // matrix_setup(intenzity,14); //Intenzitás maximum aut_ir(aut_atall,0); delay(1000); hang_ir(hang,0); delay(1000); bsta_ir(bsta,0); delay(1000); bsto_ir(bsto,0); delay(1000); ff_no_ir(ff_no,0); delay(1000); homeresklet_ir(getTemperature()); delay(1500); getTime24(); if (aut_atall==1) { atallas_ell(); } ev_ir(ds3231.ev-2000,0); delay(1500); elozo_fenyero=analogRead(A0); myDFPlayer.volume(hang); //Hangerőt beállítjuk állítjuk (0-30) } void loop() { bemond_vezerles(); //ez a függvény indítja a bemondást, ha index változó értékét 0-ra állítottuk //és a szo[] tömböt feltöltöttük a bemondandó tartalommal, nincs benn delay //a loop fut tovább if (index==15 and ora_setup==0) { //amikor nyomógombot nyom, és nincs setup mód, és éppen nem is mond semmit, //akkor elindítjuk az aktuális idő, aztán pedig a dátum és a hét napjának bemondását //Szintén nincs benne delay, éa a loop fut tovább if (bemond_fazis==1 or bemond_fazis==2) {idobemondas();} //egy rövid nyomógomb megnyomás a bemond_fazis változót 1-re álltja, és //ekkor indul a pillanatnyi idő és dátum bemondása if (bemond_fazis==3) {datumbemondas();} } //itt jönnek a nyomógomb ellenőrzés lépései //rövid (kisebb mint 700msec megnyomás indítja a dátum és hőmérséklet kijelzést, és a bemondást, ha épp a start és stop időpontok között vagyunk //Hosszú megnyomás setup módban (nagyobb mint 800msec) lépteti az éppen aktuális adat értékét a beállítandó adat kiválasztásához (év, hónap, nap stb.) //Hosszú megnyomás ha még nem vagyunk setup módban (nagyobb mint 5sec), elindítja a setup módot sw_allapot1=digitalRead(sw); if (sw_allapot1==LOW and sw_allapot==0) { //megnyomtuk az 1-es gombot, indul az időzítés, hogy megtudjuk rövid vagy hosszú lenyomás lesz ism_tilt1=0;sw_allapot=1;sw_time=millis(); vissza_time=millis(); } //ha hosszan nyomva tartotta a gombot, valamit csinálni kell amikor elengedte if ((ora_setup==0 and sw_allapot1==LOW and sw_time+5000<millis() and sw_allapot==1 and ism_tilt1==0) or //ha még nem vagyunk setup módban, akkor 5 sec után belépjünk (ora_setup==1 and sw_allapot1==LOW and sw_time+800<millis() and sw_allapot==1 and ism_tilt1==0)) //ha már setup-ban vagyunk, akkor 0.8 sec után az adat értékének léptetése indul { //itt következik annak levizsgálása, hogy mennyi ideig tartottuk nyomva hosszan a nyomógombot setup_kilep=millis(); //itt épp egy gombnyomásnak van vége, ezért innen indítom a 20 másodperces tétlenségi kilépést a setup módból if (ora_setup==0) { //nem voltunk setup módban, most az következik, biztos ami biztos, újra átolvassuk a paramétereket az eepromból EEPROM.get(0,aut_atall); EEPROM.get(2, hang); EEPROM.get(3, bsta); EEPROM.get(4, bsto); EEPROM.get(5, ff_no); } if (ora_setup==1) { //ez a setup mód, akkor lesz ora_setup=1, ha már egyszer benne voltunk ebben az if-ben //a következő loop() ciklusban vált 1-re, mert előtte még 0, és csak a setup előkészítése történik ido_tmp1=millis()-700; //azért, hogy a következő do ciklus belső feltétele biztosan igaz legyen, mikor bele lépünk a ciklusba lassit=0; //ezzel lassítom az automatikus időszámítás értékének váltását. 700msec-enként váltana az érték, //ami tül gyors, és ezért nehéz a setup-ban kiválasztani a szükséges állapotot, így csak minden második //ciklusban változtatom. A többinél nem kell, mert ott számlálókat léptetek, ott ez lenne lassú. do { sw_allapot1=digitalRead(sw); if (ido_tmp1+700<millis()) { //ha folyamatosan nyomjuk a gombot, akkor 700msec időnként kerülünk be az if ágba. //az éppen aktuális paramétert 700msec-enként növeljük (egy limit után újra 0 lesz) ido_tmp1=millis(); switch (setup_fazis) { case 0: //ebben a fázisban kiírjuk a setup feliratot, hogy tudja a kezelő, mi következik setup_ir(0); break; case 1: //setup felirat után megnyomta röviden a gombot, villogtatni fogjuk az évet, mert azt lehet beállítani ds3231.ev++;if (ds3231.ev>2040) {ds3231.ev=2021;}; ev_ir(ds3231.ev-2000,0); break; case 2: //év beállítás után megnyomta röviden a gombot, megjelenítjük a hónapot és a napot, villogtatni fogjuk az hónapot, mert azt lehet beállítani ds3231.ho++;if (ds3231.ho>12) {ds3231.ho=1;}; dat_ir(ds3231.ho,ds3231.nap,0,0); break; case 3: //hónap beállítás után megnyomta röviden a gombot, villogtatni fogjuk az napot, mert azt lehet beállítani ds3231.nap++; szoko_ev=szokoev(ds3231.ev); if ( ((ds3231.ho==1 or ds3231.ho==3 or ds3231.ho==5 or ds3231.ho==7 or ds3231.ho==8 or ds3231.ho==10 or ds3231.ho==12) and ds3231.nap>31) or ((ds3231.ho==4 or ds3231.ho==6 or ds3231.ho==9 or ds3231.ho==11) and ds3231.nap>30) or (szoko_ev==0 and ds3231.ho==2 and ds3231.nap>28) or (szoko_ev==1 and ds3231.ho==2 and ds3231.nap>29) ) {ds3231.nap=1;}; dat_ir(ds3231.ho,ds3231.nap,0,0); break; case 4: //hónap és nap beállítás után megnyomta röviden a gombot, megjelenítjük az órát és a percet, villogtatni fogjuk az órát, mert azt lehet beállítani ds3231.ora++;if (ds3231.ora>23) {ds3231.ora=0;}; ido_ir(ds3231.ora,ds3231.perc,1,0,0); break; case 5: //óra beállítás után megnyomta röviden a gombot, villogtatni fogjuk a percet, mert azt lehet beállítani ds3231.perc++;if (ds3231.perc>59) {ds3231.perc=0;}; ido_ir(ds3231.ora,ds3231.perc,1,0,0); break; case 6: //óra és perc beállítás után megnyomta röviden a gombot, megjelenítjük a nyári óraállítást, villogtatni fogjuk a a KI illetve BE feliratot, mert azt lehet beállítani aut_ir(aut_atall,0); lassit++; if (lassit==2) { if (aut_atall==0) {aut_atall=1;} else {aut_atall=0;} aut_ir(aut_atall,0); lassit=0; } break; case 7: //Automatikus nyári óraállítás beállítás után megnyomta röviden a gombot, megjelenítjük a hangerő értéket, villogtatni fogjuk a hangerő értékét, mert azt lehet beállítani hang++; if (hang>30) {hang=1;} hang_ir(hang,0); break; case 8: //Hangerő beállítás után megnyomta röviden a gombot, megjelenítjük a start időpontot, villogtatni fogjuk az óra értékét, mert azt lehet beállítani bsta++; if (bsta>23) {bsta=0;} bsta_ir(bsta,0); break; case 9: //Sttart időpont beállítás után megnyomta röviden a gombot, megjelenítjük a stop időpontot, villogtatni fogjuk az óra értékét, mert azt lehet beállítani bsto++; if (bsto>23) {bsto=bsta;} bsto_ir(bsto,0); break; case 10: //Stop időpont beállítás után megnyomta röviden a gombot, megjelenítjük a férfi és nő állapotot, villogtatni fogjuk az FF illetve NŐ feliratot, mert azt lehet beállítani if (ff_no==0) {ff_no=1;} else {ff_no=0;} ff_no_ir(ff_no,0); break; case 11: ora_setup=0;uzemmod=0;sw_allapot1=1; break; } } } while (sw_allapot1==0); } if (setup_fazis==11) {sw_allapot=1;} if (uzemmod==0) {ora_setup=1;} } if (sw_allapot1==HIGH and sw_allapot==1) { //már nem nyomja az 1-es nyomógombot setup_kilep=millis(); //itt épp egy gombnyomásnak van vége, ezért innen indítom a 10 másodperces tétlenségi kilépést a setup módból sw_allapot=0; if (millis()-sw_time<800 and millis()-sw_time>20) { //ha 20ms-nél tovább nyomta, de kevesebb mint 800msec-ig, akkor kijelzést váltunk //a dátumra és a hőmérsékletre, illetve ha setup módban vagyunk akkor a következő //beállítandó adatra if (ora_setup==0) { //röviden nyomta és nem volt setup módban, akkor indítjuk a dátum és hőmérséklet kijelzést bemond_fazis=1; //ezzel elindul az időbemondás, és azt követően a dátumbemondás uzemmod=uzemmod+1; //sorban jelezzük ki az adatokat, és ez a változó vezéreli, hogy éppen melyiket szamol=0; ido_tmp=ido_tmp-1000; if (uzemmod>3) {uzemmod=0;} //minden adatot kijeleztünk, felvesszük a nyugalmi helyzetet, az időpont kijelzést } if (ora_setup==1) { //setup módban voltunk és rövidet nyomott, jön a következő adat, vagy ha utolsón álltunk, //akkor az értékek beírása a DS3231 chip-be és az eeprom-ba //ezt még itt fejlesztem if (setup_fazis<6) { //beállítjuk az időt a DS3231 chip-ben is ds3231.het_napja=datum_hetnapja(ds3231.ev,ds3231.ho,ds3231.nap); setTime24(); } if (setup_fazis==6) { //beírjuk az automatikus nyári óraállítás paraméter értéket az eeprom-ba EEPROM.put(0,aut_atall); } if (setup_fazis==7) { // beírjuk a hangerő paraméter értéket az eeprom-ba EEPROM.put(2,hang); myDFPlayer.volume(hang); //Hangerőt beállítjuk állítjuk (0-30) } if (setup_fazis==8) { // beírjuk a bemondás start idő paraméter értéket az eeprom-ba EEPROM.put(3,bsta); } if (setup_fazis==9) { // beírjuk a bemondás stop idő paraméter értéket az eeprom-ba EEPROM.put(4,bsto); } if (setup_fazis==10) { // beírjuk a férfi-nő paraméter értéket az eeprom-ba EEPROM.put(5,ff_no); setup_fazis=-1;ora_setup=0; } setup_fazis++; } } } //ha nem vagyunk setup módban, akkor üzemmod változó mondja meg, hogy mit jelzünk ki //uzemmod=0 - időkijelzés //uzemmod=1 - dátum kijelzés //uzemmod=2 - hét napjának kijelzése //uzemmod=3 - hőmérséklet kijelzés if (ido_tmp+1000<millis() and ora_setup==0) { ido_tmp=millis(); fenyero_beallitas(); //fénymérés és fényerő beállítás getTime24(); orankenti_bemondas(); //ellenőrzi, hogy éppen egész óra van-e, és ha igen, akkor elindítja az idő bemondását if (uzemmod==0) { if (aut_atall==1) { atallas_ell(); } if (pont==0) {ido_ir(ds3231.ora,ds3231.perc,1,0,0);pont=1;} else {ido_ir(ds3231.ora,ds3231.perc,0,0,0);pont=0;} } if (uzemmod==1) { szamol++; if (szamol>2) {uzemmod=2;szamol=0;} dat_ir(ds3231.ho,ds3231.nap,0,0); } if (uzemmod==2) { szamol++; if (szamol>2) {uzemmod=3;szamol=0;} het_ir(ds3231.nap,ds3231.het_napja,0); } if (uzemmod==3) { szamol++; if (szamol>2) {uzemmod=0;} homeresklet_ir(getTemperature()); } } //Ha setup módban vagyunk, akkor a setup_fazis mondja meg, hogy éppen milyen adat látszik a képernyőn, //és ha épp nem nyomja folyamatosan a gombot, akkor villogtatjuk is gyorsan az éppen állítható adatot if (ora_setup==1) { if (setup_kilep+20000<millis() and setup_fazis<10) {ora_setup=0;uzemmod=0;sw_allapot1=0;setup_fazis=0;} //ha 20 másodpercig egy érték beállításán ácsingózik, akkor kilépünk a setup módból if (ido_tmp+25<millis()) { //ebbe az if-be 25msec-enként megyünk bele, és egyik alkalommal kijelezzük az éppen állított adatot, másik alkalommal meg nem ido_tmp=millis(); switch (setup_fazis) { case 0: //setup felirat jelzi a beállítás kezdetét if (pont==0) {setup_ir(0);pont=1;} else {setup_ir(1);pont=0;} break; case 1: //év beállításhoz villogtatás if (pont==0) {ev_ir(ds3231.ev-2000,0);pont=1;} else {ev_ir(ds3231.ev-2000,1);pont=0;} break; case 2: //hó beállításhoz villogtatás if (pont==0) {dat_ir(ds3231.ho,ds3231.nap,0,0);pont=1;} else {dat_ir(ds3231.ho,ds3231.nap,1,0);pont=0;} break; case 3: //nap beállításhoz villogtatás if (pont==0) {dat_ir(ds3231.ho,ds3231.nap,0,0);pont=1;} else {dat_ir(ds3231.ho,ds3231.nap,0,1);pont=0;} break; case 4: //óra beállításhoz villogtatás if (pont==0) {ido_ir(ds3231.ora,ds3231.perc,1,0,0);pont=1;} else {ido_ir(ds3231.ora,ds3231.perc,1,1,0);pont=0;} break; case 5: //perc beállításhoz villogtatás if (pont==0) {ido_ir(ds3231.ora,ds3231.perc,1,0,0);pont=1;} else {ido_ir(ds3231.ora,ds3231.perc,1,0,1);pont=0;} break; case 6: //Automatikus átállás nyári időszámításra beállításhoz villogtatás if (pont==0) {aut_ir(aut_atall,0);pont=1;} else {aut_ir(aut_atall,1);pont=0;} break; case 7: //Hangerő beállításhoz villogtatás if (pont==0) {hang_ir(hang,0);pont=1;} else {hang_ir(hang,1);pont=0;} break; case 8: //Bemondás start idő beállításhoz villogtatás if (pont==0) {bsta_ir(bsta,0);pont=1;} else {bsta_ir(bsta,1);pont=0;} break; case 9: //Bemondás stop idő beállításhoz villogtatás if (pont==0) {bsto_ir(bsto,0);pont=1;} else {bsto_ir(bsto,1);pont=0;} break; case 10: //A férfi vagy női hang kiválasztásához ff vagy no villogtatása if (pont==0) {ff_no_ir(ff_no,0);pont=1;} else {ff_no_ir(ff_no,1);pont=0;} break; } } } } void bemond_vezerles() { /*************************************************************************************************** * Az itt következő programrészek a szo[] tömbben összeállított szavak végig mondását végzik el * * amikor az index változót 0-ra állítjuk, akkor indul a szöveg kimondása. Közben a ciklus fut * * tovább, csak akkor vesz el egy kis időt a következő szöveg elindítása az mp3 lejátszón, amikor * * éppen befejeződött az előző szöveg lejátszása. A 6-os kivezetésen jelenik meg az mp3 lejátszó * * busy jele, ami mindaddig 0, amig épp lejátszik valamit. Mivel a busy jel nem megy le azonnal * * 0-ra lejátszás alatt, hanem változik néhányszor, a hang lejátszás indítása után kell egy kicsit * * várni, mielőtt figyelni kezdjük. * ***************************************************************************************************/ if (digitalRead(6)==1 and index<15 and millis()>varakozas+200) { //éppen szabad az mp3 lejátszó, lehet neki parancsot küldeni, ha van mit lejátszani és //eltelt legalább 200msec az utolsó indítás óta, mert a busy jelnek be kell állni 0-ra //a lejátszás indítása után, hogy figyelhessem mikor fejezte be a lejátszást (1-re vált) //Kezdetben 100msec várakozást használtam, de egyes szavak kimondását kihagyta, így 200msec-re //kelet növelni a várakozási időt. varakozas=millis(); //elindítjuk a várakozást, amivel várunk egy kicsit mielőtt a busy jelet ellenőriznénk (tranziensek //vannak a lejátszás elindítása után egy ideig a busy jelen) if (ff_no==1) {myDFPlayer.play(szo[index]+95);} //ha férfi, akkor 95-öt kel hozzáadni az index értékhez. 95 női hangú file van és 95 férfi else {myDFPlayer.play(szo[index]);} index++; if (szo[index]==0) { //ha az index értékhez tartozó tömbelem 0, akkor azt jelenti, hogy vége a lejátszható részleteknek index=15; //index=15 jelzi, hogy éppen nincs lejátszani való } } } void orankenti_bemondas() { if (ds3231.perc==0 and ds3231.masodperc==0 and ds3231.ora>=bsta and ds3231.ora<=bsto) { if (index==15 and ora_setup==0) { index=0;ido_szo(ds3231.ora,ds3231.perc,1); } } } void idobemondas() { if (bemond_fazis==1) {index=0;ido_szo(ds3231.ora,ds3231.perc,0);} bemond_fazis=2; if (index==15) {bemond_fazis=3;} } void datumbemondas() { index=0;datum_szo(0,ds3231.ho,ds3231.nap,1,ds3231.het_napja); bemond_fazis=0; } byte datum_hetnapja(int ev, byte ho, byte nap) /******************************************************************************* * Ez a függvény paraméterként várja egy dátumból az évet, hónapot és napot. * * Eredményként visszaadja a megadott dátum melyik napja a hétnek. A hét napja * * 1től 7-ig megadott érték, az 1 a hétfő, 7 a vasárnap. * *******************************************************************************/ { if (ho<1) { return 0;} //hónap napjainak száma nem lehet 0 if (ho!=1 & ho!=3 & ho!=5 & ho!=7 & ho!=8 & ho!=10 & ho!=12 & nap>31) { return 0;}; //több napot adtunk meg a hónapnak, mint amennyi napja van if (ho!=4 & ho!=6 & ho!=9 & ho!=11 & nap>30) { return 0;} //több napot adtunk meg a hónapnak, mint amennyi napja van if (ho==2) { //ha február van, ellenőrizni kell a szökőév szerinti napokat is if (szokoev(ev)) { //megmondja, hogy az adott év szökőév-e, mert ha igen, akkor a február 29 napos if (nap>29) { return 0;}} //szökőév, és több napot adtunk meg else { if (nap>28) { return 0;}} //nem szökőév, és több napot adtunk meg } int ho_napjai[]={0,31,59,90,120,151,181,212,243,273,304,334,365}; //Az évből eltelet hónapok napjainak száma halmozva havonként nem szökőévben long elmult_nap=ev*365; //Eddig ennyi napja volt az elmúlt éveknek a szökőévek figyelembevétele nélkül int elmult_szokonap=0; //Ebbe a változóba számoljuk ki majd a szökőévekből adódó plusz napok számát int szn4=(ev-1)/4; //Minden negyedik év szökőév (kivéve minden 100. év, de azt később levonjuk) //az aktuális évet nem szabad beleszámolni, mert az majd az aktuális év napjaiban benne lesz int szn100=(ev-1)/100; //minden 100. év nem szökőév, ezt majd levonjuk, kivéve minden 400. év, azt meg mindjárt hozzáadjuk int szn400=(ev-1)/400; //Minden 400. év mégiscsak szökőév elmult_szokonap=szn4-szn100+szn400; //így megkaptuk a szökőévekből adódó plusz napokat long akt_ev_nap=ho_napjai[ho-1]+nap; //Az eddig eltelt hónapok napjainak száma kiderül a tömbből, plusz hozzáadjuk az aktuális hónap napjait, ahol épp járunk //Ha az adott év szökőév, és már elmúlt február, akkor még egyet hozzá kell majd adni, mert a tömb egy nem szökőévre készült. long akt_ev_szokonap=0; if (ho>2) { if (szokoev(ev)) { akt_ev_szokonap++; // ha az aktuális éveben már elmúlt február, és az év szökőév, akkor még egy napot hozzá kell adni } } long napok=elmult_nap+elmult_szokonap+akt_ev_nap+akt_ev_szokonap; //és ezzel megkaptuk Jézus születésének napja óta eltelt napok számát if (napok%7==0) { return 7; //ha pont vasárnap van, akkor maradék nélkül osztható 7-el, ezért ilyenkor 7-et adunk vissza } else { return napok%7; //a maradék az adott hétben eltelt napok száma (hétfő az 1) } } bool szokoev(int ev) { /************************************************************************************ * Ez a függvény paraméterként várja az évet (pl. 2022) és visszaadja bool értékben * * hogy a paraméterben megadott év szökőév, vagy sem. * ************************************************************************************/ if (ev==0) { return false; //a 0.évet nem vesszük szökőévnek } bool szoko_ev=false; if (ev%4==0) { //ha néggyel osztva nem ad maradékot, akkor szökőév szoko_ev=true; if (ev%100==0) { //ha 100-al osztva nem ad maradékot, akkor nem szökőév szoko_ev=false; if (ev%400==0) { szoko_ev=true; //ha 400-al osztva nem ad maradékot, akkor mégis szökőév } } } return szoko_ev; } void atallas_ell() { /******************************************************************************************************** * Ez a függvény ellenőrzi, hogy elérkezett-e a nyári időszámítás átállásának időpontja, s ha igen, és * * Az óra nincs nyári időszámításban, akkor az aktuális órához hozzáad egyet. Ha elérkezett a nyári * * Időszámítás kikapcsolásának időpontja, akkor pedig levon az órából egyet. * * Nyári időszámítás bekapcsolása: minden év márciusának utolsó vasárnapján hajnali 2-kor át kell * * állítani az órát 3-ra. * * Nyári időszámítás kikapcsolása: minden év októberének utolsó vasárnapján hajnali 3-kor vissza * * kell állítani az órát hajnali 2-re. * * * * A függvény akkor is megoldja az óra állítást, ha az óra nem volt áram alatt, és a DS3231 óra chip * * épp elemről működött. A ds3231 magától nem tud nyári óraállítást végezni. * ********************************************************************************************************/ byte akt_marc_dat=ho_tabla[(ds3231.ev-2021)*2]; //a ho_tabla[] többől kiolvassuk, hogy az adott évben hányadikára esik március utolsó vasárnapja byte akt_okt_dat=ho_tabla[(ds3231.ev-2021)*2+1]; //a ho_tabla[] többől kiolvassuk, hogy az adott évben hányadikára esik október utolsó vasárnapja byte nyari=0; EEPROM.get(1,nyari); //ha nyari=1, akkor ebben a pillanatban az óra nyári időszámtás szerinti //állapotban van (egy órával később lesz éjfél, mint a valóságban) //Ez a programrész akkor fut le, ha az átállás pillanatában a program működik, vagyis a teljes szerkezet áram alatt van, és az Arduino-ban is fut a program. if (ds3231.ho==3 && ds3231.nap==akt_marc_dat && ds3231.ora>1 && nyari==0) { //ha márciusban az átállás napján még nincs a nyári időszámításban az óra, és elmúlt éjjel 2 óra, //előre állítjuk az órát egy órával, vagyis 2 órakor átállunk 3 órára, így az időpont egy órát késik //a tényleges csillagászati időhöz képest, a nap később kel. ds3231.ora=ds3231.ora+1; //órát előre állítjuk setTime24(); //beálltjuk az órát a hardverben is EEPROM.put(1,(byte)1); //eeprom-ba beírjuk, hogy nyári időszámitás üzemmódban vagyunk } //Ha az óraállítás pillanatában az óra IC elemről működött, és az Arduino-ban nem futott a program, akkor nem lett átállítva nyári időszámtásba. //Ezért ez első ezt követő bekapcsoláskor észre kell venni, hogy nyári időszámitásba kell állni, de ekkor bármilyen későbbi dátum lehet éppen. //Ha márciusban a dátum nagyobb mint az átállás dátuma, vagy a hónap már nagyobb mint március, de a hónap kisebb mint október, //vagy október de a nap kisebb mint az októberi átállás dátuma, és még nem vagyunk nyári időszámtásban, akkor előre kell állni egy órával. if (((ds3231.ho==3 && ds3231.nap>akt_marc_dat) || (ds3231.ho>3)) && (ds3231.ho<10 || (ds3231.ho==10 && ds3231.nap<akt_okt_dat)) && nyari==0) { EEPROM.put(1,(byte)1); //beírjuk az eeprom-ba a nyári üzemmódot ds3231.ora=ds3231.ora+1; //előre álltjuk az órát if (ds3231.ora==24) { //ha éppen 24 óra lenne a növelés után, akkor valójában egy napot kell hozzáadni és beállítani 0 órára ds3231.ora=0; //0 óra beállítása ds3231.nap=ds3231.nap+1; //növeljük a dátumot 1-el. ds3231.het_napja=ds3231.het_napja+1; //ha a napot növeltük, akkor a hét napját is kell if (ds3231.het_napja==8) { ds3231.het_napja=1;} //ha épp vasárnap volt, akkor hétfő következik a 8. nap helyett //Ha a nap növelése után az aktuális hónap utolsó napjánál 1-el nagyobb lett a nap, akkor hónapot is kell váltai és a nap=1 if ((ds3231.ho==3 || ds3231.ho==5 || ds3231.ho==7 || ds3231.ho==8 || ds3231.ho==10) && ds3231.nap>31) { ds3231.nap=1;ds3231.ho=ds3231.ho+1;} //31 napos hónap esetén a vizsgálat if ((ds3231.ho==6 || ds3231.ho==9) && ds3231.nap>30) { ds3231.nap=1;ds3231.ho=ds3231.ho+1;} //30 napos hónap esetén a vizsgálat } setTime24(); } //Ez a feltétele akkor lehet igaz, ha az őszi óraállításkor az Arduino áram alatt van és fut a program. if (ds3231.ho==10 && ds3231.nap==akt_okt_dat && ds3231.ora>2) { //Ha októberben a téli óraállítás pillanatában éppen nyári időszámításban van a program, //akkor egy órával visszaállítjuk az órát. ds3231.ora=ds3231.ora-1; //Az órát eggyel csökkentjük, 3 óra helyett újra 2 óra van, így a mutatott időpont megegyezik a csillagászati idővel setTime24(); //Beállítjuk a DS3231 IC-n is az új időpontot EEPROM.put(1,(byte)0); //megjegyezzük eepromban is, hogy téli időszámítás szerinti üzemmódban van az óra, //Egy következő ciklusban már nem fog újra lefutni ez a feltétel. } //Ha az óraállítás pillanatában az Arduino nincs áram alatt, és a DS3231 elemről működik, akkor nem történik meg az óra átállítás. //Ekkor az ezt követő első bekapcsoláskor kell az időt visszaállítani egy órával. Ha az óra által mutatott időpont a téli időszámítás //előtti pillanatban van (de a nyári időszámítás beállítási időpontja után) és az eeprom szerint nincs téli időszámításban, akkor kell //beállítani. Viszont ha a bekapcsolás éjfél és egy óra között történik, akkor nem visszaállítani kell az órát, hanem egy nappal előbbre //és 23 órára. Az egy nappal előbbre állítás miatt azonban akár hónapot is kell váltani, ha épp 1.-én ált a naptár. //Ha október van, de már elmúlt az óraállítás napja, vagy már elmúlt október, vagy már a következő évben vagyunk és március (nyári óraállítás //előtt, vagy már márciusban vagyunk de még nem jött el a nyári óraállítás dátuma, és az óra nincs téli időszámítás időpontban, akkor kell //átállítani az időt. if (((ds3231.ho==10 && ds3231.nap>akt_okt_dat) || (ds3231.ho>10) || (ds3231.ho<3) || (ds3231.ho==3 && ds3231.nap<akt_marc_dat)) && nyari==1) { EEPROM.put(1,(byte)0); //Az eepromban beállítjuk a téli időszámítást if (ds3231.ora==0) { //Ha még 0 óra van, akkor előző napra kell beállni ds3231.ora=23; //Az előző napon ekkor 23 óra van ds3231.nap=ds3231.nap-1; //csökkentjük a napot ds3231.het_napja=ds3231.het_napja-1; //csökkentjük a hét napját if (ds3231.het_napja==0) { ds3231.het_napja=7;} //ha a hét napja 0 lett (hétfőn fordulhat elő), akkor nem 0 nap következik, hanem 7 (vasárnap) if (ds3231.nap==0) { //ha 1.-e volt, akkor hónapot is kell váltani ds3231.ho=ds3231.ho-1; //csökkentjük a hónapot if (ds3231.ho==0) { //ha a hónap január volt, akkor nem a 0. hónap jön, hanem az előző év decembere ds3231.ho=12;ds3231.nap=31; //az új dátum december 31 ds3231.ev=ds3231.ev-1; //csökkentjük az évet } if (ds3231.ho==1 || ds3231.ho==3 || ds3231.ho==5 || ds3231.ho==7 || ds3231.ho==8 || ds3231.ho==10) { ds3231.nap=31;} //ezekben a hónapokban az előző hónap 31 napos, tehát az előzö nap 31.-e if (ds3231.ho==4 || ds3231.ho==6 || ds3231.ho==9 || ds3231.ho==11) { ds3231.nap=30;} //ezekben a hónapokban az előző honap 30 napos, tehát az előző nap 30.-a if (ds3231.ho==2 && szokoev(ds3231.ev)) { ds3231.nap=29;} //február utolsó napja van, ami 02.29, mert szökőévben vagyunk if (ds3231.ho==2 && !szokoev(ds3231.ev)) { ds3231.nap=28;} //február utolsó napja van, ami 02.28, mert nem szökőévben vagyunk } } else { ds3231.ora=ds3231.ora-1;} //nem 0 óra volt, így nyugodtan csökkenthetjük az órát 1-el. setTime24(); //beállítjuk az órát az új időpontra } } void setTime24() { /************************************************************************************************************* * Ezzel a függvénnyel lehet beállítani az időt. Egy dat_ido típusú és ds3231 nevű változót vár a működéshez. * * Ezt a változót globális változóként célszerű létrehozni. A getTime24() függvény ugyanezt a változót * * tölti fel a ds3231 chipből kiolvasott dátummal és időponttal. Ha memóriában átírjuk a dátumot és időt * * a ds3231 változóban, akkor ez a függvény beírja a változó aktuális értékét a chip-be. * * A dat_ido struktúra részleteit lásd a getTime24() függvény kommentjeiben! * **************************************************************************************************************/ //status regiszter beállítása Wire.beginTransmission(CLOCK_ADDRESS); Wire.write(0x0e); //A control regiszterbe fogunk írni, azt címezzük meg Wire.write(0b01100011); //BBSQW bit 1, vagyis elemes táplálásnál is működik az oszcillátor //ha 1-re állítanánk, elemes táplálásnál nem járna az óra, csak őrizni az utolsó időpontot //A RS2 és RS1 bit 0-val beállítja a négyszögjel kimenetet 1Hz-ra, ezen lehet változtatni: // 0b01101011 esetén 1024Khz, 0b01110011 esetén 4096Khz, 0b01111011 esetén 8192Khz. //A INTCN bit 0-val beállítja, hogy az INT/SQW kimenet beállított frekvenciájú jelet ad ki. //címbet a státus regiszter következik, nem kell megcímezni csak írni, és az adat oda kerül Wire.write(0b00000000); //A status regiszterben töröljük az OSF fleg-et, ami 1-el jelzi majd, ha elemes táplálásnál //nem működött az oszcillátor, vagyis az óra valószínűleg nem pontos. //Az EN32Khz bit-et is 0-ra írjuk, azaz letiltjuk a 32Khz-s kimenetet Wire.endTransmission(); //dátum és időpont beállítása Wire.beginTransmission(CLOCK_ADDRESS); Wire.write(0x00); Wire.write(dec_bcd(ds3231.masodperc)); Wire.write(dec_bcd(ds3231.perc)); Wire.write(dec_bcd(ds3231.ora) & 0b10111111); Wire.write(dec_bcd(ds3231.het_napja)); Wire.write(dec_bcd(ds3231.nap)); Wire.write(dec_bcd(ds3231.ho)); Wire.write(dec_bcd(ds3231.ev-2000)); Wire.endTransmission(); } void getTime24() { /**************************************************************************************************** * Ez a függvény kiolvassa a DS3231 RTC óra chip-ből a dátumot és az időt és egy dat_ido típusú és * * ds3231 navű változóba tölti azok aktuális pillanatnyi értékét. * * A változót globális változóként célszerű létrehozni a program eljén: * * struct dat_ido { // a dátum és idő beállításához illetve kiolvasásához a struktúrát * * int ev; //év tárolása a struktúrában (évszázadokkal kell megadni, * * //illetve így kapjuk meg az eredményt a dátum kiolvasásakor) * * byte ho; //ho tárolása a struktúrában * * byte nap; //nap tárolása a struktúrában * * byte het_napja; //hét napja a struktúrában (1-hétfő....7-vasárnap) * * byte ora; //óra tárolása a struktúrában (24 órás üzemmódot fogunk használni) * * byte perc; //perc tárolása a struktúrában * * byte masodperc; //másodperc tárolása a struktúrában * * bool pontos; //ez a változó fogja megadni az IDO kiolvasását követően, * * //hogy pontos-e a kiolvasott időpont ha elemes működés közben leáll a * * //DS3231 oszcillátora, akkor az "OSF" flag bebillen, és ezt olvassuk ki * *}; * *dat_ido ds3231; //létrehozzuk az dat_ido típusú változónkat DS3231 változó néven * ****************************************************************************************************/ //kiolvassa a dátumot és az időpontot Wire.beginTransmission(CLOCK_ADDRESS); Wire.write(0x00); Wire.endTransmission(); Wire.requestFrom(CLOCK_ADDRESS, 7); ds3231.masodperc = bcd_Dec(Wire.read()); ds3231.perc = bcd_Dec(Wire.read()); ds3231.ora = bcd_Dec(Wire.read()); ds3231.het_napja = bcd_Dec(Wire.read()); ds3231.nap = bcd_Dec(Wire.read()); ds3231.ho = bcd_Dec(Wire.read() & 0b01111111); ds3231.ev = bcd_Dec(Wire.read())+2000; //status regiszterből az OSF bit kiolvasása. Wire.beginTransmission(CLOCK_ADDRESS); Wire.write(0x0f); Wire.endTransmission(); Wire.requestFrom(CLOCK_ADDRESS, 1); if (Wire.read()& 0b10000000) {ds3231.pontos=0;} else {ds3231.pontos=1;} //1-el jelezzük, ha az óra valószínűleg pontos } float getTemperature() { // Kiolvassa a hőmérséklet értékét a 0x11h és 0x12h regiszterekből byte temp; Wire.beginTransmission(CLOCK_ADDRESS); Wire.write(0x11); //a DS3231 chip 0x11 és 0x12-es regisztere a hőmérséklet regiszter Wire.endTransmission(); Wire.requestFrom(CLOCK_ADDRESS, 2); //2 byte-ot kérünk el a chip-től temp = Wire.read(); //hőmérséklet MSB regisztere return float(temp) + 0.25*(Wire.read()>>6); //hőmérséklet LSB regiszterének kiolvasása } byte bcd_Dec(byte val) { // Convertál bcd számból decimálisba return ( (val/16*10) + (val%16) ); } byte dec_bcd(byte val) { // Convertál decimális számból bcd-be return ( (val/10*16) + (val%10) ); } void ido_szo(int xora, byte xperc,bool bing) { /******************************************************************************************************** * Ez a függvény a szo[] tömbbe helyezi az idő kimondásához szükséges szavak index értékét kimondáshoz * * szükséges sorrendben. * * Paraméterek: * * ora - az időpont órája * * perc - az időpont perce * * bing - az óránkénti bemondásnál szignált tesz a szöveg elé. Speciálisan a szignál a 191. file * * az SD kártyán, és ezt teszi be első hangnak * ********************************************************************************************************/ for (byte i=0;i<15;i++) {szo[i]=0;} //tömb törlése byte index=0; if (bing==1) {szo[index]=191;index++;szo[index]=szunet;index++;} //szignál az első tömbelembe, a második egy szünet byte h_tiz; byte h_egy; //óra ************************************ h_tiz=xora/10; h_egy=xora-((long)h_tiz*10); if ((h_tiz==1) & (h_egy==0)) {szo[index]=tiz;index++;} if ((h_tiz==1) & (h_egy>0)) {szo[index]=tizen;index++;} if ((h_tiz==2) & (h_egy==0)) {szo[index]=husz;index++;} if ((h_tiz==2) & (h_egy>0)) {szo[index]=huszon;index++;} if (h_tiz>2) {szo[index]=tiz+h_tiz-1;index++;} if (h_egy>0) {szo[index]=egy+h_egy-1;index++;} szo[index]=ora;index++; if (xperc>0) { szo[index]=szunet;index++; //az óra kimondása után beteszünk 0,2sec várakozást a szöveg tagolása érdekében //perc************************************************* h_tiz=xperc/10; h_egy=xperc-((int)h_tiz*10); if ((h_tiz==1) & (h_egy==0)) {szo[index]=tiz;index++;} if ((h_tiz==1) & (h_egy>0)) {szo[index]=tizen;index++;} if ((h_tiz==2) & (h_egy==0)) {szo[index]=husz;index++;} if ((h_tiz==2) & (h_egy>0)) {szo[index]=huszon;index++;} if (h_tiz>2) {szo[index]=tiz+h_tiz-1;index++;} if (h_egy>0) {szo[index]=egy+h_egy-1;index++;} szo[index]=perc;index++; } } void datum_szo(int ev, byte ho, byte nap, bool ho_nev, byte het_napja) { /********************************************************************************************* * Ez a függvény a szo[] tömbbe helyezi a dátum kimondásához szükséges szavak index értékét * * kimondáshoz szükséges sorrendben. * * Paraméterek: * * ev - a dátumban megadott év, évszázadokkal együtt (pl. 2021). Ha az ev=0, * * akkor csak a hónapot mondja a hónap nevével * * ho - a dátum hónapja * * nap - a dátum napja * * ho_nev - ha értéke 1, akkor a hónapokat a nevükkel mondja ki pl. "február", * * ha értéke 0, akkor a hónap sorszámával pl. "második hó" * * het_napja - ha 0, akkor nem kerül kimondásra a hét napja, ha értéke 1-7 közötti, * * akkor a dátum végén kimondja a hét napjának nevét is pl. ha 1, akkor "hétfő" * *********************************************************************************************/ for (byte i=0;i<15;i++) {szo[i]=0;} byte index=0; byte h_egyezer; byte h_egyszaz; byte h_tiz; byte h_egy; int maradek; //év ************************************ szo[index]=szunet;index++; if (ev>0) { //ha az ev nagyobb mint 0 csak akkor mondjuk ki h_egyezer=ev/1000; maradek=ev-((long)h_egyezer*1000); h_egyszaz=maradek/100; maradek=maradek-((long)h_egyszaz*100); h_tiz=maradek/10; h_egy=maradek-((long)h_tiz*10); //ezer if (h_egyezer>1) {szo[index]=egy+h_egyezer-1;index++;szo[index]=ezer;index++;} if (h_egyezer==1) {szo[index]=ezer;index++;} //ezernél kissebb rész if (h_egyszaz!=0) {szo[index]=szaz+h_egyszaz-1;index++;} if ((h_tiz==1) & (h_egy==0)) {szo[index]=tiz;index++;} if ((h_tiz==1) & (h_egy>0)) {szo[index]=tizen;index++;} if ((h_tiz==2) & (h_egy==0)) {szo[index]=husz;index++;} if ((h_tiz==2) & (h_egy>0)) {szo[index]=huszon;index++;} if (h_tiz>2) {szo[index]=tiz+h_tiz-1;index++;} if (h_egy>0) {szo[index]=egy+h_egy-1;index++;} if (ev==0) {szo[index]=nulla;index++;} //ha a kimondandó szám 0, akkor legalább egy 0-át mondani kell szo[index]=szunet;index++; //az év kimondása után beteszünk 0,2sec várakozást a szöveg tagolása érdekében } //hónap *************************************** h_tiz=ho/10; h_egy=maradek-((long)h_tiz*10); if (ho_nev==1 or ev==0) { //ha az ev=0 vagy a paraméter előírja, akkor nevével mondjuk a hónapot //hónap nevekkel kimondva szo[index]=januar+ho-1;index++; } else { //hónap sorszámmal kimondva szo[index]=elso+ho-1;index++; szo[index]=honap;index++; } // szo[index]=szunet;index++; //a hónap kimondása után beteszünk 0,2 sec várakozást a szöveg tagolása érdekében //nap************************************************* h_tiz=nap/10; h_egy=nap-((int)h_tiz*10); if ((h_tiz==1) & (h_egy==0)) {szo[index]=tiz;index++;} if ((h_tiz==1) & (h_egy>0)) {szo[index]=tizen;index++;} if ((h_tiz==2) & (h_egy==0)) {szo[index]=husz;index++;} if ((h_tiz==2) & (h_egy>0)) {szo[index]=huszon;index++;} if (h_tiz>2) {szo[index]=tiz+h_tiz-1;index++;} if (h_egy>0) {szo[index]=egy+h_egy-1;index++;} szo[index]=szunet;index++; //het napja******************************************* if (het_napja>0) { szo[index]=hetfo+het_napja-1;index++; } } void hang_ir (byte hang, bool set_hang) { /****************************************************************************************************************** * Amikor az idő bemondás hangerejét állítjuk be, ez a függvény jeleníti meg a * * hangszóró szimbólumot, valamint a hengerő érték számjegyét. * * A hangszóró szimbólumot a hang_font[] tömbből vesszük, a számjegyeket a font[] tömbből. * * A setupban villogtatni is kell a számjegyet amikor épp beállítjuk az értékét, * * erre szolgál a set_hang paraméter. Amikor értéke 0, akkor a számjegyek bitsorozatai * * bemásoljuk a kijelzőre menő bitsorozatba, amikor értéke 1, akkor csupa 0-át másolunk be. * * Hol 1-el, hol 0-val hívjuk meg a függvényt így érhető el a villogás. * * paraméterek: * * hang: a hangerő értéke 0-30 között * * hang_set: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba a * * a hangerő számjegyeit, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy a * * számjegyek villogjanak a képernyőn, mert egyszer 1-el, egyszer pedig 0-val hívjuk meg ezt a függvényt* ******************************************************************************************************************/ byte a1,a2; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző mosul van, így mindegyiknek van egy változója a1=hang/10; a2=hang-a1*10; for (byte sor=0;sor<8;sor++) { //a matrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába b1=hang_font[sor*3]; //balról első kijelző adott sorának tartalma b2=hang_font[sor*3+1]; //balról második kijelző adott sorának tartalma if (set_hang==1) { b3=hang_font[sor*3+2]; //balról harmadik kijlző adott sorának tartalma b4=0; //a negyedik kijelzőn egyik led-et sem kapcsoljuk be } else { s1=hang_font[sor*3+2]; s2=font[a1*8+sor]; s2=s2>>3; b3=s1|s2; //balról harmadik kijlző adott sorának tartalma s1=font[a1*8+sor]; s2=font[a2*8+sor]; s1=s1<<5; s2=s2>>2; b4=s1|s2; //balról negyedik kijlző adott sorának tartalma } //kiléptetjük a bitsorozatot a négy mártix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel //a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void bsta_ir (byte bsta, bool set_bsta) { //az évet évszázadok nélkül kell megadni //Amikor az idő bemondás kezdő időpontját (óráját) állítjuk be (bemondás start időpont), //ez a függvény jeleníti meg a hangszóró és faltól induló nyilacska szimbólumot, //valamint kezdő óra érték számjegyét. //A szimbólumokat a bsta_font[] tömbből vesszük, a számjegyeket a font[] tömbből. //A setupban villogtatni is kell a számjegyet amikor épp beállítjuk az értékét, //erre szolgál a set_bsta paraméter. Amikor értéke 0, akkor a számjegyek bitsorozatai //bemásoljuk a kijelzőre menő bitsorozatba, amikor értéke 1, akkor csupa 0-át másolunk be. //Hol 1-el, hol 0-val hívjuk meg a függvényt így érhető el a villogás. //paraméterek: //bsta: a kezdő óra értéke, ami 0 és 24 és ezek közötti numerikus érték lehet //bsta_set: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba a // a záró óra számjegyeit, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy a // számjegyek villogjanak a képernyőn, mert egyszer 1-el, egyszer pedig 0-val hívjuk meg ezt a függvényt byte a1,a2; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója a1=bsta/10; a2=bsta-a1*10; for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába b1=bsta_font[sor*3]; b2=bsta_font[sor*3+1]; if (set_bsta==1) { b3=bsta_font[sor*3+2]; b4=0; } else { s1=bsta_font[sor*3+2]; s2=font[a1*8+sor]; s2=s2>>3; b3=s1|s2; s1=font[a1*8+sor]; s2=font[a2*8+sor]; s1=s1<<5; s2=s2>>2; b4=s1|s2; } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void bsto_ir (byte bsto, bool set_bsto) { //az évet évszázadok nélkül kell megadni //Amikor az idő bemondás záró időpontját (óráját) állítjuk be (bemondás stop időpont), //ez a függvény jeleníti meg a hangszóró és falnak ütköző nyilacska szimbólumot, //valamint záró óra érték számjegyét. //A szimbólumokat a bsto_font[] tömbből vesszük, a számjegyeket a font[] tömbből. //A setupban villogtatni is kell a számjegyet amikor épp beállítjuk az értékét, //erre szolgál a set_bsto paraméter. Amikor értéke 0, akkor a számjegyek bitsorozatai //bemásoljuk a kijelzőre menő bitsorozatba, amikor értéke 1, akkor csupa 0-át másolunk be. //Hol 1-el, hol 0-val hívjuk meg a függvényt így érhető el a villogás. //paraméterek: //bsto: a záró óra értéke, ami a kezdő óra (bsta) és 24 és ezek közötti numerikus érték lehet //bsto_set: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba a // a záró óra számjegyeit, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy a // számjegyek villogjanak a képernyőn, mert egyszer 1-el, egyszer pedig 0-val hívjuk meg ezt a függvényt byte a1,a2; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat a1=bsto/10; a2=bsto-a1*10; byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába b1=bsto_font[sor*3]; b2=bsto_font[sor*3+1]; if (set_bsto==1) { b3=bsto_font[sor*3+2]; b4=0; } else { s1=bsto_font[sor*3+2]; s2=font[a1*8+sor]; s2=s2>>3; b3=s1|s2; s1=font[a1*8+sor]; s2=font[a2*8+sor]; s1=s1<<5; s2=s2>>2; b4=s1|s2; } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void aut_ir (bool aut,bool set_aut) { //Amikor az automatikus nyári időszámítás beállítását állítjuk be (automatikus be vagy ki), //ez a függvény jeleníti meg a "NYARI" feliratot és a "BE" illetve "KI" karaktereket. //Ha a setup során hosszan nyomjuk a nyomógombot, akkor ciklikusan váltogatja a BE és a KI //feliratokat, és ahol elengedjük a gombot az lesz beállítva. //A setupban villogtatni is kell az BE illetve KI felirat részeket, erre szolgál a set_aut // paraméter. Amikor értéke 0, akkor az BE illetve KI feliratot bemásoljuk a bitsorozatba, //amikor értéke 1, akkor csupa 0-át másolunk be. Hol 1-el, hol 0-val hívjuk meg a függvényt //így érhető el a villogás. A "NYÁRI" felirat az aut_font[] tömbben található, innen másoljuk //ki. A tömbben kétszer van meg minden, egy BE és egy KI karakter sorozattal az utolsó mátrix kijelzőre. //paraméterek: //aut: 0 esetén KI felirat, 1 esetén BE felirat //aut_set: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba a BE // vagy KI bitképét, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy a BE illetve KI betűk // villogjanak a képernyőn, mert egyszer 1-el, egyszer pedig 0-val hívjuk meg ezt a függvényt byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába b1=aut_font[sor*5]; b2=aut_font[sor*5+1]; b3=aut_font[sor*5+2]; if (set_aut==1) {b4=0;} else { if (aut==1) {b4=aut_font[sor*5+3];} else {b4=aut_font[sor*5+4];} } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void ff_no_ir (bool ff_no,bool set_ff_no) { //Amikor a bemondás hangját állítjuk be a setup során, ez a függvény jeleníti meg a hangszóró és //férfi, nő valamint az FF és NŐ karaktereket. Ha a setup során hosszan nyomjuk a nyomógombot, //akkor ciklikusan váltogatja a FF-t és a NŐ-t, és ahol elengedjük a gombot az lesz beállítva. //A setupban villogtatni is kell az FF illetve NŐ felirat részeket, erre szolgál a set_ff_no // paraméter. Amikor értéke 0, akkor az FF illetve NŐ feliratot bemásoljuk a bitsorozatba, //amikor értéke 1, akkor csupa 0-át másolunk be. Hol 1-el, hol 0-val hévjuk meg a függvényt //így érhető el a villogás. A szimbólumok (hangszóró, férfi és nő jel) az ff_no_font[] tömbben //találhatók, innen másoljuk ki. A tömbben kétszer van meg minden, egy FF és egy NŐ karakter //sorozattal az utolsó mátrix kijelzőre. //paraméterek: //ff_no: 0 esetén FF felirat, 1 esetén NŐ felirat //ff_no_set: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba az FF // vagy NŐ bitképét, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy az FF illetve NŐ betűk // villogjanak a képernyőn, mert egyszer 1-el egyszer 0-val hívjuk meg ezt a függvényt byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába b1=ff_no_font[sor*5]; b2=ff_no_font[sor*5+1]; b3=ff_no_font[sor*5+2]; if (set_ff_no==1) {b4=0;} else { if (ff_no==1) {b4=ff_no_font[sor*5+3];} else {b4=ff_no_font[sor*5+4];} } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void ido_ir (byte ora, byte perc,bool kettospont, bool set_ora, bool set_perc) { //Ez a függvény az időt (óra, perc) jeleníti meg a kijelzőn. Paraméterként megkapja //az órát és a percet, ezeket az adatokat számjegyekre bontja és a font[] tömbből //kiveszi a számjegyek bitképét és összemásolja soronként egy 16 bites bitsorozatba. //Mivel az órabeállításkor villogtatni kell vagy az órát vagy a percet, ezért megkapja //a set_ora és a set_perc paraméterekben, hogy melyiket kell villogtatni. A villogás //jelzi a setup folyamatban, hogy a hosszan nyomjuk a nyomógombot, akkor melyik adat fog változni. //paraméterek: //ora: 0-tól 24-ig az óra //perc: 0-59.ig a perc //kettospont: ha értéke 1, akkor a képernyő közepén megjelenik egy kettőspont, ha 0 akkor nem. Másodpercenként // váltogatva hívjuk meg a függvényt, így másodperces ciklusban villog a kettőspont az óra és a perc között. //set_ora: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba az óra // számjegyeinek bitképét, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy az óra számjegyei // villogjanak a képernyőn, mert egyszer 1-el egyszer 0-val hívjuk meg ezt a függvényt //set_perc: ugyanúgy működik mint a set_ora, csak ez a percet villogtatja a setup azon részében, amikor a // percet állítjuk be byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója byte a1,a2,a3,a4; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat a1=ora/10; a2=ora-a1*10; if (a1==0) {a1=10;} a3=perc/10; a4=perc-a3*10; for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába if (set_ora==1) {b1=0;b2=0;kettospont=1;} else { s1=font[a1*8+sor]; //kiolvassuk a karakter tömbből a az óra számjegyének balról első számjegyét (tízes számjegy) s2=font[a2*8+sor]; //kiolvassuk a karakter tömbből az óra számjegyének balról második számjegyét (egyes számjegy) s2=s2>>7; //az egyes számérték bitjeit 7-el jobbra toljuk mert az első mátrix kijelző első hét bitje a //tízes számjegy s1 első hét bitje, és e mögé kell egy bitet másolni b1=s1|s2; //itt másoljuk a tízes számjegy első hét bitjéhez az egyes számjegy 1 bitjét s1=font[a2*8+sor]; //újra kiolvassuk az egyes számjegy bitsorozatát s1=s1<<1; //itt meg balra toljuk egyet, mert egy bit az előző kijelzőn van, hat bit meg már a második kijelzőre szorul b2=s1; } if (set_perc==1) {b3=0;b4=0;kettospont=1;} else { s1=font[a3*8+sor]; s1=s1>>3; b3=s1; s1=font[a3*8+sor]; s2=font[a4*8+sor]; s1=s1<<5; s2=s2>>2; b4=s1|s2; } if (kettospont==1){ //ha időt jelenítünk meg és a kettospont=1 akkor egy kettőspontot teszünk a kijelző közepére if (sor==1 or sor==2 or sor==5 or sor==6) { b2=b2|B00000001; b3=b3|B10000000; } } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void ev_ir (byte ev, bool set_ev) { //A függvény a paraméterként számként megkapja az év értékét évszázadok nélkül. //Az adatot átalakítja számjegyekké, amiknek a bitképét előveszi a font[] //tömbből, amit aztán kiírunk a MAX7219 chip-be. //Mivel 4 kijelzőre kell kiléptetni az adatokat, össze kell másolgatni az összes kijelző adott sorának bitképét //és egyben kiléptetni, tehát a kijelző láncra 16 bitet kell kiírni soronként. //paraméterek: //ev: 0-tól 99-ig az év (ebben a programban csak 50-ig megy, mert a setup-ban max 2050-et lehet beállítani) //set_ev: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba az ev // karaktereinek bitképét, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy az év // villog a képernyőn, mert egyszer 1-el, egyszer 0-val hívjuk meg ezt a függvényt byte a1,a2; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója a1=ev/10; a2=ev-a1*10; for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába b1=ev_font[sor*3]; b2=ev_font[sor*3+1]; if (set_ev==1) { b3=ev_font[sor*3+2]; b4=0; } else { s1=ev_font[sor*3+2]; s2=font[a1*8+sor]; s2=s2>>3; b3=s1|s2; s1=font[a1*8+sor]; s2=font[a2*8+sor]; s1=s1<<5; s2=s2>>2; b4=s1|s2; } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void start_ir (bool set_start) { //a képernyőre a start feliratot írja ki azzal, hogy a start_font[] tömbből soronként kilépteti //a felirat bitképét. A feliratot villogtatni is kell a setup folyamat során, mert ez jelzi //hogy egy gombnyomással beírjuk a beállított értékeket és paramétereket a MAX7219 chip-be és az //eeprom-ba, és ehhez kell a set_start bemenő paraméter. Ha értéke 0 akkor //megjelenik a felirat, ha értéke 1. akkor nem. Hol 0-val, hogy 1-el hívjuk meg a függvényt //így villog a felirat. byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába if (set_start==1) {b1=0;b2=0;b3=0;b4=0;} else { b1=start_font[sor*4]; b2=start_font[sor*4+1]; b3=start_font[sor*4+2]; b4=start_font[sor*4+3]; } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void setup_ir (bool set_setup) { //a képernyőre a setup feliratot írja ki azzal, hogy a setup_font[] tömbből soronként kilépteti //a felirat bitképét. A feliratot villogtatni is kell a setup folyamat során, mert ez jelzi //hogy elindult a folyamat, és ehhez kell a set_setup bemenő paraméter. Ha értéke 0 akkor //megjelenik a felirat, ha értéke 1. akkor nem. Hol 0-val, hogy 1-el hívjuk meg a függvényt //így villog a felirat. byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába if (set_setup==1) {b1=0;b2=0;b3=0;b4=0;} else { b1=setup_font[sor*4]; b2=setup_font[sor*4+1]; b3=setup_font[sor*4+2]; b4=setup_font[sor*4+3]; } //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void dat_ir (byte ho, byte nap, bool set_ho, bool set_nap) { //A függvény a paraméterként számként megkapja a hónapot és a hónap napját. //Mindkét adatot átalakítja számjegyekké, amiknek a bitképét előveszi a honap_font[] és font[] //tömbökből, amit aztán kiírunk a MAX7219 chip-be. A hónap napjának karakter képét a //font[] tömbben hoztuk létre, ebből emeli ki. A hónap rövidített három karakteres névvel jelenik meg, //ennek bitképe a honap_font[] tömbben található, minden egyes hóna külön-külön. //Mivel 4 kijelzőre kell kiléptetni az adatokat, össze kell másolgatni az összes kijelző adott sorának bitképét //és egyben kiléptetni, tehát a kijelző láncra 16 bitet kell kiírni soronként. //paraméterek: //ho: 0-tól 12-ig a hónap //nap: az adott nap száma (dátum napja) 1-31 //set_ho: amikor setup-ban vagyunk akkor kell ez a paraméter, 0 hatására bemásoljuk a bitsorozatba a ho // karaktereinek bitképét, míg 1 esetén csupa 0-át másolunk be. Így érjük el, hogy a hónap // megnevezése villog a képernyőn, mert egyszer 1-el egyszer 0-val hívjuk meg ezt a függvényt //set_nap: ugyanúgy működik mint a set_ho, csak ez a napot villogtatja a setup azon részében, amikor a // napot állítjuk be byte a1,a2,a3,a4; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója a3=nap/10; a4=nap-a3*10; for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába if (set_ho==1) {b1=0;b2=0;} else { b1=honap_font[(ho-1)*16+sor*2]; b2=honap_font[(ho-1)*16+sor*2+1]; } if (set_nap==1) {b3=0;b4=0;} else { if (nap<10) {a3=10;}; s1=font[a3*8+sor]; s1=s1>>3; b3=s1; s1=font[a3*8+sor]; s2=font[a4*8+sor]; s1=s1<<5; s2=s2>>2; b4=s1|s2; } if (sor==7) {b3=b3|B10000000;} //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void het_ir (byte nap, byte het_napja, bool set_het) { //A függvény a paraméterként számként megkapja a hónap napját és a hét napját (1-7). A hét napját //átalakítja három karakteres névvé (hétfő-vasárnapig), és a hónap napját és a hét napját soronként //megjelenítendő bitképpé amit aztán kiírunk a MAX7219 chip-be. A hónap napjának karakter képét a //font[] tömbben hoztuk létre, ebből emeli ki. Először a hónap napját felbontjuk két különálló //egyjegyű számra, és ezekkel lehet megcímezni a font[] tömböt, amiből soronként ki lehet emelni az //adott karakter bitsorozatát. A hét napjainak bitképe a het_font[] tömbben van. Minden nap 3 betűre //van lerövidítve, és hét ilyen bitsorozat van ebben a tömbben. //Mivel 4 kijelzőre kell kiléptetni az adatokat, össze kell másolgatni az összes kijelző adott sorának bitképét //és egyben kiléptetni, tehát a kijelző láncra 16 bitet kell kiírni soronként. //paraméterek: //nap: 0-31 (nem ellenőrzi a hónap napjait) //het: 1-7, 1=hétfő //set_het: ha értéke 0, akkor a hét napjainak bitsorozatát írjuk a mátrix kijelzőre // ha értéke 1, akkor csupa 0-át léptetünk ki a betűk bitképe helyett. Ez a setupban a hét napjainak // villogtatására lett kitalálva, de a hét napjait immár nem kell beállítani, mert a dátumból // a program kiszámolja magának. Benne hagytam a villogtatás lehetőségét, de nem használom, ez a paraméter mindig 0. byte a1,a2; //paraméter érték számjegyekre bontásához byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója a1=nap/10; a2=nap-a1*10; for (byte sor=0;sor<8;sor++) { //a matrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába s1=font[a1*8+sor]; s2=font[a2*8+sor]; s2=s2>>7; b1=s1|s2; s1=font[a2*8+sor]; s1=s1<<1; b2=s1; if (set_het==1) {b3=0;b4=0;} else { b3=het_font[(het_napja-1)*16+sor*2]; b4=het_font[(het_napja-1)*16+sor*2+1]; } if (sor==7) {b3=b3|B10000000;} //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } void homeresklet_ir (float homerseklet) { //AZ a függvény a paraméterként kapott hőmérséklet számadatot alakítja át soronként megjelenítendő bitképpé //amit aztán kiírunk a MAX7219 chip-be. A karakter képet a font[] tömbben hoztuk létre, ebből emeli ki. //Először felbontjuk a float típusú hőmérséklet értéket számjegyekre, és ezekkel lehet megcímezni a font[] //tömböt, amiből soronként ki lehet emelni ez adott karakter bitsorozatát. //Mivel 4 kijelzőre kell kiléptetni az adatokat, össze kell másolgatni az összes kijelző adott sorának bitképét //és egyben kiléptetni, tehát a kijelző láncra 16 bitet kell kiírni. byte b1,b2,b3,b4; //segédváltozók, amikbe a karakterkép adott sorát töltöm be, és ebből léptetem ki a MAX7219 chip-be, //4 mátrix kijelző modul van, így mindegyiknek van egy változója int h0=(int)(homerseklet*10); byte h1=h0/100; byte h2=(h0-h1*100)/10; byte h3=h0-h1*100-h2*10; if (h1==0) { h1=10; } byte s1,s2; //ezekben tárolom a karakter tömbökből indexérték alapján kimásolt bitsorozatokat for (byte sor=0;sor<8;sor++) { //a mátrix kijelzőkbe soronként lehet beléptetni az infót, de mind a négy kijelzőnek ugyanabba a sorába s1=font[h1*8+sor]; //első karakter s2=font[h2*8+sor]; //második karakter s2=s2>>7; //második karakterből csak egy oszlop kell, a legelső b1=s1|s2; //első karakter és a második karakter első oszlopának összemásolása s1=font[h2*8+sor]; //második karakter kiolvasása újra b2=s1<<1; //második karakterből csak a 2. oszloptól kell (tehát csak öt oszlop) if (sor==7 or sor==6) {b2=b2|B00000010;} //második és harmadik karakter két oszlopának összemásolása a tizedesponttal b3=font[h3*8+sor]; //harmadik karakter kiolvasása újra b4=cfok_font[sor]; //celsius fok karakterkép //kiléptetjük a bitsorozatot a négy mátrix kijelzőbe. Sorba vannak kötve, egymásnak adják tovább az infót! digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok kileptet(sor+1,b1); kileptet(sor+1,b2); kileptet(sor+1,b3); kileptet(sor+1,b4); digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn } } /********************************************************************************************** * Megméri az A6 bemenetre kötött fotó tranzisztor és ellenállásosztóban az ellenállás * * feszültségét. Ellenállás értéke 1Kohm. A fotó tranzisztor kb. 5000Lux-nál teljesen kinyit, * * ekkor az ellenálláson közel 5V feszültség mérhető. Sötétben a feszültség 0V * **********************************************************************************************/ void fenyero_beallitas(){ int ledmatfeny=0; for (byte j=9;j>0;j--) {mert_fenyero[j]=mert_fenyero[j-1];} int fenyero=analogRead(A0); mert_fenyero[0]=fenyero; fenyertek=(mert_fenyero[0]+mert_fenyero[1]+mert_fenyero[2]+mert_fenyero[3]+mert_fenyero[4]+mert_fenyero[5]+mert_fenyero[6]+mert_fenyero[7]+mert_fenyero[8]+mert_fenyero[9])/10; if (fenyertek<=4) {ledmatfeny=0;} if (fenyertek<=8 & fenyertek>4) {ledmatfeny=1;} if (fenyertek<=15 & fenyertek>8) {ledmatfeny=2;} if (fenyertek<=30 & fenyertek>15) {ledmatfeny=3;} if (fenyertek<=45 & fenyertek>30) {ledmatfeny=4;} if (fenyertek<=60 & fenyertek>45) {ledmatfeny=5;} if (fenyertek<=75 & fenyertek>60) {ledmatfeny=6;} if (fenyertek<=90 & fenyertek>75) {ledmatfeny=7;} if (fenyertek<=105 & fenyertek>90) {ledmatfeny=8;} if (fenyertek<=120 & fenyertek>105) {ledmatfeny=9;} if (fenyertek<=135 & fenyertek>120) {ledmatfeny=10;} if (fenyertek<=150 & fenyertek>135) {ledmatfeny=11;} if (fenyertek<=165 & fenyertek>150) {ledmatfeny=12;} if (fenyertek<=200 & fenyertek>165) {ledmatfeny=13;} if (fenyertek<=300 & fenyertek>200) {ledmatfeny=14;} if (fenyertek>300) {ledmatfeny=15;} //árnyékos lakásban kellett az óra gyengén látónak, ezért az éjszaka kivitelével azt akartam //hogy teljes fényerővel világítson, ezért nagyon szűk fényintenzitáson belül szabályoz. //300 felett már max fényerő. Úgy tapasztaltam, hogy olyan helyen ahol soha nem süt a nap //az érzékelőre, 200 és 400 között van a mért érték maximuma. matrix_setup(intenzity,ledmatfeny); //Intenzitás minimum } void kileptet(byte bitkep1, byte bitkep2) { //adatokat léptetek ezzel a függvénnyel a MAX7219 chip-be. A chip 8 sort kezel //bitkep1=a sor sorszáma, amibe a megjelenítendő adatot írjuk (0-7-ig lehet címezni) //bitkep2=az adat, amit bele írunk a regiszterbe, ez jelenik meg az adott sor led-jein bitenként for (byte i=0;i<8;i++) { //először a felső byte adatot fogjuk kiléptetni bitenként jobbról balra digitalWrite(adat_kimenet,(bitkep1<<i) & 128); digitalWrite(clk_kimenet,1); //órajel felfutóél (beolvassa az adatot) digitalWrite(clk_kimenet,0); //órajel lefutóél } delayMicroseconds(idozites); for (byte i=0;i<8;i++) { //először a felső byte adatot fogjuk kiléptetni bitenként jobbról balra digitalWrite(adat_kimenet,(bitkep2<<i) & 128); digitalWrite(clk_kimenet,1); digitalWrite(clk_kimenet,0); } } void matrix_setup(byte mode_reg, byte ertek) { //a matrix kijelzőt vezérlő MAX7219 chip mode regiszterébe írok ezzel a függvénnyel működési beállításokat, pl fényerő beállítás //mode_reg= a mód regsizter címe a chip-ben, ertek= az az érték, amit a regiszterbe írok digitalWrite(cs_kimenet,0); //cs bemenetre 0-at kapcsolunk, kijelző kiválasztva, jöhetnek az adatok delayMicroseconds(idozites); //várunk kicsit, hogy legyen idő a chipnek beállni az adatfogadásre for (byte i=0;i<4;i++) { //négyszer küldünk ki minden adatot, mert négy kijelzőnk van sorba kötve kileptet(mode_reg,ertek); //kiléptetjük az adatvezetéken a parancsot és az adatot egymás után } digitalWrite(cs_kimenet,1); //cs bemenetet vissza állítjuk 0-ra, chip nincs kiválasztva, illetve ezzel a felfutó éllel jelenik meg a beléptetett adat a kijelzőn }