tiistai 26. syyskuuta 2023

CW_64

Morsetuksen alkeita.

 Tämä ohjelma on oikeastaan vain runko sähkötyksen opetteluun. Tämä sisältää ainoastaan aakkosmerkit, jotka muodostuvat yhdestä, kahdesta tai kolmesta, joko pisteestä tai viivasta. Pisteistä lyhin on E-kirjain, eli yksi lyhyt piste. Viivoista lyhyin on T-kirjain. Pisin merkki on O-kirjain, joka muodostuu kolmesta viivasta. Muut ovat niiden väliltä ja muodostuvat pisteistä ja viivoista.

 

Tavoite luonnollisesti oli tehdä tämä ohjelma, sekä luoda siihen erilaisia toimintoja. Kun ohjelma käynnistyy, tulostuu näytölle pyyntö painaa kosketuspainiketta TCH1 ja valita sähkötyksen nopeus. Nopeus voidaan valita potentiometrilla, ja ainoastaan silloin, kun sormi viipyy painikkeella. Kun sormi irrotetaan, tulostuu näytölle ilmoitus, että sähkötys alkaa kahden sekunnin kuluttua.


 Kun sähkötysääni kuuluu, on näyttö tyhjä. Tänä aikana kuuluu ainoastaan summerista sähkötysmerkit. Viiden merkin välein on hiukan pidempi tauko. Merkkejä arvotaan 30 kappaletta (rajoite johtuu tuosta pienestä kaksirivisestä näytöstä). Kun sähkötys on loppu, tulostetaan näytölle kahteen riviin nuo arvotut sähkötysmerkit. Jos merkit on kirjoitettu paperille kuuntelun aikana, voidaan niiden oikeellisuus ja oppimisen onnistuminen tarkastaa näytöltä.

 Kun painiketta TCH1 painetaan uudestaan, voidaan nopeus valita jälleen (ei välttämätöntä), ja suorittaa uusi harjoitus. Tuo nopeusasetus (15 .. 93 merkkiä minuutissa) on lähinnä symbolinen, sillä kaikkia sähkötysmerkkejä tämä harjoitus ei sisällä. Tavoite on ainoastaan, että voidaan muodostaa sekä hidasta että nopeaa sähkötystä.

 /***************************************

 *  Ohjelman nimi: Opi_CWF_64
 *  26.09.2023
 *  Lyhyt toimintaselostus:
 *  Tulostaa pillille 1, 2, ja 3
 *  merkkisiä sähkötyskirjaimia.
 *  Sähkötysnopeutta voidaan säätää käsin.
 **************************************/

// MÄÄRITTELYT:
#include <LiquidCrystal.h>
  LiquidCrystal lcd(7, 6, 13,12,11,10);
  const byte api = B11100001; // ä
  const byte opi = B11101111; // ö

// Taulukoita ja muuttujia
    const int Con_Tapit = 30;         // Merkkitaulukon pituus
    char Merkit[] = "EISTANMUDORKWG"; // Arvottavat merkkialkiot
    String Tulos = "";      
    int Int_TaulPit = 13;             // Merkkien lukumäärä
    int Int_Sattuma = 0;
    const int ViKe = 5;               // Viivekerroin    
    boolean Kep_Tulosta = false;      // Tulostus LCD-näytölle    
    int Int_Rivi = 0;                 // LCD-näytön rivi
    int Int_Kohta = 0;                // LCD-näytön kohta     

// Liityntöjen määrittelyt
// Digitaalinen tulo
    const int Con_TCH1 = 3;       // Kosketuspainike 1
// Digitaalinen lähtö
    const int Con_Pilli = 9;      // tämä on BUZZeri
// Analoginen tulo    
    const int Con_Nopeus = 0;     // Potentiometrin tulo
    int Int_NopRaaka = 0;
    int Int_Nopeus = 0;          // sähkötyksen nopeussäätö
    const int Con_Arpa = 1;

// Sähkötykseen ja ohjaukseen liittyvät
    int Int_Jakso = 0;            // Tähän lasketaan nopeus
    boolean Bol_TCH1 = false;
    boolean Diu_TCH1 = false;     // Painiketieto yhden kierroksen ajan
    boolean Kep_teksti_1 = true;  // Alkutekstin kirjoitus

// Sekvenssit
    int Seq_TCH1 = 1;             // Kosketuspainikkeen käsittely
    int Seq_CW_Merkit = 0;        // Merkkien valinta taulukosta

//********************************************************************
// ALIOHJELMAT
// Näytön aliohjelmat
void Fun_Tyhjenna(int rivi){
  lcd.setCursor(0, rivi);
  lcd.print("                    ");
}// LCD rivityhjennys loppu

// Tekstien päivitys
void Fun_Teksti(int kohta, int rivi, char teksti){
  lcd.setCursor(kohta, rivi);
  lcd.print(teksti);
}// Teksti_ali loppu
void Fun_Lause(int kohta, int rivi, String teksti){
  lcd.setCursor(kohta, rivi);
  lcd.print(teksti);
}// Lause_ali loppu
//Numeroiden päivitys
void Fun_Nopeus(int kohta, int rivi, int nopeus){
  lcd.setCursor(kohta, rivi);
  lcd.print(nopeus);
}// Mittaus_ali loppu

// Äänimerkin aktivointi
    void Fun_Pilli(int kertaa, int kesto){
      int k = kertaa;
      int pituus = Int_Jakso * kesto;
      for(int i = 1; i <= k; i++){
      digitalWrite(Con_Pilli, true);
      delay(pituus);
      digitalWrite(Con_Pilli, false);
      delay(Int_Jakso);
     }// Pillin loppu
    }// foorin loppu


//********************************************************************
// ASETUKSET:
void setup(){                  
 Serial.begin(9600);
  lcd.begin(20,2);
  lcd.clear();
Int_TaulPit = sizeof(Merkit);
  randomSeed(analogRead(Con_Arpa));
  pinMode(Con_TCH1, INPUT);  // Kosketuspainike
  pinMode(Con_Nopeus, INPUT); // Potentiometrin tulo
  pinMode(Con_Pilli, OUTPUT);  
}// Asetuksen loppu


//********************************************************************
// PÄÄLOOPPI                   
void loop(){

// Tyhjennetään näyttö ja ladataan alkutekstit
if (Kep_teksti_1 == true){
    Fun_Lause(1, 0, "Paina TCH1 ja");
    Fun_Lause(1, 1, "valitse nopeus");
    Kep_teksti_1 = false;}

// Kosketuspainikkeen hallinta
Bol_TCH1 = digitalRead(Con_TCH1);
switch (Seq_TCH1) { // Kosketuspainikkeen sekvenssi
  case 1:
    if(Bol_TCH1 == true){
      Fun_Tyhjenna(0);Fun_Tyhjenna(1);
      Seq_TCH1 = 2;
      }
    break;
  case 2:
    Fun_Lause(1, 0, "Valitse nopeus:");
      Seq_TCH1 = 3;
  break;
  case 3: // Määritellään sähkötysnopeus
 Bol_TCH1 = digitalRead(Con_TCH1);
       // Määritellään sähkötyksen nopeus ja merkin kesto
          Int_NopRaaka = analogRead(Con_Nopeus);
             Int_Nopeus = Int_NopRaaka / 13 + 15; //13 + 20;
          Int_Jakso = 150 -  Int_Nopeus; // Sähkötyksen nopeus potikalta
            Fun_Nopeus(3,1,Int_Nopeus);
            Fun_Lause(6,1,"m/min");
     if(Bol_TCH1 == false){
        Fun_Tyhjenna(0);Fun_Tyhjenna(1);
        Seq_TCH1 = 4;}
   break;

  case 4: // Ilmoitus alkamisesta
    Fun_Lause(1,0,"S");
    Fun_Teksti(2,0,B11100001);
    Fun_Lause(3,0, "hk");
    Fun_Teksti(5,0,B11101111);    
    Fun_Lause(6,0, "tys alkaa");
    Fun_Lause(3,1, "2s kuluttua.");
      delay(2000);
      Fun_Tyhjenna(0);Fun_Tyhjenna(1);
    Seq_TCH1 = 5;
   break;

  case 5: // Aktivoidaan sähktyssekvenssi
      Diu_TCH1 = true;
      Seq_TCH1 = 6;
   break;   
  case 6: // Tulostetaan näytölle arvotut merkit
      Int_Rivi = 0;Int_Kohta = 0;
      for(int k = 0; k < 30; k++){
      Fun_Teksti(Int_Kohta, Int_Rivi, Tulos[k]);
        Int_Kohta++;
          if(Int_Kohta == 5 || Int_Kohta == 11){
           Int_Kohta++;}
          if(Int_Kohta == 17){Int_Rivi = 1; Int_Kohta = 0;}
      } // forin loppy
        Seq_TCH1 = 7;
  break;  
  case 7: // Paluu uuteen arvontaan
      Bol_TCH1 = digitalRead(Con_TCH1);
         if(Bol_TCH1 == true){Seq_TCH1 = 1;}
            Tulos = "";
   break;  
}// Sekvenssin loppu

if(Diu_TCH1 == true){// eka on lkm. ja toka kesto
   for(int i = 0; i < Con_Tapit;i++){
     Int_Sattuma = random(0,14);
     Seq_CW_Merkit  = Int_Sattuma;
     Tulos = Tulos + Merkit[Int_Sattuma];
   switch (Seq_CW_Merkit){
    case 0:Fun_Pilli(1, 1);delay(ViKe*Int_Jakso);break;  // E
    case 1:Fun_Pilli(2, 1);delay(ViKe*Int_Jakso);break;  // I                      
    case 2:Fun_Pilli(3, 1);delay(ViKe*Int_Jakso);break;  // S
    case 3:Fun_Pilli(1, 2);delay(ViKe*Int_Jakso);break;  // T
    case 4:Fun_Pilli(1, 1);Fun_Pilli(1, 2);delay(ViKe*Int_Jakso);break;  // A
    case 5:Fun_Pilli(1, 2);Fun_Pilli(1, 1);delay(ViKe*Int_Jakso);break;  // N
    case 6:Fun_Pilli(1, 2);Fun_Pilli(1, 2);delay(ViKe*Int_Jakso);break;  // M
    case 7:Fun_Pilli(2, 1);Fun_Pilli(1, 2);delay(ViKe*Int_Jakso);break;  // U    
    case 8:Fun_Pilli(1, 2);Fun_Pilli(2, 1);delay(ViKe*Int_Jakso);break;  // D
    case 9:Fun_Pilli(3, 2);delay(3*Int_Jakso);break;  // O     
    case 10:Fun_Pilli(1, 1);Fun_Pilli(1, 2);Fun_Pilli(1, 1);delay(ViKe*Int_Jakso);break;  // R
    case 11:Fun_Pilli(1, 2);Fun_Pilli(1, 1);Fun_Pilli(1, 2);delay(ViKe*Int_Jakso);break;  // K
    case 12:Fun_Pilli(1, 1);Fun_Pilli(1, 2);Fun_Pilli(1, 2);delay(ViKe*Int_Jakso);break;  // W
    case 13:Fun_Pilli(1, 2);Fun_Pilli(1, 2);Fun_Pilli(1, 1);delay(ViKe*Int_Jakso);break;  // G
  }// Sekvenssin loppu
  if(i > 0 && (i+1)%5 == 0){delay(10*Int_Jakso);}// Pidempi tauko viiden välein
  }// Merkkivalinnan loppu
}// Arvonnan loppu
Diu_TCH1 = false; // DifUpp nollataan joka kierroksella
Kep_Tulosta = false;
delay(1);
} // Pääohjelma LOPPU