Main()

Ensto/Koodin dokumentaatio/Main/Main()

Käydään seuraavaksi läpi itse pääfunktio. Jälkikäteen ajateltuna useita kohtia pääfunktiosta olisi voinut toteuttaa omina funktioinaan, jotka olisivat tehneet pääfunktiosta helpommin luettavan ja lyhyemmän.

(Rivit 15-28)Vielä pääfunktion alkuvalmisteluja, jotka eivät kuulu itse päälooppiin. Aluksi tulostetaan debuggausmielessä tiedot kuormista ja vaiheista. Asetetaan running-muuttuja todeksi. Se vastaa pääloopin toistumisesta, tässä versiossa ohjelmaa sitä ei aseteta missään vaiheessa False:ksi. Haetaan globaalit muuttujat maxHour, maxPower ja startto pääfunktion käyttöön. Asetetaan startto True:ksi, jotta aikaisemmin aloittamamme threadi käynnistää varsinaisen toimintansa.

Käynnistämme myös chrono-ajastimen ajanlaskun ja asetamme kaksi aikamuuttujaa, latestMeasTime, johon tallennetaan ajastimen aika viimeisestä mittauksesta; ja latestPowerTime, joka kertoo milloin uusin maksimiteho on laskettu.

Seuraavaksi alkaa päälooppi, jota toistetaan jatkuvasti. Se alkaa riviltä 29 ja jatkuu riville 194.

(Rivit 31-45)Loopin alussa tarkistetaan onko tunti vaihtunut. Tämä tehdään vertaamalla RTC:stä saatuja arvoja measTime-listan arvoihin. Tallennamme myös myös minuutit ja sekunnit muuttujiin minutes ja seconds myöhempää käyttöä varten. Mikäli tunti on vaihtunut, nollataan kuormien ja vaiheiden tuntikulutukset ja asetetaan measTime:n arvot vastaamaan nykyistä tuntia.

(Rivit 47-51)Seuraavaksi lasketaan uusi maksimiteho, jota ohjattu järjestelmä pystyy keskimäärin käyttämään ylittämättä suurinta sallittua tunnin kulutusta. Tämä tehdään viiden sekunnin välein tässä versiossa ohjelmaa. Aluksi laskemme tunnin jäljellä olevan ajan käyttämällä RTC:stä saamiamme minuutteja ja sekunteja.

Jäljellä oleva aika sekunneissa on tunnin sekunnit 3600 – minuutit*60 – sekunnit. Suurin sallittu keskimääräinen teho on jäljellä oleva energia, joka saadaan tunnin maksimista ja tämänhetkisestä kokonaiskulutuksesta, jaettuna jäljellä olevana aikana(muutettuna tunneiksi, koska maksimienergia on annettu wattitunneissa). Lopuksi asetetaan aika siitä, milloin tämä on viimeksi tehty.

(Rivit 53-85) Seuraavassa osassa koodia tarkastetaan kuormista milloin niistä on viimeksi lähetetty kulutustietoja tietokantaan. Mikäli 10 sekuntia on kulunut, lasketaan aluksi keskiarvo tälle ajalle. Tähän käytetään funktiota getLast10Sec, joka palauttaa listan kuorman viimeisistä 10 sekunnin mittauksista. Jos jostain syystä listan pituus on nolla, asetetaan keskiarvoksi nolla, jotta vältetään nollalla jakaminen.

Määritämme input-muuttujaan mitä haluamme lähettää tietokantaan. Kyseessä on merkkijono. Siinä näkyy myös tietokannan rakenne. Ensimmäisenä on määritelty mittauksen nimi “Measurement” ja pilkku, jonka jälkeen määritellään tagit, joilla InfluxDB:ssä määritellään tiedot mittauksesta, kuten ID ja nimi. Tagien jälkeen syötteessä pitää olla välilyönti, jonka jälkeen määritellään varsinaiset field:it ja arvot. Meillä on kaksi field:iä, power ja totalEne, joille annetaan arvot kuorman tehon ja kulutuksen mukaan.

Määrittelemme myös url-muuttujaan jälleen tietokannaosoitteen ja kirjautumistiedot. Toisin kuin aikaisemmin, käytämme nyt write api end point:ia, emmekä query:a. Tämä siksi, että lähetämme nyt dataa InfluxDB:hen.

Seuraavaksi lähetämme datan post-requestin avulla, datana input-muuttuja, joka on vielä enkoodattu utf-8-muotoon(encode-funktion oletusarvo).

Lopuksi tyhjennämme kymmenen sekunnin kulutuksen listan kuormalta ja asetamme nykyisen ajan siksi, milloin lähetys on viimeksi suoritettu.

(Rivit 87-118)Tehdään sama asia kuin äsken, mutta nyt vaiheille. Koska syötteet ovat täysin samanmuotoiset, tätä varten olisi voitu luoda yksi funktio, johon annetaan parametrina joko kuormat tai vaiheet.

(Rivit 120-186)Seuraava pitkä osa koodia on tarkoitettu mittausten ja rajoitusten tekemiselle. Tämä suoritetaan puolen sekunnin välein ja huomioon otetaan itse mittauksissa ja ohjauksissa kulunut aika.

Valitsimme alunperin puolen sekunnin väliajan, koska SiPy:n oman AD-muuntimen epätarkkuuden johdosta jouduimme ottamaan erittäin paljon mittaustuloksia vakaan keskiarvon saamiseksi, joka hidasti ohjelmaa. Ulkoinen AD-muunnin ei kuitenkaan vaadi tätä, joten tätä aikaa voisi todennäköisesti pienentää helpostikin. Mittausten alussa SiPyn ledi asetetaan punaiseksi, jotta tiedetään että mittaus on käynnissä. Kun mittaus on tehty, ledi sammutetaan.

(Rivit 124-145)Nyt käydään kuormat yksi kerrallaan läpi. Jos kuorma on aktiivinen, eli virrankulkua siihen ei ole estetty, tehdään mittaus sen getCurrent-funktiolla. Seuraavaksi laskemme tehon vakioksi asettamallamme ja olettamallamme voltage-muuttujan avulla. Tehohan on virta kertaa jännite.

Seuraavaksi laskemme kulutetun energian. Tämä tehdään kertomalla teho kuluneella ajalla viime mittauksesta, jonka saamme erotuksena viime mittauksen ajasta(funktio getLastTime) ja nykyisestä ajasta, newTime-muuttuja. Oletamme, että teho on pysynyt vakiona tuon ajan. Lisäksi muutamme energian wattitunneiksi, koska se on energialle käyttämämme yksikkö.

Lopuksi päivitämme kuormaan tiedon tämän mittauksen ajasta ja kutsumme funktiota addCurHourEne, joka sekä lisää kuorman nykyiseen kulutukseen mitatun energian, mutta myös lisää mitatun tehon kuorman teholistaan.

Jos kuorma ei ole aktiivinen, merkitään sen teholistaan nollia ja seuraavaksi tarkistetaan mikä on kokonaisteho järjestelmässä. Tämä tiedetään laskemalla yhteen vaiheiden tehot, jotka saadaan funktiolla getLastPower. Voimme myös laskea katkaistun kuorman ennustetun kulutuksen, mikäli se kytkettäisiin takaisin päälle. Tämä saadaan kertomalla viimeinen mitattu virta(getLastCur) jännitteellä.

Mikäli kokonaisteho ja kuorman teho yhdessä alittavat suurimman sallitun tehon, voidaan kuorma kytkeä takaisin tehonrajoituksen puolesta. Täytyy myös tarkistaa, ettei vaiheen virta ylitä sallittua rajaa, joka tehdään vertaamalla vaiheen ja kuorman virtojen summaa maksimivirtaan.

Mikäli molemmat arvot alittuvat, voidaan kuorma automaattiohjauksen puolesta kytkeä takaisin päälle. Tämä tehdään kuorman funktiolla relayAutoClose.

(Rivit 147-168)Seuraavassa osassa koodia teemme mittaukset päävaiheille ja tarkistamme samalla, että niissä ei kulje liian suurta virtaa verrattuna niiden sulakkeisiin. Aluksi asetamme totalEne- ja totalPower-muuttujat nolliksi, joihin tulemme laskemaan vaiheiden arvojen summat. Näitä käytetään myöhemmin.

Käymme vaiheet yksitellen läpi ja asetamme kuormat prioriteettijärjestykseen, sen varalta että nämä olisivat vaihtuneet palvelimella. Otamme vaiheesta virran getCurrent-funktiolla ja jälleen laskemme tehot ja energiat, kuten kuormien yhteydessä. Lisäämme vaiheolioon kulutetun energian ja viimeisimmän tehon, sekä uuden tehon 10 sekunnin listaan. Lisäksi lisäämme totalEne- ja totalPower-muuttujiin vaiheen mittaustiedot.

Vertaamme myös vaiheesta mitattua virtaa sen sallittuun maksimivirtaan, joka saadaan funktiosta getMaxCur. Jos virta ylittyy, pudotamme yhden pienimmän prioriteetin kuorman, joka on aktiivinen. Tähän voitaisiin lisätä älyä sillä, että verrattaisiin virran ylitystä kuorman virtaan ja tällä löydettäisiin optimaalinen kuorma pudotukselle, mutta tämä myös hieman lisäisi kohdassa kuluvaa aikaa, varsinkin mitä enemmän kuormia olisi.

(Rivit 170-177)Seuraavaksi järjestämme vaiheet niiden listassa tehon mukaan, suurin teho ensimmäiseksi. Käytämme taas sort-funktiota, jonka key-parametrina käytämme lambda-avainsanaa ja funktiota getLastPower. Reverse-parametri kääntää listan suurimmasta pienimpään. Jos kokonaisteho on suurempaa kuin määritelty maksimi, pudotetaan vaiheista kuormia prioriteettijärjestyksessä. Vaiheet kuitenkin käydään läpi niiden tehojen mukaan, mikä on hyvä ottaa huomioon.

(Rivit 179-186)Aikaisemmin, kun on puhuttu releiden ohjauksesta, on varsinaisesti tarkoitettu vain ohjausmuuttujien asettamista. Nyt näitä kuormien ohjausmuuttujia käytetään ohjaamaan kuormien releitä. Käydään kuormat taas yksitellen läpi.

Otetaan ohjausmuuttujat getControlState-funktiolla, joka palauttaa ne kahden arvon tuplena(muuttumaton lista). Tallennetaan niiden arvot muuttujiin autoCont ja manualCont ja tallennetaan myös kuorman releen pinni muuttujaan relayPin. Lopuksi kutsutaan control-funktiota, joka suorittaa releiden ohjauksen sille annettujen parametrien mukaan.

(Rivit 188-194)Lopuksi sammutamme ledin, näyttääksemme että mittaus ja ohjaus on loppunut ja tulostamme muutamia arvoja debuggaustarkoituksessa. Lisäksi päivitämme erään bluetooth-characteristic:sin arvon, vastaamaan merkkijonoa, joka kertoo nykyisen tunnin kokonaiskulutuksen.

Näin pitkän merkkijonon lähettäminen ei kuitenkaan toiminut oikein, joten jätimme tämän ominaisuuden kehittämisen kesken. Ilmeisesti lähetettävän tiedon pituutta pystyy kuitenkin muuttamaan characteristic:sista. Lisäksi todellisessa tapauksessa lähetettäisiin todennäköisesti pelkkä numeerinen arvo. Kuitenkin, characteristic:sien arvoja vaihtamalla on mahdollista lähettää tietoa bluetoothin kautta älypuhelimelle tai muille laitteille.