Motto toteutui taas
kerran. Kyllä tuo Ohjelma 18 toimii, mutta ei tyydyttävästi. Myöhemmissä versioissa
muutos on tullut lähinnä ajan käsittelyyn. Ensimmäisessä versiossa CoL_EroSekunti = 999; jätätti aivan
liikaa. Arvo 985 jätätti hiukan, mutta liikaa ollakseen kello. Arvo 984 edisti
liikaa. Oli siis tehtävä jotain.
Epäilin noita
ajanvalintanauhassa (Seq_YlaRivi) olevia viiveitä delay(20). Syy niiden olemassa olemiseen
johtui ylärivin tekstien välkkymisestä. Näyttö rauhoittui osin, mutta kaikki ei
ollut kunnossa kuitenkaan. Välkkyminen johtui siitä, että jokaisella
ohjelmakierroksella näytön ylärivi tyhjennettiin (lcd.print("
");) ja heti perään teksti. Versiossa 2, jo käynnistettäessä (void setup(){ .. Fun_YlaRivi(1, Int_UT);) kutsutaan aliohjelmaa kerran ja
kirjoitetaan UT-otsikko. Myöhemmin kirjoitetaan ainoastaan kerran ja vain
silloin, kun otsikko muuttuu. Näyttö on rauhallinen laajasta katselukulmasta.
Kuten versioiden määrästä
voi päätellä, niin ihan putkeen ei heti mennyt. Välillä jätätti parikin
minuuttia vuorokaudessa ja välillä oli kuin katutrokarin kello: ” Osta!, tää on
hyvä kello, tää ei kauaa tuntia huitase!” Versiossa 5 päädyin jakamaan ohjelman
suorituksen nauhoille, jolloin mitään tarpeetonta tarkastelua (if) ei suoriteta. Tässä minuutit
päivitetään vasta silloin, kun sekunnit tulevat täyteen. Samoin käsitellään tunnit
minuuttien tullessa täyteen.
Tälle kellolle on
tarkoitus järjestää pidempiaikainen käyttö. Siksi kiinnitin sen alumiiniseen
kulmaan ja samalla kytkin jännitteen stabilisaattorin kautta. Kellon käyttö
tulee olemaan osana radioamatööriasemaa. Siellä on 12V akkusyöttö. Siksi myös
tuo kansainvälinen aika, mitä tuo harrastus käyttää. Akkusyöttö ei kuitenkaan
suoraan käy Arduinolle, joten alla 9V stabilisaattorin kytkentä.
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiym-zJCe7kf80_EOmd72vjJQ1knMKkguzasVNOE51i2ZBXA3y6NIY9WTaTjYn5tcLMppxZlFQtTsykzp7_4LkTmDYkjPugBaubjbxEY47L51oZm_RZtqtFh8i2mGZuaFWFW1Iz8jCLsXg8/s320/Ohjelma_18.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidUFxIaN9lMCBbor1Mxb1vCPya80RpPGdrYJN3hIB4JrfGUoL2RCAL9w1eunC2NmUok51U_z7HA5fRhJVGALaipNJnUHoG_S-9igGDpdwjI4L_90w8QvGyeKHnp7n0hdXjtVIlQWcR1tKX/s200/Ohj18_1mp.jpg)
Tarjolla tähän
sovellukseen on myös kirjasto-ohjelma
Time.h,
mutta sitä en tunne (ainakaan vielä). Se käsittää ajan tulostuksen vuositasolta
sekuntiin saakka.
Jos tämän valitsemani ratkaisun tarkkuus ei riitä, on olemassa yksi hyvä vaihtoehto:
voi mennä kirpparille ja ostaa paristokäyttöisen herätyskellon, missä on myös
sekuntiviisari. Tämä on tärkeää, sillä silloin sekunnin pulssi on saatavissa
valmiina. Tällä toteutuksella pääsee jo erittäin hyvään tarkkuuteen. Mutta
tässä pieni ongelma on se, että kelloa syötetään tavallisesti 1,5V:in jännitteellä.
Tällöin on kaksi vaihtoehtoa: joko vahvistaa kellon pulssi 5V:iin ja digitaalitulolle
sopivaksi, tai lukea tätä pulssia analogiatulon kautta.
Tässä viimeisessä
ohjelmaversiossa (_v5)
CoL_EroSekunti
= arvolla 998 antoi jo melko pienen jätätyksen = 48s/vrk. On huomattavasti
helpompi ohjelmallisesti käsitellä jättävää kuin edistävää ”kelloa”. Nyt
vuorokauden vaihtuessa voi sekuntien lähtöarvoksi ladata 48, jolloin
ensimmäinen minuutti on tynkä, mutta ei kai sillä yösydännä ole niin väliä. Jos
laittaa ajan oikeaksi päivällä kello 12:00, on ajan näyttö hiukan edellä ennen
puolta päivää ja jätättää iltapäivän edistyessä. Eikä tämä muutenkaan aivan
täydellinen ole. Koska aika käsitellään UT:na, ollaan kesäaikana 3 tuntia
edellä. Näyttö kuitenkin rajoitetaan 24:ään, jolloin näyttö jumittuu keskiyötä
lähestyttäessä tuohon lukemaan. Talviaikaan tuntia myöhemmin. Aamuyöstä näyttö palautuu
normaaliksi. Tokko tuollakaan suurta merkitystä, sillä toivottavasti silloin
ollaan jo unten mailla. Se on korjattavissa haluttaessa ehdollisella
vähennyslaskulla. Jos UT on kesäaikaan > 20, vähennetään 24 ja talviaikaan
suurempi kuin 21, tehdään sama vähennys.
Ohjelma 18v5
/*****************************************
* Ohjelma 18v5
* 05.05.2016
* LCD-näyttö kellonajoille:
* Universal Time, talviaika ja
kesäaika
*****************************************/
#include <LiquidCrystal.h>
// Näytön pinnit
LiquidCrystal lcd(8, 9, 4, 5,6,7);
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// MÄÄRITTELYT:
// Kellon määrittley
unsigned long Ulo_MilliSek = 0;
unsigned long Ulo_UusiMilliSek = 0;
const long CoL_EroSekunti = 998;
int Int_Sekunti = 0;
int Int_Minuutti = 0;
int Int_Tunti = 0;
int Seq_Aika = 0;
boolean Bol_Tulosta = false;
int Seq_YlaRivi = 1;
int Int_UT = 0;
int Int_Talvi = 1;
int Int_Kesa = 2;
//int Int_Otsikko = 1;
int Seq_TuntiAsetus = 1;
boolean Kep_TuntiAs = false;
int Seq_MinAsetus = 1;
boolean Kep_MinAs = false;
int Seq_AjanEtAsetus = 1;
int Seq_AjanTaAsetus = 1;
// ASETUKSET:
void setup(){
Serial.begin(9600);
lcd.begin(16,2);
Fun_YlaRivi(1, Int_UT);
}// Asetuksen loppu
// PÄÄLOOPPI
void loop(){
// Sisäisen kellon käyttö
Ulo_MilliSek = millis();
if(Ulo_MilliSek - Ulo_UusiMilliSek
> CoL_EroSekunti){
Ulo_UusiMilliSek = Ulo_MilliSek;
Seq_Aika = 1;
if(Bol_Tulosta ==
true){Fun_Tulostus();}
}
//Ajan hallintasekvenssi
switch (Seq_Aika){
case 1:
Int_Sekunti++;
if(Int_Sekunti > 59){
Int_Minuutti++;
Seq_Aika = 2;
}else{
Seq_Aika = 0;
}
break;
case 2:
Int_Sekunti = 0;
if(Int_Minuutti > 59){
Int_Tunti++;
Int_Minuutti = 0;
Seq_Aika = 3;
}else{
Seq_Aika = 0;
}
break;
case 3:
if(Int_Tunti > 23){
Int_Tunti = 0;
Seq_Aika = 0;
Int_Sekunti = 48;
}
break;
}
// Näytön valintasekvenssi
lcd_key = read_LCD_buttons(); // Näytön painikkeet
switch (Seq_YlaRivi) {
case 1:
if(lcd_key == 4){
Fun_YlaRivi(3, Int_Talvi);
Int_Tunti = Int_Tunti +2;
Seq_YlaRivi = 2;}
break;
case 2:
if(lcd_key == 5){Seq_YlaRivi = 3;}
break;
case 3:
if(lcd_key == 4){
Fun_YlaRivi(3, Int_Kesa);
Int_Tunti = Int_Tunti +1;
Seq_YlaRivi = 4;}
break;
case 4:
if(lcd_key == 5){Seq_YlaRivi = 5;}
break;
case 5:
if(lcd_key == 4){
Fun_YlaRivi(1, Int_UT);
Int_Tunti = Int_Tunti -3;
Seq_YlaRivi = 6;}
break;
case 6:
if(lcd_key == 5){Seq_YlaRivi = 1;}
break;
}// Näytön valintojen loppu
lcd.setCursor(4, 1);
if(Int_Tunti < 10){
lcd.print("0");
lcd.print(Int_Tunti);
}else{lcd.print(Int_Tunti);}
lcd.print(":");
if(Int_Minuutti < 10){
lcd.print("0");
lcd.print(Int_Minuutti);
}else{lcd.print(Int_Minuutti);}
lcd.print(":");
if(Int_Sekunti < 10){
lcd.print("0");
lcd.print(Int_Sekunti);
}else{lcd.print(Int_Sekunti);}
// Tunnin asetus
switch (Seq_TuntiAsetus) {
case 1:
if(lcd_key == 3){
Kep_TuntiAs = true;
lcd.setCursor(0, 1);
lcd.print("t");
Seq_MinAsetus = 1; Kep_MinAs = false;
Seq_TuntiAsetus = 2;}
break;
case 2:
if(lcd_key == 5){Seq_TuntiAsetus = 3;}
break;
case 3:
if(lcd_key == 3){
Kep_TuntiAs = false;
lcd.setCursor(0, 1);
lcd.print(" ");
Seq_TuntiAsetus = 4;}
break;
case 4:
if(lcd_key == 5){Seq_TuntiAsetus = 1;}
break;
} // Tuntiasetus loppu
// Minuutin asetus
switch (Seq_MinAsetus) {
case 1:
if(lcd_key == 0){
Kep_MinAs = true;
lcd.setCursor(0, 1);
lcd.print("m");
Seq_TuntiAsetus = 1; Kep_TuntiAs = false;
Seq_MinAsetus = 2;}
break;
case 2:
if(lcd_key == 5){Seq_MinAsetus = 3;}
break;
case 3:
if(lcd_key == 0){
Kep_MinAs = false;
lcd.setCursor(0, 1);
lcd.print(" ");
Seq_MinAsetus = 4;}
break;
case 4:
if(lcd_key == 5){Seq_MinAsetus = 1;}
break;
} // Minuuttiasetus loppu
// Ajan asetus eteenpäin
switch (Seq_AjanEtAsetus) {
case 1:
if(lcd_key == 1){
if(Kep_TuntiAs == true){Int_Tunti++;}
if(Kep_MinAs == true){Int_Minuutti++;}
if(Kep_TuntiAs == false && Kep_MinAs == false){
Int_Sekunti++;
}
Seq_AjanEtAsetus = 2;}
break;
case 2:
if(lcd_key == 5){Seq_AjanEtAsetus = 1;}
break;
} // Ajan eteenpäin asetuksen loppu
// Ajan asetus taaksepäin
switch (Seq_AjanTaAsetus) {
case 1:
if(lcd_key == 2){
if(Kep_TuntiAs == true){Int_Tunti--;}
if(Kep_MinAs == true){Int_Minuutti--;}
if(Kep_TuntiAs == false&& Kep_MinAs == false){
Int_Sekunti--;
}
Seq_AjanTaAsetus = 2;}
break;
case 2:
if(lcd_key == 5){Seq_AjanTaAsetus = 1;}
break;
} // Ajan taaksepäin asetuksen loppu
Int_Sekunti = constrain(Int_Sekunti, 0, 60);
Int_Minuutti = constrain(Int_Minuutti, 0, 60);
Int_Tunti = constrain(Int_Tunti, 0, 24);
//delay(1);
} // Pääohjelma LOPPU
// FUNKTIOT
void Fun_Tulostus(){
//Serial.print("Teksti :");
Serial.println(Muuttuja);
}
// Funktio Lue painikkeet:
int read_LCD_buttons(){
adc_key_in = analogRead(0);
if(adc_key_in > 1000) return
btnNONE;
if(adc_key_in < 50) return btnRIGHT;
if(adc_key_in < 195) return btnUP;
if(adc_key_in < 380) return btnDOWN;
if(adc_key_in < 555) return btnLEFT;
if(adc_key_in < 790) return btnSELECT;
return btnNONE;
}
// Funktio päivitä yläotsikko
void Fun_YlaRivi(int Paikka,int Otsikko){
char* Otsake[] = {"UNIVERSAL
TIME","TALVIAIKA","KESA-AIKA"};
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(Paikka, 0);
lcd.print(Otsake[Otsikko]);
} // Yärivi loppu