Ohjelma
kysyy käynnityksen jälkeen ensimmäistä lukua ja kehoittaa
painamaan ENTteriä. Kun tämä on tehty näytetään kehoitus toisen
luvun antamiseen. Toisen ENTterin jälkeen ohjelma laskee neljä
laskutehtävää (summa, erotus, tulo ja osamäärä) ja näytön
alarivin hallinta siirtyy ylös- ja alas-painikkeille. Näillä
voidaan siirtyä edestakaisin noiden tulosten katselussa. Tästä
tilasta paistutaan painamalla MENU-painiketta, jolloin ohjelma
siirtyy kysymään ensimmäistä numeroa uudestaan. Suositeltavaa on
käyttää lukualuetta välillä 1 .. 99, sillä ohjelma on ajateltu
tällaista suoritusta varten. Rajoituksia ja tarkastuksia ei
ohjelmassa ole, mutta kahden suuren luvun kertominen (tulo >
2exp15 = 32768) antaa tulokseksi negatiivisen luvun, koska käytetyt
muuttujat ovat int-tyyppiä.
Tässä
sovelluksessa sarjaluenta kehittyy hiukan pidemmälle. Sitä
sovelletaan nelilaskimena. Hyviä laskimia voi ostaa edullisesti,
joten jos nelilaskin olisi päämäärä, ei siinä olisi juuri
järkeä. Tavoite onkin synnyttää luotettava luenta ja huolimatta
pitkästä painamisesta (siis millisekuntiskaalassa), siihen
reagoidaan ainoataan yhden ohjelmakierroksen ajan. Jos tätä
toteutusta hiukan muuttamalla haluaisi käyttää johonkin
”järkevään”, voisi sen tehdä tulostamaan sattumanvaraisesti
sekä oikeita sanoja että epäsanoja. Käyttäjä painaisi heti
tulkinnan jälkeen kummasta on kyse. Aivoilta menee nimittäin
kauemmin epäsanan kuin tutun sanan tulkitsemiseen. Myöhemmin voisi
tulostaa aikaerot. Kyse on samasta ilmiöstä kun PUNAINEN
kirjoitetaan vihreällä värillä
ja sana pitäisi lukea ääneen, aiheuttaa se hiukan hankaluutta.
![]() | |
Näppäimistön painikejärjestys. |
Aluksi
ajattelin tehdä kytkinvärähtelyn eliminoimisen huolella, mutta
satojen painamisten yhteydessä ei syntynyt ainuttakaan
virhetulkintaa, joten jätin sen pois kasvattamasta ohjelmaa. Se
voitaisiin tehdä seuraaavasti: Kun ohjelma havaitsee painalluksen,
tehdään uusi luenta vaikkapa viiden (5) millisekunnin kulutta, ja
verrataan näin saatua kahta taulukkoa toisiinsa. Jos ne ovat
yhteneväiset, hyväksytään tulkinta. Jos eivät, toistetaan uusi
luenta, kunnes ne ovat samat.
Toinen
tavoite oli laajentaa kaksirivisen näytön mahdollisuuksia
lisäämällä MENU-ominaisuus. Listaa voi selata ylös- ja
alaspainikkeilla. Sivuttaisnuolet eivät ole käytössä tässä
ohjelmassa.
Ohjelma
on hyvin aliohjelmapainotteinen. Pääohjelma ei käsitä juurikaan
muuuta kuin aliohjelmakutsuja. Ensimmäisenä tunnistetaan, että
jotain on painettu (Int_Nappain > 0). Sen
jälkeen suljetaan uusi tunnistaminen (= painaminen jatkuu). Sitten
ohjelma katsoo, onko kyse numerosta (Näppäin välillä 1
.. 10). Seuraaavaksi
tunnistetaan muut painikkeet ja sijoitetaan niihin koodi. Tämän
ryhmän viimeisenä suljetaan uusi luenta (Bol_NappVapa =
false), jolloin uusi luenta
estyy. Suraavaksi jäädään odottamaan painikkeiden vapautusta (ja
eston vapauttamista). Pääohjelman lopuksi suoritetaan halutut
aliohjelmaketjut (aliohjelma kutsuu toista aliohjelmaa).

Ohjelma
kysyy käynnityksen jälkeen ensimmäistä lukua ja kehoittaa
painamaan ENTteriä. Kun tämä on tehty näytetään kehoitus toisen
luvun antamiseen. Toisen ENTterin jälkeen ohjelma laskee neljä
laskutehtävää (summa, erotus, tulo ja osamäärä) ja näytön
alarivin hallinta siirtyy ylös- ja alas-painikkeille. Näillä
voidaan siirtyä edestakaisin noiden tulosten katselussa. Tästä
tilasta paistutaan painamalla MENU-painiketta, jolloin ohjelma
siirtyy kysymään ensimmäistä numeroa uudestaan. Suositeltavaa on
käyttää lukualuetta välillä 1 .. 99, sillä ohjelma on ajateltu
tällaista suoritusta varten. Rajoituksia ja tarkastuksia ei
ohjelmassa ole, mutta kahden suuren luvun kertominen (tulo >
2exp15 = 32768) antaa tulokseksi negatiivisen luvun, koska käytetyt
muuttujat ovat int-tyyppiä.


OHJELMA
38
/*************************
*
Ohjelma 38
*
23.02.2017
*
Tosi lyhyt matikka
*************************/
//
MÄÄRITTELYT:
#include
<LiquidCrystal.h>
LiquidCrystal
lcd(3, 2, 7,6,5,4);
//
Muut määrittelyt
const
int Con_Pit = 16; // Datataulukon pituus
int
Int_Nappain = 0;
boolean
Bol_NappPain = false;
boolean
Bol_NappVapa = true;
int
Int_LaskVaihe = 1; //Laskentatapahtuman vaihe
int
Seq_Laskenta = 0;
int
Seq_NappOhjaus = 0; // Näppäinten ohjaussekvenssi
int
Int_Luku1 = 0;
int
Int_Luku2 = 0;
int
Int_Summa = 0;
int
Int_Erotus = 0;
int
Int_Tulo = 0;
float
Flo_Osamaara = 0.0;
float
L1 = 0.0; float L2 = 0.0;
//
ALIOHJELMAT
//
Funktio Parallel IN serial OUT (Rinnan sisään, sarjassa ulos)
//
SarjaIN_Ali_v3.No2Hel17
int
Fun_LueRsSu(int
PL, int
CP, int
Data, int
Pituus){
int
NappainNumero = 0;
int
i = 0;
boolean
Taulukko[Pituus];
boolean
Bitti = false;
pinMode(PL,
OUTPUT); // Rinnan -> sarja siirto, pinnin numero
pinMode(CP, OUTPUT); // Kellotus, pinnin numero
pinMode(Data, INPUT);// Dataluennan
pinnin numero
//
Rinnakkaisdatan siirto
digitalWrite(PL, LOW);
digitalWrite(PL, HIGH);
for(
i = 0; i < Pituus; i++){ // Sarjadatan talletus
Taulukko[i] = digitalRead(Data);
digitalWrite(CP, HIGH);
digitalWrite(CP, LOW);
}//
sarjaluennan loppu
for(
i = 0; i < Pituus; i++){ // Onko taulukossa 1-bitti
if(Taulukko[i] == true){
NappainNumero = Pituus - i; //
"bittien kääntö"
}//
if oli 1-bitti loppu
}//
Näppäin numeron tulkinta 0 == 1
return
NappainNumero;
}//
Funtion loppu
//
Lukujen käsittelyfunktio
void
Fun_Laskenta(int askel, int painike){
Seq_Laskenta
= askel;
switch
(Seq_Laskenta) {
case
1:
Int_Luku1
= Int_Luku1 * 10 + painike - 1;
if(Int_Luku1 < 10){
Fun_LCD(11,1,10,Int_Luku1);
}else{
Fun_LCD(11,1,9,Int_Luku1);
}
// if Luvun pituusvalinnan loppu
Seq_Laskenta = 0;
break;
case
2:
Int_Luku2
= Int_Luku2 * 10 + painike - 1;
if(Int_Luku2 < 10){
Fun_LCD(11,1,10,Int_Luku2);
}else{
Fun_LCD(11,1,9,Int_Luku2);
}
// if Luvun pituusvalinnan loppu
Seq_Laskenta = 0;
break;
case
3:
Int_Summa
= Int_Luku1 + Int_Luku2;
Int_Erotus
= Int_Luku1 - Int_Luku2;
Int_Tulo
= Int_Luku1 * Int_Luku2;
L1
= Int_Luku1; L2 = Int_Luku2;
Flo_Osamaara = L1 / L2;
lcd.clear();
Seq_Laskenta = 0;
break;
case
4: // Tämä askel on vain testiä varten, ei suorituksessa
Serial.print("Summa =: ");
Serial.println(Int_Summa);
Serial.print("Erotus =: ");
Serial.println(Int_Erotus);
Serial.print("Tulo =: ");
Serial.println(Int_Tulo);
Serial.print("Osamaara =: ");
Serial.println(Flo_Osamaara);
Seq_Laskenta = 0;
break;
case
5: // Summa näyttöön
Fun_LCD(4,0,0,0);
Fun_LCD(11,0,8,Int_Luku1);
Fun_LCD(5,0,11,0);
Fun_LCD(11,0,14,Int_Luku2);
Fun_LCD(6,1,0,0);
Fun_LCD(11,1,10,Int_Summa);
Seq_Laskenta = 0;
break;
case
6: // Erotus näyttöön
Fun_LCD(23,1,0,0);
Fun_LCD(7,1,0,0);
Fun_LCD(11,1,11,Int_Erotus);
Seq_Laskenta = 0;
break;
case
7: // Tulo näyttöön
Fun_LCD(23,1,0,0);
Fun_LCD(8,1,0,0);
Fun_LCD(11,1,11,Int_Tulo);
Seq_Laskenta = 0;
break;
case
8: // Osamäärä näyttöön
Fun_LCD(23,1,0,0);
Fun_LCD(9,1,0,0);
lcd.setCursor(15, 1);
lcd.print(Flo_Osamaara);
Seq_Laskenta = 0;
break;
}//
sekvenssin loppu
}//
Laskentafunktion loppu
//
Nappain_Ali_v1.No2Hel17
void
Fun_NappTulkki(int askel){
Seq_NappOhjaus
= askel;
switch
(Seq_NappOhjaus) {
case
1: // Numerot 0 .. 9
Fun_Laskenta(Int_LaskVaihe,
Int_Numero);
Seq_NappOhjaus = 0;
break;
case
2: // ENTER no: 10
if(Int_LaskVaihe ==
1){Fun_LCD(2,1,0,0);}
Fun_LCD(22,1,9,0); // Luvun
syöttöpaikan tyhjennys
Int_LaskVaihe++;
if(Int_LaskVaihe == 3){
Fun_Laskenta(3, 0);
Fun_Laskenta(5, 0);
Int_LaskVaihe = 5;
}
// if Numeroiden sijoitus näyttöön
Seq_NappOhjaus = 0;
break;
case
3: // Nuoli oikealle no: 11 (ei nyt käytössä)
Seq_NappOhjaus = 0;
break;
case
4: // Nuoli ylös no: 12 (paluu tulostusmenussa)
Fun_LCD(23,1,0,0);
Int_LaskVaihe--;
if(Int_LaskVaihe < 5){Int_LaskVaihe
= 5;} // Rajoitus
if(Int_LaskVaihe >=
5){Fun_Laskenta(Int_LaskVaihe, 0);}
Seq_NappOhjaus = 0;
break;
case
5: // Nuoli vasemmalle no: 13 (ei nyt käytössä)
Seq_NappOhjaus = 0;
break;
case
6: // Nuoli alas no: 14 (eteenpäin tulostusmenussa)
Fun_LCD(23,1,0,0);
Int_LaskVaihe++;
if(Int_LaskVaihe > 8){Int_LaskVaihe
= 8;}
if(Int_LaskVaihe <
9){Fun_Laskenta(Int_LaskVaihe, 0);}
Seq_NappOhjaus = 0;
break;
case
7: // MENU, keskipainike, no: 15 (paluu alkuun)
Int_LaskVaihe = 1;
Int_Luku1 = 0;
Int_Luku2 = 0;
Fun_LCD(3,0,0,0);
Fun_LCD(23,1,0,0);
Fun_LCD(1,1,0,0);
Seq_NappOhjaus = 0;
break;
}//
Näppäinohjaus loppu
}//
Näppäimenkäsittelyfunktion loppu
//
LCD aliohjelman määrittelyt
void
Fun_LCD(int start, int rivi, int paikka, int data){
//
Näytön valintasekvenssi
int
Seq_LCD = start;
switch
(Seq_LCD){
case
1:
lcd.setCursor(paikka, rivi);
lcd.print("Luku 1:");
Seq_LCD = 0;
break;
case
2:
lcd.setCursor(paikka, rivi);
lcd.print("Luku 2:");
Seq_LCD = 0;
break;
case
3:
lcd.setCursor(paikka, rivi);
lcd.print("ANNA LUKU ja ENT!");
Seq_LCD = 0;
break;
case
4:
lcd.setCursor(paikka, rivi);
lcd.print("LUKUJEN");
Seq_LCD = 0;
break;
case
5:
lcd.setCursor(paikka, rivi);
lcd.print("ja");
Seq_LCD = 0;
break;
case
6:
lcd.setCursor(paikka, rivi);
lcd.print("SUMMA ON:");
Seq_LCD = 0;
break;
case
7:
lcd.setCursor(paikka, rivi);
lcd.print("EROTUS ON:");
Seq_LCD = 0;
break;
case
8:
lcd.setCursor(paikka, rivi);
lcd.print("TULO ON:");
Seq_LCD = 0;
break;
case
9:
lcd.setCursor(paikka, rivi);
lcd.print("OSAMAARA ON:");
Seq_LCD = 0;
break;
case
11: // Lukujen tulostus(paitsi liukuluku)
lcd.setCursor(paikka, rivi);
lcd.print(data);
Seq_LCD = 0;
break;
case
21:
lcd.setCursor(paikka, rivi);
lcd.print(" ");
Seq_LCD = 0;
break;
case
22:
lcd.setCursor(paikka, rivi);
lcd.print(" ");
Seq_LCD = 0;
break;
case
23:
lcd.setCursor(paikka, rivi);
lcd.print("
");
Seq_LCD = 0;
break;
case
24: // Koko näytön tyhjennys
lcd.clear();
Seq_LCD = 0;
break;
}//
Valintasekvenssin loppu
}//
Funktion LCD loppu
//
ASETUKSET:
void
setup(){
Serial.begin(9600);
lcd.begin(20,2);
lcd.clear();
//
Yläteksti näyttöön, suoritetaan kerran
Fun_LCD(3,0,0,0);
Fun_LCD(1,1,0,0);
}//
Asetuksen loppu
//
PÄÄLOOPPI
void
loop(){
Int_Nappain
= Fun_LueRsSu(8, 9, 10, Con_Pit); // luetaan näppäimistö
if(Int_Nappain
> 0){Bol_NappPain = true;} // tunnistetaan painaminen
if(Bol_NappPain == true &&
Bol_NappVapa == true){ // suoritetaan
if(Int_Nappain > 0 &&
Int_Nappain < 11){
Int_NappOhjaus = 1;
Int_Numero
= Int_Nappain;
}//
Numerot loppu
if(Int_Nappain == 11){Int_NappOhjaus
= 2; }
if(Int_Nappain == 12){Int_NappOhjaus
= 3; }
if(Int_Nappain == 13){Int_NappOhjaus
= 4; }
if(Int_Nappain == 14){Int_NappOhjaus
= 5; }
if(Int_Nappain == 15){Int_NappOhjaus
= 6; }
if(Int_Nappain == 16){Int_NappOhjaus
= 7; }
Fun_NappTulkki(Int_NappOhjaus);
Bol_NappVapa
= false;
}//
Näppäinten hallinta loppu
if(Int_Nappain
== 0){ // == ei mitään painettu
Bol_NappPain
= false;
Bol_NappVapa
= true;
}//
if vapautuksen loppu
if(Seq_Laskenta == 3){ // Suoritetaan
nelilaskenta
Int_LaskVaihe = 5;
Fun_Laskenta(Int_LaskVaihe, 0);
}
// Laskennan loppu
delay(1);
}
// Pääohjelma LOPPU