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

Ei kommentteja:

Lähetä kommentti