torstai 10. toukokuuta 2018

VILKKU

On toki oikeutettua kysyä, onko tämän pitkän tauon aikana kaikki unohtunut, kun pitää jälleen siirtyä alkeisiin, eli vilkuttamaan LEDiä? Päivät ovat täyttyneet kaikenlaisesta muusta menneen talven aikana.

Nyt kuitenkin tuli jo kiire kehitellä ensi kesäksi uutta aurinkopaneelin kääntäjäprotoa (jokainen edellistä yksinkertaisempi), ja siinä yhteydessä syntyi ajatus: voisiko noiden parin LEDin avulla saada yksinkertaisella ohjelman pätkällä aikaan enemmän informaatiota toiminnan tilasta kuin pelkästään toimii / seis?
    Kun aurinko siirtyy kolme (3) tuntia paneelin suunnasta sivuun, putoaa paneelin tuotto noin puoleen. Toisin sanoen, jos paneeli seuraa aurinkoa klo 9 .. 15, (6h eli 90 astetta), tuottaa paneeli klo 6 – 9 keskim. 75% ja siitä eteenpäin 9 – 15 yli 90% (jos korjataan esim. kerran tunnissa). Sitten taas klo 15 – 18 keskim. 75%. Aurinkoa seuraamalla korvataan käytännössä yhden paneelin tuotto. Pilvet tietysti sotkevat tämän optimismin!
    Minulle on myös sanottu (ja epäilty), että paneelin tuotto kuluu nimenomaan tähän kääntämiseen. Minulla on ollut jo useamman kerran käytössä veneen lasinpyyhkijän moottorit (hiukan modifioituina). Ne toimivat 12 V:n jännitteellä ja niissä on sopiva vaihteisto.
    Tämä on pelkkää laskentoa: jos käännetään kuusi (6) kertaa ja yksi tunnin kääntö kestää yhden (1) minuutin, kuluttaa kääntö 6 Amin aamusta iltaan plus paluu toiset kuusi Ah. Mikrokontrolleri on kuitenkin päällä ja kulutta sähköä koko ajan, joten jos se kuluttaa 5 mA (<Leonardo, UNO noin 150mA, tietysti riippuu ja roikkuu!), kuluu siihen 1440min * 0,005A = 7,2 Amin. Yhteensä siis 13,2 Amin. Jos varaudutaan vaikkapa tuplaan, noin 30 Amin, eli 0,03 Ah:iin, niin 85W panelilta (tuotto noin 4A) kuluu tuotosta kääntäjän pyörittämiseen auringon heloituksessa noin 8 min.
Päässä pyörii jo ensi talven proto. Siinä ei lasin pyyhkijään tarvitse tehdä muutoksia, ja sen tulisi kääntää useampia rinnan olevia paneeleja yhdessä. Saa nähdä toteutuuko??

Päädyin miettimisen jälkeen aliohjelmaan, minkä avulla yksi kaksivärinen LEDi tarjoaa kuusi (6) eri tilatietoa (sen lisäksi, että kumpikaan LEDi ei valaise). Ajattelin laittaa sen tänne blogiin ajatuksella, että sillä saattaisi olla käyttöä muillekin. Minulle ainakin myös jatkossa myös muissa sovelluksissa.
    Tässä ohjelmaesimerkissä on kuusi (6) painiketta. Käytännössä informaatio tulee tietysti prosessin tilatietoina. Aliohjelmassa ( void Fun_LEDit(int led, int toiminto){) on kolme toiminnallista askelta ja oletusaskeleena (default:) LEDien sammutus ja aikalaskurin palautus, jotta uusi ohjaus alkaisi aina LEDin syttymisellä
    Askeleet ovat: 1. LED palaa niin kauan kun tuloinformaatio on TOSI. 2. LEDin lyhyt välähdys ja loppu kokonaisajasta sammuneena ja 3. Kokonaisaika puolitetaan, jolloin LED on puolet ajasta valo päällä ja puolet ajasta pimeänä.
    Tämä valittavana kutsussa (esim. {Fun_LEDit(Con_LEDvih, 1), jolloin vihreä valo palaa niin kauan kuin tulo on aktiivinen. Eli pääohjelman kutsussa määritellään kahdella parametrilla, kumpi LEDi aktivoituu ja millä tavalla.
    Jos mikään ohjaus ei ole aktiivinen, kutsutaan oletusaskelta (}else{Fun_LEDit(0, 0);}), missä molemmat LEDit ohjataan nollaan ja aika palautetaan alkuun, jotta seuraava ohjaus alkaa LEDin syttymisellä.

Koska tulot (tässä tapauksessa) on määritelty sisäisesti ylös (pinMode(Con_Pain1, INPUT_PULLUP );), muuttuu prosessorin tulo alas ( 1 → 0 ), käännetään tulon tilaa luettaessa huutomerkillä (!) (Bol_Pain1 = !digitalRead(Con_Pain1);). Tämä on kyllä vain ihmisen aivoja varten.

Tässäkin aliohjelmassa on tietysti rajoituksensa. Tämä edellyttää, että sille syötetään ainoastaan yksi tieto kerrallaan. Jos halutaan vilkuttaa useampaa lamppua samaan aikaan ja eri tahtiin, pitää aliohjelmalle välittää myös yksilöllinen aikainformaatio. Samoin pitää myös valojen sammutus valvoa yksilöllisesti. Tässä sen toteuttaa oletusaskel (default:), mikä edellyttää, että aliohjelmaa ei kutsuta lainkaan.
    Jos nuo ajat (919 ja 43) ihmetyttävät, niin niiden lukuarvoilla ei sinänsä ole merkitystä. Noilla ajoilla (monien muiden lähellä olevien lisäksi) vilkutus tuntui sopivalta. Mutta miksi juuri noin oudot luvut? Molemmat ovat alkulukuja ja niiden valinnan taustalla on viimeaikainen toisen ohjelmointikielen (python) harjoitteleminen. Sen harjoituksissa on ollut hauskoja ”numeromurskausjuttuja”, mm. alkulukujen (jaollinen vain yhdellä(1) ja itsellään) laskeminen. Toinen kiva harjoitus purki tietoa, että kaikki luonnolliset luvut ovat alkulukujen tuloja. Esim. kertolasku 2*3*3*5*3607*3803 antaa tulokseksi luvun : 1234567890. Numerot ovat hauskoja!
 
OHJELMA 53
 
/***************************************
* Vilkku_v1
* 10.05.2018
* Laajempaa LEDi-informaatiota
**************************************/

// MÄÄRITTELYT:
// Ledit
const int Con_LEDpun = 2; // Ohjaukset seis
const int  Con_LEDvih = 3; // Automaatilla

// Tulot
const int  Con_Pain1 = 4;
boolean Bol_Pain1 = false;
const int  Con_Pain2 = 5;
boolean Bol_Pain2 = false;
const int  Con_Pain3 = 6;
boolean Bol_Pain3 = false;
const int  Con_Pain4 = 7;
boolean Bol_Pain4 = false;
const int  Con_Pain5 = 8;
boolean Bol_Pain5 = false;
const int  Con_Pain6 = 9;
boolean Bol_Pain6 = false;

// Muutamia perusmäärityksiä
const int Con_Kierros = 919; // Kokonaiskesto
const int Con_Ero = 43; // Pilkahdusaika
int Int_Kierros = Con_Kierros;// Keston välimuisti

// ALIOHJELMAT
// LEDien ohjaus
void Fun_LEDit(int led, int toiminto){
   switch (toiminto) {
     case 1: // Jatkuva
     digitalWrite(led, HIGH);
   break;
   case 2: // Pilkahdus
     if (Int_Kierros > (Con_Kierros - Con_Ero))
       {digitalWrite(led, HIGH);
    }else{digitalWrite(led, LOW);}
       Int_Kierros = Int_Kierros - 1;
     if (Int_Kierros == 0){Int_Kierros = Con_Kierros;}
   break;
   case 3: // Vilkku
     if (Int_Kierros > (Con_Kierros / 2))
       {digitalWrite(led, HIGH);
     }else{digitalWrite(led, LOW);}
       Int_Kierros = Int_Kierros - 1;
    if (Int_Kierros == 0){Int_Kierros = Con_Kierros;}
   break;
   default: // LEDien sammutus ja ajan palautus
     digitalWrite(Con_LEDvih, LOW);
     digitalWrite(Con_LEDpun, LOW);
     Int_Kierros = Con_Kierros;
   }// sekvenssi loppu
}// LEDien funktion loppu

// ASETUKSET:
void setup(){
Serial.begin(9600);
pinMode(Con_LEDpun, OUTPUT);
pinMode(Con_LEDvih, OUTPUT);
pinMode(Con_Pain1, INPUT_PULLUP );
pinMode(Con_Pain2, INPUT_PULLUP);
pinMode(Con_Pain3, INPUT_PULLUP);
pinMode(Con_Pain4, INPUT_PULLUP);
pinMode(Con_Pain5, INPUT_PULLUP);
pinMode(Con_Pain6, INPUT_PULLUP);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){
Bol_Pain1 = !digitalRead(Con_Pain1);
Bol_Pain2 = !digitalRead(Con_Pain2);
Bol_Pain3 = !digitalRead(Con_Pain3);
Bol_Pain4 = !digitalRead(Con_Pain4);
Bol_Pain5 = !digitalRead(Con_Pain5);
Bol_Pain6 = !digitalRead(Con_Pain6);

if (Bol_Pain1 == true){Fun_LEDit(Con_LEDvih, 1); // jatkuva
}else if(Bol_Pain2 == true){Fun_LEDit(Con_LEDpun, 1);
}else if(Bol_Pain3 == true){Fun_LEDit(Con_LEDvih, 2); // pilkahdus
}else if(Bol_Pain4 == true){Fun_LEDit(Con_LEDpun, 2);
}else if(Bol_Pain5 == true){Fun_LEDit(Con_LEDvih, 3); // tasavilkku
}else if(Bol_Pain6 == true){Fun_LEDit(Con_LEDpun, 3);
}else {Fun_LEDit(0, 0);} // LEDien sammutus (default)
delay(1);
} // Pääohjelma LOPPU