Működés naplózó



Sokat gondolkodtam a címen, de nem jutott eszembe értelmesebb. Ha van jobb javaslatod írd meg légyszíves. Ja, hogy ehhez tudni kellene mi a szösz ez az egész. Már írom is. Egy olyan eszköz létrehozása volt a célom, ami rögzíti, hogy egy 220 -as ( vagyishát 230 -as ) fogyasztó mikor működik és mikor nem. Azaz naplózza a bekapcsolás és a kikapcsolás tényét, célszerűen a dátumát és időpontját.

Azt hiszem az elején érdemes túlesni a következőn: ha valami átmeneti ( vagy tartós :-) zavarodottság folytán netalán megpróbálod megépíteni az alábbi eszközt, vedd figyelembe, hogy a 230V -os hálózati feszültség életveszélyes lehet, ezért csak akkor kezdj hozzá ha ennek tudatában ill. a szükséges ismeretek birtokában vagy !

A figyelmes olvasó azonnal felfedezheti :-), hogy hoppá, ez bizony nem sokban különbözik a "Gomb nyomás-elengedés naplózás Arduino -val" című projektemtől. És valóban így van :-). Már azt az áramkört is egy kicsit ebből az irányból szemlélve hoztam létre. Hiszen ha egy nyomógomb lenyomását ill. elengedését sikerül rendesen logolni, akkor onnan már csak egy lépés, hogy egy vezetéken átfolyó áramot figyeljek. A kapcsoló helyett egy ZMCT103C nevű céláramkört tettem a kapcsolásba. Jó sokat elszórakoztam vele, mert enyhénszólva nem éppen úgy működik ahogy elvártam volna. Elvileg az átfolyó áram mérésére is alkalmas lenne, de én bizony akárhogy mesterkedtem, annak is örültem, hogy a "folyik_áram - nem_folyik_áram" információt ki tudtam belőle csiholni. Na mindegy, perpillanat ennyi nekem elegendő. ( Mint az előbb hivatkozott leírásban is említettem a cél alapvetően az lett volna, hogy egy búvárszivattyú működését naplózzam. De az is felmerült bennem, hogy a gyerkőcünk számítógép használatát figyelem vele. Nohát, még ilyet :-). )

Kapcsolási rajz nem készült, de hogy nehogy valaki elkezdjen panaszkodni :-), íme egy hozzávetőleges "rajz": Működés_naplózó

Nem kellett sokat agyalognom, hogy a kialakítás terve összeálljon. Mivel a hálózatra dugott fogyasztókat kell mérni, nyilvánvalóan egy elosztós konnektort érdemes felhasználni. Sőt, ha elég ügyes vagyok, akkor egyéb kiegészítésre nincs is szükségem, egy elosztóba maga az áramkör is beépíthető. Így egy szép, kompakt megoldást kapok. Természetesen az elején még nem tudtam pontosan a helyszükségletet, de végülis az elosztókból létezik 3 -as, 6 -os, sőt hosszabb is. Azért reméltem hogy túl hosszúra nem lesz szükség, ezért első közelítésben a 3 -as kiépítésűt céloztam meg. ( Végülis jól választottam, de - mint a további írásomból kiderül -, a helyet tekintve mindvégig nagyon rezgett a léc. )

No akkor talán vágjunk is bele. Első tapogatózó lépésem az elosztó feltérképezése volt. Ehhez először is eltávolítottam belőle a kapcsolót. Hogy miért kapcsolós elosztót választottam ? Két nyomós oka volt. Az egyik, hogy annak nagyobb a belmérete, így az esélyem is nagyobb volt hogy belefér aminek bele kell férnie. A másik, hogy ilyen volt itthon fölöslegben. Akkortehát a kiindulási állapot: Működés_naplózó

Egy csatlakozót meg kellett hagynom magának a fogyasztónak ( amit majd ide jól bedugva mérünk, ugye ), ami célszerűen a szélén levő. A többire nincs szükség, ezért széleskörű marási munkálatokba fogtam. Ja igen. Az ugye nyilvánvaló, hogy normál módon nem lehet szétszedni az elosztót. Normál mód alatt azt értem, hogy csavarhúzóval, esetleg fogóval. Volt korábban egy erre irányuló kísérletem, de csúnya kudarcba fulladt. Az elosztó alján levő sima fejű csavarokat akartam kiszedni, de nem jött össze ( vagyishát szét ). Pedig még speckó csavarkiszedőt is vettem hozzá. Egy youtube videó alapján is próbálkoztam. Kedvenc oldalamon is van egy leírás egy szétszedési próbálkozásról, nézze meg előbb aki meg akar vele próbálkozni.

Mindegy, ha normál módon esélytelen, akkor marad a nem normál mód: Működés_naplózó

Kis feszegetést követően: Működés_naplózó

No akkor vessünk egy kis számot, vagy hogy is mondják. Nézzük meg befér-e, aminek be kell férnie. A tápegységről eddig nem írtam, ezért néhány szó róla. Ez egy távközlési cuccban szolgált fénykorában, nagyon jó minőségű, német gyártmányú, afféle "jó ránézni" kivitel, amiben markánsan különbözik filléres kínai rokonaitól. Kapcsoló üzemű és 5V -os természetesen. Csak egy pöttyet nagy, dehát ebből van itthon néhány, azaz: ez van, ezt kell szeretni. Majd megoldom valahogy ( mondta a sündisznó vágyakozó pillantásokat vetve a súrolókefére :-). Működés_naplózó

Kicsit necces. És a képen a 3. dimenzió még nem is látszik annyira. Mi lenne, ha két rétegben helyezném el a paneleket ? Alulra menne a tápegység fejjel lefelé: Működés_naplózó

És lenne mondjuk egy lap, ami elválasztaná a többi áramkörtől: Működés_naplózó

És akkormár a táp panelt akár rögzíthetném is erre a lapra:

Működés_naplózó
Működés_naplózó

Lám belefért. Itt már az ZMCT103C részére is kivágtam egy darabot, mert az meg pofával lefelé lesz, hogy az ( egyik ) erősáramú madzag a szerkentyű alsó részén tudjon átmenni a tekercsén ( itt jegyzem meg, hogy az eszköz elkészülte után jutott eszembe, hogy az áram érzékelő tekercsét akár ki is forraszthattam volna a modulból azaz kihosszabbíthattam volna egy rövid vezetékkel, és úgy egész biztos sokkal egyszerűbb lett volna az eszközök elhelyezése ... az a pár centi vezeték pedig szinte biztos semmi működésbeli problémát nem okozott volna ): Működés_naplózó

Valahogy így: Működés_naplózó

Közben azon agyalogtam, hogy a konnektor megmaradt réz vezetői bizony eléggé összevissza fityegnek, valahogy fixálni kell őket hogy biztonságban legyenek ( ők is, meg a felhasználó is ). Egy megfelelő méretű műanyag közdarabbal oldottam meg: Működés_naplózó

Sőt a nagy sikerre való tekintettel mindjárt kettőt is készítettem belőle ( a francokat, az első példánynál elmértem a távolságokat ): Működés_naplózó

De végülis összejött, így már azért biztonságosabb a dolgok fekvése ill. állása: Működés_naplózó

Azután bekötöttem az erősáramú vezetékeket a - tőlem telhető - legbiztonságosabb módon. A sárga-barna vezetékek a kapcsolóüzemű tápegység bemenő vezetékei ( természetesen nem maradnak szabadon a végei :-). A képen már a ZMCT103C áramkör tekercsén is meg van járatva az erősáramú vezeték. Kezd bonyolódni a helyzet ha arra gondolunk, hogy mi mindennek kell még beférnie: Működés_naplózó

Újabb ( nem kis ) lépés. Elválasztó lap berögzítve ( két csavar középtájon ), vezetékek előkészítve: Működés_naplózó

Közben az elválasztó panel is sokat változott. Fene se gondolta volna az elején hogy ez lesz belőle. Szerencsém hogy nyers NYÁK lapot választottam, mert egyszerűen rá tudtam forrasztani a kis panelek pozícionálásához szükséges távtartókat, illetve az anyacsavarokat. A full rezezés talán abban is segít, hogy a tápegység tekercse és az erősáramú vezetékek ne szórják meg az elektronikát. De nem biztos. Működés_naplózó

Ezen a képen már látványilag szinte a végén járunk. Be van zsúfolva minden, csak még nincsenek összehuzalozva: Működés_naplózó

De ne szaladjunk ennyire előre, hiszen az Arduino Nano panel rögzítése elég komoly mutatvány volt. Alapvetően semmit nem szerettem volna ragasztani, ezért aztán küzdöttem mint disznó a jégen. A következő kép talán jól szemlélteti a küzdelem egyik fázisát. Az Arduino panel USB kivezetésének részére egy nyílást kellett készítenem, amiben tulajdonképpen nem is a nyílás volt a nehézség, hanem a pontos pozícionálás. A panel távolabbi végében az a függőleges fekete valami egy műanyag lap, aminek a felső részét természetesen levágtam. Az támasztja be a panelt amikor valaki ( én ) csatit akar belegyömöszölni. Kérdezhetné a kedves olvasó, hogy lehet-e majd szükség az USB csatlakozóra "üzemszerűen", azaz fontos volt-e sz*pni a hozzáférhetővé tételével. Fontos. Működés_naplózó

Ugyancsak nem szabad elfelejteni egy fontos dolgot az RTC modullal kapcsolatban. DS3231 modult használtam, ami teljes pompájában így néz ki: Működés_naplózó

Jól látszik, hogy egy gombelem szerű áramforrás is található rajta, aminek egy óra modulnál nyilvánvalóan az a szerepe, hogy a betáp esetleges megszűnése esetén is működjön az idő mérése. Ez eddig szuper, viszont - mint a képen is látszik - ez nem a jól megszokott filléres gombelem, hanem bizony akkumulátor. Ennek pedig az az oka, hogy jó hosszú ideig tartson, vagyis alapesetben ( tehát amikor van tápfesz ) az akku töltődik, amikor pedig nincs, akkor arról jár az áramkör. Ez rendben is volna, ha árban összevethető lenne az akku az elemmel. De bizony nem összevethető, jóval drágább. Így aztán sokan, és ebben az esetben én is, gombelemet teszünk inkább bele. A gombelemnek viszont nagyon nem tesz jót ha feszültséggel táplálják, így egy kis trükközésre van szükség: el kell vágni a panelen az elemet tápláló vezetéket. Sajnos erről a műveletről nem készítettem fényképeket, de szerencsére van róla egy jó videó, ami kiválóan mutatja a lényeget:

DS 3231 RTC | Disable Battery Charging circuit

Felvetődhet a kérdés, hogy vajon meddig képes egy elem működtetni az áramkört. Válaszként azt találtam, hogy "nem fixen az elemről fog működni, csak a belső RTC fog arról menni ha a tápfesz beesik bizonyos szint alá ". Tehát elvileg sokáig fogja bírni, a valóságban pedig ... majd meglátjuk.

A következő képent már össze is van vezetékezve aminek össze kell. Jól látható hogy nem látható erősáramú vezeték, és kizárt hogy valaki belenyúljon fázisba. Na jó, nem kizárt, de meg kell érte dolgoznia. A piros-fehér a táp ( 5V ) vezeték jobb oldalon egy furaton jön fel a tápegységtől. A jobb alsó részen látható ( ha látható ) a feszültség osztó 3 darab ellenállása. Igen, azért 3, mert nem volt 2k -s ellenállásom ezért 2 db 1k -ból csináltam :-). Nem röhög ! Működés_naplózó

Ugyanez oldalról, Működés_naplózó

USB csatlakozóval, Működés_naplózó

és naplemente után: Működés_naplózó

Node ez így mondhatnánk smafu, ha így marad. De bizony nem marad így, mert a zseniális konstruktőr azt is kigondolta hogyan lehetne szépen lezárni a tetejét. Méghozzá úgy, hogy egy kis vircsaft is kerüljön bele. Plexivel! Mondjuk az érdekességen kívül tényleg nincs sok értelme az átlátszó fedélnek, hacsaknem annyi, hogy lehet látni a bluetooth modul LED -jét, ami az áramkörre való felkapcsolódásnál jól jöhet ( sajna időnként előfordul, hogy nem sikerül csont nélkül a kapcsolódás ):

Találtam a lomok között egy éppen megfelelő méretű plexi lapot, XXXX mm vastagot. A marópálya megszerkesztése rém egyszerű, ráadásul fel tudtam használni azt a tervet, amivel az elosztó fedeléből vágtam ki az elején a téglalap alakú részt. Így legalább a pontos illeszkedés is garantálva volt. 2 -es, 2 élű maróval dolgoztam: Működés_naplózó

Alacsony fordulaton nyomattam: Működés_naplózó

Tudtam, hogy a túl kicsi és a túl nagy előtolás sem szerencsés: Működés_naplózó

Ennek ellenére első plexi marásom ( na jó, második, mert előtte csináltam azért egy próbát ) meglehetősen felemásra sikeredett. Az eredmény végülis jó lett, de ez a szerencsén is múlott. Részletezem. Mint a képen is jól látszik, marásnál az anyag felkenődött a szerszámra. Mondhatnánk hogy ez nem gond, de ne mondjuk, mert gond. Vagyishát ebben az esetben még éppen nem volt probléma, mert mire gondot okozott volna vége is volt a marásnak. A dolog lényege az, hogy a marás során fejlődő hő miatt a plexi meglágyul, szinte folyékonnyá válik, és a szerszám élének geometriájából adódóan felkúszik a száron. Ott viszont már nincs akkora hő, ezért szépen meg is szilárdul. Méghozzá igen keményre ( a munka után komoly feszegetésbe került az eltávolítása ). Ez azért jelent problémát, mert az anyag így egyre csak gyűlik, olyannyira, hogy egy idő után már akadályt képez az újonnan képződő "forgács" számára. Emiatt jobb esetben a marási felület ronda lesz, rosszabb esetben eltörik a szerszám ( 2 -es marónál nem sok kell hozzá ). Nem véletlenül mondják a tapasztaltabbak, hogy akkor marjuk megfelelően a plexit, ha a forgács olyan, mint a kókuszreszelék. Később ( Az óra projektnél ) ezt nekem is sikerült elérnem, mégpedig 4 -es átmérőjű 2 élű szerszám alkalmazásával. Node lássuk a végeredményt: Működés_naplózó

És egész jól illeszkedik is a helyére:

Működés_naplózó
Működés_naplózó

Mostmár csak a rögzítését kellett megoldani, amihez két kanyi nagy csavart használtam. Ez a két csavar tartja tulajdonképpen a belső részeket is, távtartók segítségével. Szerintem ötletes :-). Működés_naplózó

Íme a kész alkotás: Működés_naplózó


És most térjünk át a szoftver(ek)re.

Két részből tevődik össze, az egyik magát a naplózót működtető Arduino -s rész, a másik pedig az Androidos alkalmazás. Egyikről sem írnék túl sokat, mert mindkét program igen nagy hasonlóságot mutat a Nyomógomb naplózó kütyüével, melyet elég részletesen bemutattam itt az oldalamon. Inkább a speciális részeket részletezem egy kicsit.

Tömören összefoglalva: a program az A0 -s bemeneten várja az áramérzékelő jelét, és ennek hatására letárolja az esemény dátumát-idejét ( melyet az RTC -ből olvas ki ) és még néhány információt az Arduino EEPROM memóriájában. A letárolt struktúrát lásd lentebb. Ezenkívül kommunikál bluetooth -on egy másik eszközzel, ami a mi esetünkben egy Android -os telefon.

Mint a fenti kapcsolási rajzból és a lentebb következő kódból is kiderül, a BT soros kommunikációt nem az Arduino hagyományos ( hardveres ) soros portján oldottam meg. Helyette ún. "SoftwareSerial" módszert választottam, aminek az a lényege, hogy az Arduino -nak két külön digitális portján ( esetünkben D2 és D3 ) folyik a kommunikáció. Ennek az a legnagyobb előnye, hogy a két kommunikáció nem zavar be egymásnak, a hagyományos (hardveres) soros porton megy a program letöltés ill. a soros monitorra történő kiíratás, a szoftveres soros porton pedig a BT kommunikáció. Így jóval egyszerűbb volt a program tesztelése. Bár én nem tapasztaltam, utólag megtudtam, hogy ez a megoldás bizonyos esetekben problémákat okozhat. Ezen az oldalon részletesebben le van írva a dolog.

A kommunikációban a következők történhetnek:

Vannak bizonyos működési helyzetek, amik a szokványostól eltérőek, de le kell kezelni. Az idealizált helyzet az volna, ha garantálni lehetne, hogy először elindul a mérő áramkör, majd utána kapcsolódik BE-KI-BE-KI stb. a mérendő fogyasztó. És a végén előbb a fogyaztó lenne kikapcsolva, azután pedig maga a mérő áramkör, vagyis az Arduino. Ekkor mindig egymás után következnének a BE-KI párok. Ehhez képest a következő esetek is előfordulhatnak:

1. Úgy kapcsoljuk be a mérőt, hogy a rádugott fogyasztó már be van kapcsolva. Ez nem túl nagy baj, mert a mérő elindulásakor egyből rögzítünk is egy BE eseményt mintha akkor lett volna bekapcsolva a fogyasztó.

2. Kikapcsolhatjuk úgy a mérőáramkört, hogy a fogyasztó éppen BE van kapcsolva. Nyilván ekkor a fogyasztó is KI kapcsolódik hiszen azonos tápról mennek, viszont a KI eseményt nem tudjuk rögzíteni, vagyis letárolva marad egy KI nélküli BE esemény. Aztán ha esetleg úgy kapcsoljuk vissza a mérőt hogy a fogyasztó még be van kapcsolva, rögzítődik még egy BE esemény. Így akár több BE is lehet ki nélkül. Ezt ha nem vesszük figyelembe az Android alkalmazásban amikor a működési időket számoljuk nagy gubancokat okozhat.

VAGYIS AZT IS LE KELLENE TÁROLNUNK, HA MAGA A MÉRŐ ÁRAMKÖR KI ILL. BE LETT KAPCSOLVA !

Ebből a bekapcsolás viszonylag egyszerű, viszont a kikapcsolás nem, hiszen nem tudjuk előre, és ha bekövetkezik nem tudjuk rögzíteni az időpontját. Emiatt egy "MÉRŐ ÚJRAINDÍTÁS" esemény bejegyzésre is szükség van.

3. Az 1. pontnak egy speciális esete, ha nem a mérő áramkör bekapcsolása, hanem egyszerűen csak a telóról a memória terület nullázása történik úgy, hogy közben a rádugott fogyasztó BE van kapcsolva. Normál esetben ezután egy KI esemény fog történni és rögzítődni, aminek ugye nincs BE előzménye, hiszen töröltük.

A MEMÓRIATERÜLET TÖRLÉS UTÁN TEHÁT ÚJRA KELL OLVASNI ÉS TÁROLNI A FOGYASZTÓ STÁTUSZÁT, ÉS HA "BE" AKKOR RÖGZÍTENI.

A fenti módszerekkel ki van küszöbölve az, hogy KI eseménnyel kezdődjenek a letárolt adatok.

A program a jobb érthetőség miatt több helyen kommentezve van. Íme:


#include "Wire.h"
#include <EEPROM.h>
#include <SoftwareSerial.h>         // Ez a BlueTooth soros kommunikációjához kell

#define DS3231_I2C_ADDRESS 0x68
#define CURRENT_SENSOR A0           // Analóg bemenet az áramérzékelő számára

#define rxPin 2                     // Define SoftwareSerial rx data pin  , azaz a BlueTooth RX
#define txPin 3                     // Define SoftwareSerial tx data pin  , azaz a BlueTooth TX  

SoftwareSerial BlueTooth(rxPin, txPin);  // create instance of SoftwareSerial  , ez a BlueTooth soros kommunikációjához kell

byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  
byte byteRead;     // Soros port (bluetooth) beolvasáskor ide olvasunk
byte ByteSorszam;  // Megadja, hogy hányadik byte beolvasásánál tartunk a BT modul felől

byte EV1;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott év első byte -ja
byte EV2;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott év második byte -ja
byte HON;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott hónap érték
byte NAP;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott nap érték
byte NA_;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott hét napja ( Appinventor: Weekday, Arduino: dayOfWeek )
byte ORA;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott óra érték
byte PER;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott perc érték
byte MAS;          // Soros port (bluetooth) beolvasáskor ide kerül az Android eszköztől kapott másodperc érték

int Aram;         // Az áramérzékelő működését jelzi

int Mode = 0;			/* Ezzel jelezzük, hogy az aktuális áram BE - Ki kapcsolás naplózásával hol tartunk, ill. ha most kapcsoltuk be a mérőt
                     0 - alapeset
                     5 - áram bekapcsolás történt
                     6 - áram kikapcsolás történt az előző bekapcsolás óta 
                     7 - a mérő most lett bekapcsolva ( Start ) */

int Akt;    		  // Ez mutatja az EEPROM -ban a legutóbb beírt ( Aktuális ) bejegyzés címét.
                  // Ennek TIZED részét letároljuk az EEPROM 0. címére, hogy áramszünet után is tudjuk hol tartunk.
                  // Azért a tized részét, mer csak 255 -öt tudnánk egyébként letárolni, és úgyis csak minden 10. tárhelyre mutathat.
                  // Tehát ha 0. -on 1 van akkor Akt=10,
                  //       ha 0. -on 2 van akkor Akt=20, stb.
                  /* A legeslegelső bejegyzés a Mem_kezdet tárhelyre kerül, mert az előtte levő tárhelyet fenntartjuk egyéb célokra.
                     Egy bejegyzés 10 byte, ami a következőképpen épül fel:

                    1. byte:  " + " a byte sorozat elejét jelző karakter
                    2. byte:  ÉV
                    3. byte:  HÓNAP
                    4. byte:  NAP
                    5. byte:  ÓRA  
                    6. byte:  PERC
                    7. byte:  MÁSODPERC
                    8. byte:  Mode
                    9. byte:  fenntartva későbbi célokra
                   10. byte:  " - " a byte sorozat végét jelző karakter */  
                  
					        // Írás Akt+10 címre történik, kivéve ugye ha a memória végén vagyunk, mert akkor a 'Mem_kezdet' -re visszaugorva írunk,
                  // felülírva az esetlegesen ott levő - régebbi - adatokat.
					        // Olvasás Akt+10 -től Akt -ig, figyelembe véve a memória végét.
					        // Ha még nincs teljesen feltöltődve a memória adatokkal akkor 0 -kat olvasunk ( vagy amivel előre feltöltöttük ), azt le kell kezelni kiíratáskor

int Mem_kezdet = 20 ;   // A használható memória első byte -jának címe
int Mem_plafon = 800 ;  // E fölötti címekre már nem írhatunk adatot ( az UNO -nál elvileg 1024 byte az EEPROM mérete, tehát efölé semmiképp nem szabad venni )
                        // NAGYON FONTOS, hogy "Mem_plafon-Mem_kezdet" 20 -al osztható legyen, azaz pl. Mem_kezdet=20 és Mem_plafon=50 hibás működéshez vezet,
                        // mert a memória "beteléskor" amikor ugye a Mem_kezdet -nél folytatjuk az írást egy Be-Ki adatpárosnak csak az egyik ( Be ) fele íródik
                        // felül, vagyis lesz egy "Ki" adatunk a levegőben, amivel az adatlekéréskor a adatküldés kezdődik, vagyis kiíráskor Be-Ki párosok
                        // helyett  Ki-Be párosok lennének, ami nyilván hibás és zavaró.
int Foglalt_blokk =0;   // Hány foglalt byte-tízes van a rendelkezésre álló ( Mem_kezdet és Mem_plafon közötti ) memóriaterületen
int MitAkar = 0;        /* Az Android eszköztől kapott byte, ami megadja, hogy mit szeretne tőlünk
                         *  - KÜLDHETI A PONTOS IDŐT                           ( a =  97 )
                         *  - LEKÉRDEZHETI A MI IDŐNKET ÉS A MEMÓRIA ADATOKAT  ( b =  98 )
                         *  - LEKÉRDEZHETI AZ EEPROMBAN TÁROLT ADATOKAT        ( c =  99 )
                         *  - KÉRHETI a TÁROLT ADATOK TÖRLÉSÉT                 ( d = 100 )
                        */

int sensorMin = 1024;
int sensorMax =    0;

/* ======================================================================================================================================================================= */
void setup()
{
  Wire.begin();
  Serial.begin(9600);               // Ezen megy a sima soros kommunikáció
  BlueTooth.begin(9600);            // Ezen megy a BlueTooth kommunikáció

  pinMode(LED_BUILTIN, OUTPUT);     // A beépített LED -et felgyújtjuk ha áramot érzékelünk
  
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year

  // A következő utasításra nincs szükség ha z RTC -ben van elem:
  // setDS3231time( 50, 59, 23, 1, 24, 4, 18)  ;   // Ezt a dátumot-időt állítja be induláskor: 2018.04.24. 23:59:50

  Akt = EEPROM.read(0) * 10;       // Első lefutáskor beállítjuk Akt -ba a legutóbb beírt adat-tízes memóriacímét

  delay(1000);                     // 1 sec késleltetéssel kezdjünk, hogy mindenki észhez térjen bekapcsolás után

  Mode = 7;                        // Csinálunk egy olyan bejegyzést, hogy a mérő épp most lett bekapcsolva ( Start )
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);   // Ezekre az adatokra szükség van a naplózásnál
  naplozas();                      // Ennek azért van jelentősége hogy az eredmények kiértékelésekor tudatában legyünk.
                                   // Jó lenne valahogy a kikapcsolást is rögzíteni, de az a jellegéből adódóan nem kivitelezhető
                                   // a mostani tudásommal.
  Mode = 0;                        // Miután benaplóztuk visszaállítjuk a kiindulási értékre.
  

  Serial.println(" ************************* Android EEPROM tartalom 0 - 200 *******************************:");  

  for ( int i = 0 ; i < 200; i=i+10 )  // 10 -esével lépegetünk, először az Akt utáni byte-tízestől a memória terület végéig
      {
             
               Serial.print(i);                
                Serial.print(":");
            for (int k=0 ; k<10; k++)             // Itt már 1 -esével lépünk végig a byte-tízes elemein          
               {
                
                Serial.print(EEPROM.read(i+k));
                Serial.print("-");                
               }
            Serial.println();

      }
}

/* ======================================================================================================================================================================= */
void loop()
{
 
  bt_kezeles();                                       // Ha jön a soros porton valami, beolvassuk

  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); 

  getMinMaxValue();                                   // Beolvassuk az áramérzékelőből az adatokat ( ami 1 másodpercig tart ), sensorMin -ben és sensorMax -ban kapjuk.
  if ( sensorMax-sensorMin > 100 ) Aram = 1 ;
  if ( sensorMax-sensorMin < 100 ) Aram = 0 ;  
  
// Óvatosan a kiíratásokkal, mert lelassítja a programot ami hibás működéshez vezet  !!!
  Serial.print(" Áram = ");  
    Serial.println(Aram); 
  
  if (( Aram == 1 ) && ( Mode == 0 ))    	// Ha nyomva lett, és még nem lett naplózva akkor naplózzuk
     {
      digitalWrite(LED_BUILTIN, HIGH);
      Mode = 5;                           // Ezzel jelezzük, hogy lenyomást kell naplózni
	   	naplozas();
     }

  if (( Aram == 0 ) && ( Mode == 5 ))      // Ha nincs nyomva, de előzőleg nyomást naplóztunk az azt jelenti, hogy most engedték el, tehát   
     {
       digitalWrite(LED_BUILTIN, LOW);      
		   Mode = 6;                           // Ezzel jelezzük, hogy elengedést kell naplózni
		   naplozas();                         // naplózzuk az elengedést
		   Mode = 0;						               // Vége egy nyomás-elengedés naplózási ciklusnak
     }  

// Óvatosan a kiíratásokkal, mert lelassítja a programot ami hibás működéshez vezet  !!!

 // delay(1000);

}


/* ======================================================================================================================================================================= */
/* ====================================================== FÜGGVÉNYEK: ==================================================================================================== */
void naplozas()
{

  /* Az Akt tehát mindig a legutóbb beírt byte-tízes-csomag első byte -jára mutat  */

  if ( (Mode == 5) || (Mode == 6) || (Mode == 7))      // Ha nyomás, elengedés vagy új bekapcsolás történt akkor naplózzuk
     {
      if ( Akt+10 >= Mem_plafon )         // Ha a következő írás már a megadott memória cím limitre vagy fölé esne
         { Akt = Mem_kezdet; }        // akkor visszamegyünk a memória elejére,
           else
         { Akt = Akt + 10; }          // ha nem, akkor egyszerűen csak egy adaggal feljebb ugrunk a következő írható byte-tízesre */

      // Írunk az EEprom -ba. A struktúrát lásd fentebb.
      EEPROM.write(Akt, '+');       Akt++; delay(200);
      EEPROM.write(Akt, year);      Akt++; delay(200);
      EEPROM.write(Akt, month);     Akt++; delay(200);
      EEPROM.write(Akt, dayOfMonth);Akt++; delay(200);
      EEPROM.write(Akt, hour);      Akt++; delay(200);
      EEPROM.write(Akt, minute);    Akt++; delay(200);
      EEPROM.write(Akt, second);    Akt++; delay(200);
      EEPROM.write(Akt, Mode);      Akt++; delay(200);        // A Mode jelzi, hogy milyen esemény történt az adott időpontban, azt is beírjuk a végére 
      EEPROM.write(Akt, '-');       Akt++; delay(200);
      EEPROM.write(Akt, '-');       Akt++; delay(200);
      Akt = Akt - 10;                                            // Hiszen Akt mindig a legutóbbi byte-tízes első byte -jára mutat
      EEPROM.write(0, Akt/10); delay(200);                       // Letároljuk Akt/10 -et a 0. címre. Hogy miért /10 lásd fentebb
     }
}

/* -------------------------------------------------------------------------------- */
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}

/* -------------------------------------------------------------------------------- */
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

/* -------------------------------------------------------------------------------- */
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:
    Serial.println("Sunday");
    break;
  case 2:
    Serial.println("Monday");
    break;
  case 3:
    Serial.println("Tuesday");
    break;
  case 4:
    Serial.println("Wednesday");
    break;
  case 5:
    Serial.println("Thursday");
    break;
  case 6:
    Serial.println("Friday");
    break;
  case 7:
    Serial.println("Saturday");
    break;
  }
}

/* -------------------------------------------------------------------------------- */
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}

/* -------------------------------------------------------------------------------- */
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}

/* -------------------------------------------------------------------------------- */
void bt_kezeles()
{

/* Ezt a függvényt kell gyúrnunk hogy az Android -os eszközzel megfelelő legyen a kommunikáció 
 *  
 * Először is meg kell állapítanunk, hogy az Android -os eszköz mit akar.  
 *  - KÜLDHETI A PONTOS IDŐT                           ( a =  97 )
 *  - LEKÉRDEZHETI A MI IDŐNKET ÉS A MEMÓRIA ADATOKAT  ( b =  98 )
 *  - LEKÉRDEZHETI AZ EEPROMBAN TÁROLT ADATOKAT        ( c =  99 )
 *  - KÉRHETI a TÁROLT ADATOK TÖRLÉSÉT                 ( d = 100 )
 *  
 *  Ezeket úgy jelzi, hogy elküldi a kívánt dolog kódját
*/

  // Először is 
  MitAkar = 0;                          // Tiszta lappal indulunk
  if  ( BlueTooth.available() )         // Ha van mit olvasni
      { 
        byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
        Serial.write(byteRead);         // Vissza echo -zzuk
        MitAkar = byteRead;
      }

// Elvileg a MitAkar csak a fenti négy érték valamelyikét veheti fel mert azt kaphatjuk csak az Android eszköztől. 
// Ezeket az eseteket a következő négy if feltétellel kezeljük le:


if ( MitAkar == 97 )   // AZ ANDROID -OS ESZKÖZ KÜLDI A PONTOS IDŐT
{  
/*  A BT modul felől soros porton érkezik a pontos idő a következő formátumban:

    1. byte:  " + " a byte sorozat elejét jelző karakter
    2. byte:  ÉV első byte
    3. byte:  ÉV második byte. Hogy megkapjuk a helyes évet ezt 256 -tal kell szorozni, majd hozzáadni a 2. byte -ban kapott értéket
    4. byte:  HÓNAP
    5. byte:  NAP
    6. byte:  HÉT NAPJA
    7. byte:  ÓRA  
    8. byte:  PERC
    9. byte:  MÁSODPERC
   10. byte:  " - " a byte sorozat végét jelző karakter
    
*/  
      ByteSorszam = 1;                         // Megadja, hogy hányadik byte beolvasásánál tartunk a BT modul felől

      if  ( BlueTooth.available() )         // Ha van mit olvasni
          { 
            byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
            Serial.write(byteRead);      // Vissza echo -zzuk
            if ( byteRead == 43 ) ByteSorszam = 2 ;   // Továbblépünk a ciklusból
           }
     if ( ByteSorszam == 2 )                      // Ha az előbb beolvastuk az induló "+" karaktert, akkor beolvassuk a többi byte -ot is
     {
         while ( ByteSorszam == 2 )               // Ebben a ciklusban beolvassuk az ÉV érték első byte -ját
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     EV1 = byteRead;
                     ByteSorszam = 3 ;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 3 )               // Ebben a ciklusban beolvassuk az ÉV érték második byte -ját
               {                                  // A helyes évet úgy kapjuk, ha ezt 256 -tal kell szorozzuk, majd hozzáadjuk az EV1 -ben kapott értéket
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     EV2 = byteRead;
                     ByteSorszam = 4 ;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 4 )               // Ebben a ciklusban beolvassuk az HONAP értékét
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     HON = byteRead;
                     ByteSorszam = 5 ;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 5 )               // Ebben a ciklusban beolvassuk a NAP értékét
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     NAP = byteRead;
                     ByteSorszam = 6 ;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 6 )               // Ebben a ciklusban beolvassuk a "HÉT NAPJA" értékét
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     NA_ = byteRead;
                     ByteSorszam = 7 ;            // Továbblépünk a ciklusból
                   }
               }               
         while ( ByteSorszam == 7 )               // Ebben a ciklusban beolvassuk az ÓRA értékét
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     ORA = byteRead;
                     ByteSorszam = 8 ;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 8 )               // Ebben a ciklusban beolvassuk az PERC értékét
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     PER = byteRead;
                     ByteSorszam = 9 ;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 9 )               // Ebben a ciklusban beolvassuk a MÁSODPERC értékét
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     MAS = byteRead;
                     ByteSorszam = 10;            // Továbblépünk a ciklusból
                   }
               }
         while ( ByteSorszam == 10 )               // Ebben a ciklusban beolvassuk a záró " - " karaktert ( de nem csinálunk vele semmit )
               {    
                 if  ( BlueTooth.available() )       // Ha van mit olvasni
                   { 
                     byteRead = BlueTooth.read();    // Beolvasunk egy karaktert 
                     Serial.write(byteRead);      // Vissza echo -zzuk
                     ByteSorszam = 1 ;            // Továbblépünk a ciklusból
                     setDS3231time(MAS, PER, ORA, NA_, NAP, HON, EV2*256+EV1-2000)  ;    // Végül a beolvasott időt elküldjük az RTC -nek.
                   }       // Formátum: void setDS3231time(second, minute, hour, dayOfWeek, dayOfMonth, month, year)
               }           // A DS3231 az évnek csak a második 2 számjegyét várja, ezért kell kivonni a kiszámolt év értékéből ( EV2*256+EV1 ) 2000 -et.

       Serial.println ( "Az Android eszkoztol BT -on kapott ertek: " );       
       Serial.print ( " - EV1=" ); Serial.print ( EV1 );
       Serial.print ( " - EV2=" ); Serial.print ( EV2 );       
       Serial.print ( " - HON=" ); Serial.print ( HON );
       Serial.print ( " - NAP=" ); Serial.print ( NAP );
       Serial.print ( " - NA_=" ); Serial.print ( NA_ );
       Serial.print ( " - ORA=" ); Serial.print ( ORA );
       Serial.print ( " - PER=" ); Serial.print ( PER );
       Serial.print ( " - MAS=" ); Serial.println ( MAS );
       Serial.print ( " ----------- EV_szamolt=" ); Serial.println ( EV2*256+EV1 );
// delay(10000);
     }
} // Eddig tart az első funkció, azaz amikor az Android -os eszköz leküldi nekünk a pontos időt

if ( MitAkar == 98 )  // AZ ANDROID -OS ESZKÖZ LEKÉRDEZI A PONTOS IDŐT ÉS A MEMÓRIA ADATOKAT
{  

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

  BlueTooth.write("20");
  BlueTooth.print(year, DEC);
  BlueTooth.write(".");  
  BlueTooth.print(month, DEC);
  BlueTooth.write(".");  
  BlueTooth.print(dayOfMonth, DEC);
  BlueTooth.write("  ");  
  BlueTooth.print(hour, DEC);
  BlueTooth.write(":");  
  BlueTooth.print(minute, DEC);
  BlueTooth.write(":");  
  BlueTooth.print(second, DEC);    // Eddig tartott a dátum és idő elküldése, de még elküldjük a memória foglaltságra vonatkozó adatokat * -al szeparálva:

  BlueTooth.write("*");                                  // Szeparátor, az androidos eszköz innen tudja, hogy más adat következik
  BlueTooth.print( (Mem_plafon-Mem_kezdet)/10, DEC);     // Elküldjük az androidnak a rendelkezésre álló memóriaterület méretét
  BlueTooth.write("*");                                  // Megint szeparátor

  Foglalt_blokk = 0;
  for ( int i = Mem_kezdet ; i < Mem_plafon; i=i+10 )  // 10 -esével lépegetünk, hiszen ennyiből áll egy byte-tízes blokk
      {
       if ((EEPROM.read(i) == 43) && (EEPROM.read(i+9) == 45))            // Megszámoljuk azokat a byte-tízeseket, amikben van érvényes adat
                                                   // Sajnos bizonyos esetekben, pl. az áramkör kikapcsolásánál előfordulhat, hogy egy 10 -es rekord
                                                   // csak félig van beírva. Ezért megnézzük hogy az első és utolsó marker byte -jai érvényesek-e,
                                                   // azaz az első byte '+', az utolsó pedig '-' -e. Ha igen, feltételezzük hogy a köztük levő adatok jók.
          {
            Foglalt_blokk++;                            // Itt már 1 -esével lépünk végig a byte-tízes elemein          
          }
      }
  BlueTooth.print(Foglalt_blokk, DEC);                  // Elküldjük az androidnak a foglalt byte-tízesek darabszámát

  // send it to the serial monitor
  Serial.print(" -------------------------Android -nak küldve ----------------------------:");  
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");

  
} // Eddig tart a második funkció, azaz amikor az Android -os eszköz lekérdezi tőlünk a pontos időt és a memória adatokat

if ( MitAkar == 99 )  // AZ ANDROID -OS ESZKÖZ LEKÉRDEZI AZ EEPROM TARTALMÁT
{  

   /* Az adatokat Akt+10 memóriacímtől kezdődően kezdjük olvasni és továbbítani.
      Ha elértünk a Mem_plafon -ig, akkor Mem_kezdet -ig visszaugrunk és onnan folytatjuk az olvasást egészen Akt -ig, 
      hiszen ott van a legutóbb beírt adat, és ezzel az olvasás vége.
      Ha még nem töltődött fel teljesen a memória adatokkal, Akt+10 -ről és esetleg az utána levő byte-tízesekről 0 -kat olvasunk 
      ( vagy amivel előre feltöltöttük ), azokat természetesen fölösleges elküldenünk. Ezt legegyszerűbben úgy figyelhetjük, 
      ha a byte-tízes első byte -ját nézzük hogy '+' -e, azaz 43 -e.
   */

  Serial.print(" ************************* Android -nak küldve *******************************:");  

  for ( int i = Akt+10 ; i < Mem_plafon; i=i+10 )  // 10 -esével lépegetünk, először az Akt utáni byte-tízestől a memória terület végéig
      {
       if ((EEPROM.read(i) == 43) && (EEPROM.read(i+9) == 45))            // Csak akkor foglalkozunk a byte-tízessel, ha van benne valami rendes adat.
                                                   // Sajnos bizonyos esetekben, pl. az áramkör kikapcsolásánál előfordulhat, hogy egy 10 -es rekord
                                                   // csak félig van beírva. Ezért megnézzük hogy az első és utolsó marker byte -jai érvényesek-e,
                                                   // azaz az első byte '+', az utolsó pedig '-' -e. Ha igen, feltételezzük hogy a köztük levő adatok jók.
          {
            for (int k=0 ; k<10; k++)             // Itt már 1 -esével lépünk végig a byte-tízes elemein          
               {
                BlueTooth.write(EEPROM.read(i+k));          // Ez egyben küldi el a karaktert,  tehát ha pl. az ÉV -nél 18 van, akkor egy 18 -as byte -ot küld
                Serial.print(i+k);                
                Serial.print(":");                                
                Serial.print(EEPROM.read(i+k));
                Serial.print("-");                
               }
          }
      }

  for ( int i = Mem_kezdet ; i < Akt+10; i=i+10 ) // 10 -esével lépegetünk, mostmár a memória terület kezdetétől Akt -ig
      {
       if ((EEPROM.read(i) == 43) && (EEPROM.read(i+9) == 45))            // Csak akkor foglalkozunk a byte-tízessel, ha van benne valami rendes adat.
                                                   // Sajnos bizonyos esetekben, pl. az áramkör kikapcsolásánál előfordulhat, hogy egy 10 -es rekord
                                                   // csak félig van beírva. Ezért megnézzük hogy az első és utolsó marker byte -jai érvényesek-e,
                                                   // azaz az első byte '+', az utolsó pedig '-' -e. Ha igen, feltételezzük hogy a köztük levő adatok jók.
          {
            for (int k=0 ; k<10; k++)             // Itt már 1 -esével lépünk végig a byte-tízes elemein          
               {
                BlueTooth.write(EEPROM.read(i+k));          // Ez egyben küldi el a karaktert,  tehát ha pl. az ÉV -nél 18 van, akkor egy 18 -as byte -ot küld
                Serial.print(EEPROM.read(i+k));
                Serial.print("-");                                
               }
          }
      }


  Serial.println();  

  
} // Eddig tart a harmadik funkció, azaz amikor az Android -os eszköz lekérdezi tőlünk az EEPROM -ban tárolt adatokat

if ( MitAkar == 100 )  // AZ ANDROID -OS ESZKÖZ KÉRI AZ EEPROM TARTALMÁNAK TÖRLÉSÉT
{  

   /* Az adatokat Akt+10 memóriacímtől kezdődően kezdjük olvasni és továbbítani.
      Ha elértünk a Mem_plafon -ig, akkor Mem_kezdet -ig visszaugrunk és onnan folytatjuk az olvasást egészen Akt -ig, 
      hiszen ott van a legutóbb beírt adat, és ezzel az olvasás vége.
      Ha még nem töltődött fel teljesen a memória adatokkal, Akt+10 -ről és esetleg az utána levő byte-tízesekről 0 -kat olvasunk 
      ( vagy amivel előre feltöltöttük ), azokat természetesen fölösleges elküldenünk. Ezt legegyszerűbben úgy figyelhetjük, 
      ha a byte-tízes első byte -ját nézzük hogy '+' -e, azaz 43 -e.
   */

  Serial.print(" 00000000000000000000  TÖRÖLJÜK AZ ADATOKAT 000000000000000000000000000:");  

  for (int i = 0 ; i <= Mem_plafon ; i++)      // Mindent nullázunk az elejétől a lehetséges memória plafonig
    {
      EEPROM.write(i, 0);
    } 

  Akt = Mem_kezdet;                          // Az Akt értékét is újra generáljuk, de azt nem szabad elfelejteni, hogy ezzel a sorral azt adjuk meg,
                                             // hogy legutóbb a Mem_kezdet -re lett adat beírva, tehát az ezutáni beírás a Mem_kezdet+10 címre fog kerülni.
                                             // Így memória törlés után az első beírt adat tulajdonképpen nem a Mem_kezdetű byte-tízesre, hanem az
                                             // azt követőre esik, de ennek nincs jelentősége.
  EEPROM.write(0, Akt/10); delay(200);       // Akt értékét letároljuk a memória 0. byte -ján. Hogy miért /10 lásd fentebb. Utána szusszanunk egyet.
  Mode = 0;                                  // Ez egy nagyon fontos utasítás. Előfordulhat, hogy akkor kér törlést az Android eszköz, amikor a fogyasztó
                                             // be van kapcsolva. Ekkor ugye a BE kapcsolást még a törlés előtt rögzítettük ( azaz eltűnt ), és most
                                             // KI kapcsolás várható. Vagyis KI -vel kezdődne az adatsor, ami nem szerencsés. Ezzel az utasítással azt
                                             // érjük el, hogy memória törlést követően legyen letárolva egy BE esemény ha a fogyasztó BE van kapcsolva. 
  Serial.println();  

  
} // Eddig tart a negyedik funkció, azaz amikor az Android -os eszköz azt kéri, hogy töröljük az EEPROM -ban tárolt adatokat

               
               // Csak a fenti négy eset lehetséges, ha a négy kódon kívül valami más érkezik akkor nem reagálunk

}

/* -------------------------------------------------------------------------------- */
 
void getMinMaxValue()
{
    int sensorValue;    //value read from the sensor
    
    sensorMin = 1024;
    sensorMax =    0;    
    uint32_t start_time = millis();
    while((millis()-start_time) < 200) // Mintavétel 200 ms -ig. A mintában 1000 ms volt, de az nagyon lelassítaná a programot
    {
        sensorValue = analogRead(CURRENT_SENSOR);
        if (sensorValue > sensorMax)
        {
            sensorMax = sensorValue;
        }
        if (sensorValue < sensorMin)
        {
            sensorMin = sensorValue;
        }        
    }
}

A másik rész az Android -os alkalmazás, amit ezúttal is az App Inventor segítségével állítottam össze. Nem kommentezem, de ha valami nem érthető ismétcsak javaslom átnézésre a Nyomógomb naplózó leírását. Vagy keress meg, szívesen elmagyarázom. A Designer -ben létrehozott fő képernyő így néz ki:

Működés_naplózó

Természetesen itt is van egy második képernyő, aminek az adatkiíráskor van szerepe: Működés_naplózó

Ezután következzen maga a "program", vagyishát a program blokkok. A Screen1 -hez tartozó program nem túl bonyolult ezért csak nagyvonalakban kommenteztem. Ha így nem annyira érthető légyszíves nézd meg a Nyomógomb naplózó leírásában, elég nagy a hasonlóság. Itt is egy időzítő adja a lényegi részt ami 1 másodpercenként fut le. Az eszköz ennyi időközönként küld egy 98 ( azaz "b" ) karaktert az órának, ami abból tudja, hogy vissza kell küldenie az idejét. Ezáltal tud frissülni a második felső sorban látható óra idő ( a szemléletesség kedvéért 0-12 formában kiírva ). Lehetőség van természeten a Naplózó idejének beállítására is. Ha a felhasználó el szeretné kérni a Naplózótól az eddig letárolt adatokat azt egy 99 -es kód ( azaz 'c' karakter ) elküldésével kezdeményezi egy másik időzítőben ( ami 1 ms -onként fut ). Ennek hatására a Naplózó elküldi az adatokat, amik ha rendben vannak, megnyílik egy másik screen ( lásd lentebb ). Tehát a program:


Működés_naplózó

A másik rész az adatkiírás. A Naplózótól származó "nyers" adatokat az ItemList listába tesszük, amit feldolgozunk. A feldolgozás végén két listát kapunk. Egy "magyart" ( HU_List ) amit majd a végén ki is íratunk, illetve egy "angolt" ( EN_List ). Ez utóbbi azért szükséges, mert van egy rutin ami az egyik dátum-időből ki tud vonni egy másikat, azaz ki tudja számolni a két dátum-idő közötti különbséget, viszont az csak angol dátum-idő formátummal tud dolgozni.

Fontos még megemlíteni, hogy itt implikáltam be először azt, hogy a listában szerepeljen magának a Naplózónak a Be ill. Kikapcsolása. Erre azért van szükség, mert igen erőteljesen bekavarhat, ha mondjuk a fogyasztó be van kapcsolva, és úgy kapcsoljuk ki majd vissza a Naplózót ( és ezzel együtt persze a fogyasztót is, hiszen azonos a bemenetük ). Ezeket a speciális eseteket leírtam fentebb az Arduino -s kód elején levő kommentekben. Itt csak annyi a fontos, hogy az adatsorban egy 7 -es kód jelzi a bekapcsolást. A Be kapcsolásnak tudjuk az idejét, viszont hogy előtte mikor volt kikapcsolás azt nem ( nyilván azt is lehetne valahogy rögzíteni, de elbonyolítaná a Naplózó hardverét, ezért nem foglalkoztam vele ). Ezért a Ki kapcsolást egy kérdőjeles dátummal-idővel jelöljük. Itt természetesen korrekt működési időt sem tudunk számolni. Az alábbi képernyő mentésen több ilyen bekapcsolás ( Start ) is látható : Működés_naplózó

Lehetőség van a file -ba mentésre, amihez az alkalmazás az "Eszkoz_adatok.txt" alapértelmezett nevet ajánlja fel, de átírható. Ha már létezik a file felülírja. Ja, bocs, majdnem elfelejtettem a programot :-). Íme:

Működés_naplózó

Működés közben az Android -os eszközön látható képernyőket mutatják az alábbi képek. Itt is azt tudom leírni, amit a LED -es óránál írtam :-). A felső sorban van az Android -os eszköz saját ideje, alatta a Naplózó ideje, tehát amit a Naplózó bluetooth -on átküldött az Android -os eszköznek. Nyilván ha még nem jött létre a BT kapcsolat akkor itt csak kérdőjeleket láthatunk. Ha nincs bekapcsolva az Android -os eszközön a bluetooth akkor a felső gomb pirossal hívja fel erre a figyelmet. Az alkalmazásból nem lehet bekapcsolni ( még, de lehet hogy egy következő verzióban már lehet majd :-). Ha engedélyezett a bluetooth ( felső gomb zöld ) akkor össze kell kapcsolódni az eszközzel. Ezt a második ( egyelőre piros ) gombra bökve lehet megtenni. A felkínált eszközök közül a HC-06 -ot kell választani. Ha minden jól megy ez is bezöldül, és fent a második sorban megjelenik a Naplózótól kapott idő. Ha úgy ítéljük hogy ez az idő nem pontos, a harmadik gomb megnyomásával kezdeményezhetjük az Android -os eszköz ( nyilvánvalóan pontos ) idejének átküldését a Naplózó áramkörnek. Az átküldés megtörténtét egy üzenet jelzi, ill. a felső második sorban ellenőrizhető.

További két gomb szolgál a Naplózóban tárolt adatok elkérésére ( letöltésére az Android -os alkalmazásnak ), illetve törlésére. Az adatok tehát nem az Androidos eszközön törlődnek ezáltal, hanem a Naplózóban. Nincs mód a visszaállításra.

A második ( Adat_kiír ) képernyőn láthatjuk az áttöltött adatokat, amiket lementhetünk file -ba is.

Ezzel végére értem a leírásnak, köszönöm hogy elolvastad !


 JozsBiker, 2021