sunnuntai 26. maaliskuuta 2017

Sarjaliikenne V a

Aivan erilainenhan tämän jakson piti olla. Toivottavasti toteutuu seuraavassa; nimittäin sarjaliikennetoteutus ilman näköyhteyttä. Toisin sanoen suurtaajuudella (tässä tapauksessa 433MHz) toimiva lähetin ja vastaanotin (transceiver). Moduulin toiminta perustuu Texas Instrumentin piiriin CC-1101 (todellinen sovellus RF1100SE).

Jouduin kuitenkin sellaiseen lyhenneviidakkoon, että luetun ymmärtämisessä oli todellisia vaikeuksia. Siksi lähdin liikkeelle keräten tähän aiheeseen liittyviä lyhehteitä, jotta lunttaaminen kävisi helpommin. Julkaisen ne tässä. Toivottavasti luettelosta on jollekin toisellekin hyötyä. Tämä ei varmaankaan ole täydellinen luettelo, mutta tämän pohjalta sitä on helpompi jatkossa täydentää.

Jos googlaa noita lyhenteitä törmää tosiasiaan, että monilla, ellei jokaisella lyhenteellä on muitakin merkityksiä. Tässä olen yrittänyt esittää nimenomaan tähän aihepiiriin liittyvät tulkinnat. En ole pyrkinytkään suomentamaan (pari on tainnut jäädä) niitä, sillä englanniksi ne ovat selkeämpiä ymmärtää.

ACP      Adjacent Channel Power
ADC      Analog to Digital Converter
AFA       Adaptive Frequency Agility
AFC      Automatic Frequency Compensation
AGC     Automatic Gain Control
AMR     Automatic Meter Reading
ASK      Amplitude shift keying
AVDD   Power (Analog) 1.8 - 3.6 V analog power supply connection

BER     Bit Error Rate
BT        Bandwidth-Time product

CCA     Clear Channel Assessment
CFR     Code of Federal Regulations
CRC     Cyclic Redundancy Check
CS       Carrier Sense
CSn     Digital Input Serial configuration interface, chip select
CW      Continuous Wave (Unmodulated Carrier)

DC          Direct Current
DCOUPL    Power (Digital) 1.6 - 2.0 V digital power supply output
for decoupling
DGUARD    Power (Digital) Power supply connection for digital noise isolation
DVDD         Power (Digital) 1.8 - 3.6 V digital power supply for digital I/O’s
and for the digital core voltage regulator
DVGA     Digital Variable Gain Amplifier

EB       Evaluation Board
EIRP   Equivalent Isotropically Radiated Power
EM      Evaluation Module
ESR    Equivalent Series Resistance

FCC    Federal Communications Commission
FEC    Forward Error Correction
FHSS  Frequency Hopping Spread Spectrum
FIFO   first in, first out Ensin sisään, ensin ulos
FS      Frequency Synthesizer
FSK    Frequency Shift Keying
2-FSK Binary Frequency Shift Keying
4-FSK Quaternary Frequency Shift Keying

GDO0 (ATEST) Digital I/O, Digital output pin for general use:
Test signals, FIFO status signals, Clear channel indicator, Clock output, down-divided from XOSC, Serial output RX data, Serial input TX data Also used as analog test I/O for prototype/production testing
GDO2               Digital Output, Digital output pin for general use:
Test signals, FIFO status signals, Clear channel indicator, Clock output, down-divided from XOSC, Serial output RX data
GFSK  Gaussian shaped Frequency Shift Keying
GND    Ground connection

HGM   High Gain Mode

IF        Intermediate Frequency
I/Q      In-Phase/Quadrature
ISM     Industrial, Scientific and Medical

LBT     Listen-before-Talk
LC       Inductor-Capacitor
LGM    Low Gain Mode
LNA     Low Noise Amplifier
LO       Local Oscillator
LQI      Link Quality Indication
LSB     Least Significant Bit

MBUS  Wireless ( mittareiden etäluentäväylä)
MCU    Microcontroller Unit
MSB    Most Significant Bit
MSK    Minimum Shift Keying

N/A     Not Applicable
NRZ    Non Return to Zero (Coding)

OOK   On-off keying

PA       Power Amplifier
PCB    Printed Circuit Board
PD      Power Down
PER    Packet Error Rate
PLL     Phase Locked Loop
POR   Power-On Reset
PQI     Programmable Preamble Quality Indicator
PQI     Preamble Quality Indicator
PQT    Preamble Quality Threshold
PTAT   Proportional To Absolute Temperature

QLP    Quality Logo Products
QLP    Quad Leadless Package
QPSK Quadrature Phase Shift Keying

RBIAS  Analog I/O External bias resistor for reference current
RC       Resistor-Capacitor
RF       Radio Frequency
RF_N   RF I/O Negative RF input signal to LNA in receive mode
Negative RF output signal from PA in transmit mode
RF_P   RF I/O Positive RF input signal to LNA in receive mode Positive RF
output signal from PA in transmit mode
RoHS   Restriction of Hazardous Substances.
RSSI    Receive Signal Strength Indicator
RX       Receive, Receive Mode

SAW    Surface Aqustic Wave
SCLK   Serial configuration interface, clog input
SI         Digital Input Serial configuration interface, data input
SO (GDO1) Serial configuration interface, data output
SoC     System-on-Chip
SMD    Surface Mount Device
SNR    Signal to Noise Ratio
SRD    Short Range Device
SPI      Serial Peripheral Interface bus (lyhyille matkoille)

TBD    To Be Defined
T/R     Transmit/Receive
TX      Transmit, Transmit Mode
TrxEB SmartRF Transceiver EB

UHF    Ultra High frequency

VCO    Voltage Controlled Oscillator
VDD     Power supply connection

WOR   Wake on Radio, Low power polling

XOSC           Crystal Oscillator
XOSC_Q1    Analog I/O Crystal oscillator pin 1, or external clock input
XOSC_Q2    Analog I/O Crystal oscillator pin 2
XTAL            Crystal

lauantai 18. maaliskuuta 2017

Sarjaliikenne IV

Tavoiteena on langattomasti (IR välityksellä) siirtää sarjadataa Arduinolta toiselle. Jännä nähdä, onko tämä niin simppeli, kuin tällä hetkellä ajattelen? Lähetinpuolelle vastuksen kautta IR-LED (KY-005) ja vastaanottoon tuo sarjan 37 vastaanotin (KY-022) infrapuna (IR) vastaanotinelementtinä on AIXIN (aixin opto-electrical tecnolgy co, ltd)
valmistama IR-komponentti AX-1838HS (datasivu esim. https://arduino-info.wikispaces.com/file/view/IR-Receiver-AX-1838HS.pdf). Lähettävästä infrapunaLEDin tarkoista ominaisuuksista minulla ei ole tietoa. En tiedä mm. sitä, onko lähettävän LEDin aallonpituus sama 940nm. Ainakin tuntui, että lähettimen ja vastaanottimen välinen etäisyys jäi varsin lyhyeksi. Yksi ongelma oli myös se, että LEDin pinnijärjestys oli (jälleen kerran) väärä. Onneksi AX-1838HS:stä löytyi dataa ja onneksi on tapana ennen jännitteiden kytkemistä tarkastaa mittaamalla näiden moduulien kytkentä. 
 
Yllä selvisikin jo vastaus ensimmäiseen kysymykseeni. Kuvittelin paljon simppelimpää juttua ja toteutusta. Näistä syistä tästä jaksosta tulikin varsin ”tynkä”, sillä tällä hetkellä en näe ratkaisulle todellista käyttöä. IR-LEDi lähettää sarjaliikennepulsseja ja toisessa päässä ne vastaanotetaan, mutta lennokkien, autojen, valojen ja muiden vimpaimien kauko-ohjaukseen aiheeseen pitäisi perehtyä kyllä paljon tarkemmin.








OHJELMA 42L (lähettävä)
/***************************************
* Ohjelma_42L
* 17.03.2017
* Perustutkimusta KY005 ja KY022
* Lähettävän Arduinon ohjelma
**************************************/

// MÄÄRITTELYT:
int Int_Numero = 6;
const int Con_Viive = 500;

// ASETUKSET:
void setup(){
    Serial.begin(9600);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){
    Serial.write(Int_Numero);
    delay(Con_Viive);

delay(1);
} // Pääohjelma LOPPU


OHJELMA 42V (vastaanottava)
/***************************************
* Ohjelma 42V
* 17.03.2017
* Perustutkimusta KY005 ja KY022
* Vastaanottavan Arduinon ohjelma
**************************************/

// MÄÄRITTELYT:
int Int_Tuleva = 0;

// ASETUKSET:
void setup(){
    Serial.begin(9600);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){

    if(Serial.available()){ // Luku sarjaportista pinni 0
       Int_Tuleva = Serial.read();
       Serial.print("Tuleva :"); Serial.println(Int_Tuleva);
    }// if Sarjaportin luku loppu

delay(1);
} // Pääohjelma LOPPU

torstai 9. maaliskuuta 2017

Sarjaliikenne III

Tavoitteena on kuvata kahden Arduinon välistä sarjaliikennettä. Tässä on jo käytössä oikeat sarjaliikennekäskyt: odottaako sarjaportissa dataa (Serial. Available()), sarjaportin luku (Serial.read()) ja sarjaporttiin kirjoittaminen (Serial.write(Int_Numero);).
     Ohjelmalla syötetään ”näppäimistöltä” (APL-150117, Arduino Leonardo) I/O-pinnien (1 tx) kautta dataa 7-segmenttinäytölle (APL-060616, Arduino UNO) ja pautetaan (0 rx) takaisin näppäimistön LCD-näytölle. (Huom! Nuo APL:t eivät merkitse muille mitään. Se on vain oma tapani hallita monia rakentamiani piirilevyjä. Jos ne eivät ole dokumentoitu, aika pian unohdan, mitä mikäkin mahdollisesti tekee.)
     Arduino UNOssa Serial tarkoittaa sekä USB-porttia (mihin liitetään tietokone työkaluohjelmineen) sekä fyysistä porttia pinneissä nolla (0, rx, vastaanotto) ja yksi (1, tx, lähetys). Käytännössä tämä merkitsee sitä, että ulkoinen portti pitää UNOoon ohjelmaa ladatessa ola vapaa (eli sarjakaapeli toiseen mikrokontrolleriin irroitettuna). Leonardossa fyysinen portti on Serial1, joten ohjelman latausvaiheesta ei tule ristitiitaa. Suuremmissa Arduinoissa, kuten esim. Arduino MEGAssa on USB:n (myös pinit 0 ja 1) lisäksi kolme fyysistä sarjaporttia (pinneissä tx/rx: 18/19, 16/17 ja 14/15).

Tässä sovelluksessa on suurin osa ohjelmista (lähinnä aliohjelmista) kopioita aiemmista. Julkaisen ne kuitenkin tässä kokonaisuuksina, sillä niitä on jonkin verran editoitu ja aika paljon deletoitu. Kuitenkaan tästä jaksosta ei tullut ylivoimaisen pitkää ohjelmaosuutta.
     Videota ei tästä ole. Ohjelma toimii siten, että painettaessa jotain numeroa (0 .. 9, muut painikkeet eivät ole käytössä. Tosin huomasin leikkiessäni näppäimistöllä, että ohjelmassa on bugi; muut painikkeet näyttävät vähentävän numeroa yhdellä.), Leonardon ohjelma tulostaa sen LCD-näytölle (MENI: No) ja lataa po. numeron sarjaporttiin. UNO lukee numeron sarjaportista, kirjoittaa sen 7-segmenttinäyttöön ja lopuksi kirjoittaa lähtevään sarjaporttiin. Leonardo ”kuuntelee” sarjaporttia, ottaa vastaan välitetyn numeron ja tulostaa sen hetken kuluttua LCD-näytön alariville (TULI: No). Seuraava kierros tapahtuu uudella numeron painamisella.

OHJELMAT:
/***************************************
* Ohjelma 41 LEO
* 09.03.2017
* Sarjaliikenteen meno ja paluu
* Meno näppäimestä, paluu LCD-näyttöön
**************************************/

// MÄÄRITTELYT:
// LCD-näyttö
   #include <LiquidCrystal.h>
   LiquidCrystal lcd(3, 2, 7,6,5,4);
    const int Con_Pit = 16; // Datataulukon pituus
    int Int_Nappain = 0;
    int Int_Numero = 0;
    int Int_NumeroP = 0; // Palautuva numero
    boolean Bol_NappPain = false;
    boolean Bol_NappVapa = true;
    int Seq_NappOhjaus = 0; // Näppäinten ohjaussekvenssi
    int Int_NappOhjaus = 0; // Näppäimen numero

// 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

// Nappain_Ali_v1.No2Hel17
void Fun_NappTulkki(int askel){
   Seq_NappOhjaus = askel;
   switch (Seq_NappOhjaus) {
   case 1: // Numerot 0 .. 9
      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("TULI:");
      Seq_LCD = 0;
   break;
   case 3:
      lcd.setCursor(paikka, rivi);
      lcd.print("MENI:");
      Seq_LCD = 0;
   break;
   case 11: // Lukujen tulostus(paitsi liukuluku)
      lcd.setCursor(paikka, rivi);
      lcd.print(data);
      Seq_LCD = 0;
   break;
  }// Valintasekvenssin loppu
}// Funktion LCD loppu

// ASETUKSET:
void setup(){
   Serial.begin(9600);
   Serial1.begin(9600);
   lcd.begin(20,2);
   lcd.clear();
// Tekstit näyttöön, suoritetaan kerran
   Fun_LCD(3,0,0,0); // "MENI:"
   Fun_LCD(1,1,0,0); // "TULI:"
}// 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
       Fun_NappTulkki(Int_NappOhjaus);
       Int_Numero--; // Vähennetään yksi (1), koska numero on näppäin - 1
       Fun_LCD(11,0,7,Int_Numero);
       Bol_NappVapa = false;
     }// Näppäinten hallinta loppu
     if(Int_Nappain == 0){ // == ei mitään painettu
      Bol_NappPain = false;
      Bol_NappVapa = true; // Vapautetaan näppäimistö uuteen lukuun
    }// if vapautuksen loppu
// Kirjoitus sarjaporttiin
   Serial1.write(Int_Numero); // Kirjoitus sarjaporttiin pinni 1
// Lukeminen sarjaportista
   if(Serial1.available()){ // Luku sarjaportista pinni 0
      Int_NumeroP = Serial1.read();
      Fun_LCD(11,1,7,Int_NumeroP);
   }// if Sarjaportin luku loppu

delay(1);
} // Pääohjelma LOPPU

/***************************************
* Ohjelma 41 UNO
* 09.03.2017
* Luenta sarjaportista, numeron siirto
* 7-segmenttinäyttöön ja palutus sarjaporttiin
**************************************/

// MÄÄRITTELYT:
   int Int_Numero = 0;
   boolean Arr_Data[8] = {0,0,0,0,0,0,0,0};// Näyttö

// Sarjadatan syöttö 74HCT595
   const int Con_DS_Data = 6; // Sarjadatan syöttö
   const int Con_SHCP_Kello = 7; // Sarjadatan kellotus
   const int Con_STCP_Siirto = 8; // Syöttö rinnanlähtöön

// ALIOHJELMAT
// 7-segmenttinäytön lataus aliohjelma
// N7seg_Aliohjelma_v1 N7seg_ALI_v1.N1Maa17
void Fun_N7seg(int numero){
   int Seq_7nayt = numero + 1;
// 7-segmenttinäytön numerot
   boolean Arr_Data0[8] = {1,0,1,1,1,1,1,0}; // 0
   boolean Arr_Data1[8] = {0,0,0,0,1,1,0,0}; // 1
   boolean Arr_Data2[8] = {0,1,1,1,0,1,1,0}; // 2
   boolean Arr_Data3[8] = {0,1,0,1,1,1,1,0}; // 3
   boolean Arr_Data4[8] = {1,1,0,0,1,1,0,0}; // 4
   boolean Arr_Data5[8] = {1,1,0,1,1,0,1,0}; // 5
   boolean Arr_Data6[8] = {1,1,1,1,1,0,1,0}; // 6
   boolean Arr_Data7[8] = {0,0,0,0,1,1,1,0}; // 7
   boolean Arr_Data8[8] = {1,1,1,1,1,1,1,0}; // 8
   boolean Arr_Data9[8] = {1,1,0,1,1,1,1,0}; // 9

switch (Seq_7nayt) {
   case 1: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data0[i];}break;
   case 2: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data1[i];}break;
   case 3: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data2[i];}break;
   case 4: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data3[i];}break;
   case 5: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data4[i];}break;
   case 6: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data5[i];}break;
   case 7: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data6[i];}break;
   case 8: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data7[i];}break;
   case 9: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data8[i];}break;
   case 10: for(int i = 0; i < 8; i++){
      Arr_Data[i] = Arr_Data9[i];}break;
   }// Bittijonojen lataus loppu
}// Näytön latauksen aliohjelman loppu

// Numeroiden syöttö 7-segmenttinäyttöön
void Fun_Naytto(int j){
   Fun_N7seg(j);
   for(int i = 0; i < 8; i++){
      digitalWrite(Con_DS_Data, Arr_Data[i]);
      digitalWrite(Con_SHCP_Kello, HIGH);
      digitalWrite(Con_SHCP_Kello, LOW);
   }// Sarjakirjoitus loppu
// Sarjadatan siirto lähtöihin
   digitalWrite(Con_STCP_Siirto, HIGH);
   digitalWrite(Con_STCP_Siirto, LOW);
}// Näytön loppu

// ASETUKSET:
void setup(){
Serial.begin(9600);
   pinMode(Con_DS_Data, OUTPUT);
   pinMode(Con_SHCP_Kello, OUTPUT);
   pinMode(Con_STCP_Siirto, OUTPUT);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){
   if(Serial.available()){
      Int_Numero = Serial.read();
      Fun_Naytto(Int_Numero); // Tulostus 7-segmenttiin
// Tulostus työkalun ruudulle (palautus)
   }// if sarjadatan tunnistuksen loppu
   Serial.write(Int_Numero);
   delay(1);
} // Pääohjelma LOPPU

sunnuntai 5. maaliskuuta 2017

Sarjaliikenne II

Tässä sovelluksessa sarjapulssit syötetään binääritulon nolla (0 / rx) kautta. Varsinaista sarjaliikennettä ei tämäkään jakso vielä ole, mutta kuitenkin hiukan periaatteltaan samanlainen toteutus kuin ”Kostutuskeskus” 4. tammikuuta 2017. Tuossa toteutuksessa anturi lähettää ”pitkän” pulssin merkiksi sanoman alusta. Kun se on ajallisesti tunnistettu, vastaanotetaan alkupulssia seuraavat pulssit datana.
 Tässä sovelluksessa alkupulssi annetaan sähkötysavaimella (siksi sähkötysavaimella, koska sillä on paljon helpompi tuottaa lyhyitä pulsseja nopeasti kuin painikkeella). Alkupulssi käynnistyy ensimmäisestä avaimen painalluksesta. Sen merkkinä palaa punainen LEDi pienen hetken. Tänä aikana ohjelma ei lue tulevaa dataa avaimesta. Kun tämä alkuviive on päättynyt, hyppää ohjelma askeleeseen kaksi, missä vihreää LEDiä vilkutetaan viisi (5) kertaa. Samanaikaisesti luetaan digitalituloa nolla (0) ja kerätään tämän vilkutuksen aikana tulleet pulssien nousevat reunat muuttujaan (Int_Numero). Kun vihreän LEDin vilkutus on loppunut, hyppää ohjelma askeleeseen kolme (3), missä pulssien lukumäärä siirretään 7-segmenttinäyttöön. Kolmannessa askeleessa on 1,5 sekunnin viive, minkä kuluttua numeromuuttuja nollataan ja sekvenssi pysäytetään. Seuraava avaimen painallus käynnistää tapahtumaketjun taas alusta. Video antinarduvideo40.youtube.com havainnollistaa tapahtumaketjua hieman selvemmin.

Tämän kertainen ohjelma koostuu pääosin jo aiemmin käytetyista ohjelmapalasista. Siksi olen jättänyt esim. 7-segmenttinäyttöön liittyvät aliohjelmat pois, viitaten ainostaan jaksoon, mistä ne voi halutessaan kopioda. Tätä ohjelmaa laatiessa haastavin osuus oli saada vihreän LEDin vilkutus ja avaimen tilan lukeminen samanaikaiseksi. Digitalitulo nolla (0) on määritelty sisäiselle ylösvetovastukselle (INPUT_PULLUP), joten tällöin ei tarvitse käyttää tulovastusta. Toisaalta avainta painettaessa tulon jännite laskee nollaan (5V → 0V), joten luettaessa signaali käännetään huutomerkillä (!) (Bol_Avain = !digitalRead(Con_Avain);)

OHJELMA 40
/***************************************
* Ohjelma 40
* 05.03.2017
* Sarjapulssien laskenta ja näyttö
**************************************/

// MÄÄRITTELYT:
    const int Con_Jakso = 400;
    unsigned int Uni_Jakso = Con_Jakso;
    int Seq_Runko = 0;
    boolean Bol_LEDtila = true;
    unsigned int Uni_LEDpun = Con_Jakso * 3;
    int Int_LEDvihKertaa = 5;
    const int Con_Avain = 0; // Sähkötysvaimen liityntä
    boolean Bol_Avain = false;
    boolean BolAvainVapaa = true;
    int Int_Numero = 0;
    boolean Arr_Data[8] = {0,0,0,0,0,0,0,0};// Näyttö
// Sarjadatan syöttö 74HCT595
   const int Con_DS_Data = 6; // Sarjadatan syöttö
   const int Con_SHCP_Kello = 7; // Sarjadatan kellotus
   const int Con_STCP_Siirto = 8; // Syöttö rinnanlähtöön

// ALIOHJELMAT
// Aliohjelma: luvun vähennys
unsigned int Fun_Miinus( unsigned int luku){
    luku--; return luku;}// vähennys loppu

// Aliohjelma LEDin ohjaus
void Fun_LEDit(int pinni, boolean tila){
    pinMode(pinni, OUTPUT);
    digitalWrite(pinni, tila);
}// LEDin ohjaus loppu

// Seuraavana 3 aliohjelmaa:
// void Fun_Tyhjenna(){
// void Fun_N7seg(int numero){
// void Fun_Naytto(int j){
// Nämä ovat maaliskuun ensimmäisessä päivityksessä

// ASETUKSET:
void setup(){
    Serial.begin(9600);
    pinMode(Con_Avain, INPUT_PULLUP);
    pinMode(Con_DS_Data, OUTPUT);
    pinMode(Con_SHCP_Kello, OUTPUT);
    pinMode(Con_STCP_Siirto, OUTPUT);
}// Asetuksen loppu

// PÄÄLOOPPI
void loop(){
    Bol_Avain = !digitalRead(Con_Avain);
    if(Bol_Avain == true && Seq_Runko == 0){
       Fun_Tyhjenna();
       Seq_Runko = 1;}

switch (Seq_Runko) {
case 1: // Poltetaan punaista LEDiä aloituksen merkkinä
    Fun_LEDit(4, LOW);
    Fun_LEDit(5, HIGH);
    Uni_LEDpun = Fun_Miinus(Uni_LEDpun);
    if(Uni_LEDpun == 0){
       Fun_LEDit(5, LOW);
       Uni_LEDpun = Con_Jakso * 3;
      Bol_LEDtila = true;
      Seq_Runko = 2;
    }// if punaisen polton loppu
break;
case 2: // Vilkutetaan vihreää LEDiä merkiksi datan annosta
do{
    delay(2); // Vaatii näköjään pienen viiveen jotta suorittaa
    Uni_Jakso = Fun_Miinus(Uni_Jakso);
    if(Uni_Jakso == Con_Jakso - 1 || Uni_Jakso == Con_Jakso / 2){
       Bol_LEDtila = !Bol_LEDtila;
       Fun_LEDit(4, Bol_LEDtila);
    }// if vihreän vilkutus
    if(Uni_Jakso == 0){
       Fun_LEDit(4, LOW);
       Int_LEDvihKertaa = Fun_Miinus(Int_LEDvihKertaa);
       Uni_Jakso = Con_Jakso;
     }// if kertojen laskenta

// Avainten painamisten laskenta
    Bol_Avain = !digitalRead(Con_Avain);
    if(Bol_Avain == true && BolAvainVapaa == true){
       Int_Numero++;
       BolAvainVapaa = false;
    }// Avaimen nouseva reunan tunnistus loppu
    if(Bol_Avain == false){BolAvainVapaa = true;}
}while (Int_LEDvihKertaa > 0);
    if(Int_LEDvihKertaa == 0){
       Seq_Runko = 3;
    }// if askeleen vaihto
break;
case 3: // Tulostetaan numero, eli painamisten lukumäärä
    Fun_Naytto(Int_Numero);
    Int_LEDvihKertaa = 5;
    Int_Numero = 0;
    delay(1500); // Näytetään 1,5 sekuntia
    Fun_Tyhjenna();
    Seq_Runko = 0;
break;
}// Sekvenssin loppu

delay(1);
} // Pääohjelma LOPPU