tiistai 19. joulukuuta 2023

ASCII_65A

 Tällä ohjelmalla tulostetaan ASCII-merkkejä LCD-näytölle.

 

Taistelin epävarmana kehittäessäni yhtä sovellusta siitä, miten saisin ääkkösten isot kirjaimet (Ä ja Ö) tulostettua tuon pienelle kaksiriviselle LCD_näytölle. En netistä enkä muistakaan lähteistä löytänyt apua ongelmaani. Tuon puutteen ajamana syntyi tämä pieni ohjelma, jonka ajattelin ladata tänne sivullenikin. Toivottavasti joku hyötyisikin siitä.

 Ohjelmassa syötetään binäärimuodossa (byte) muuttuja väliltä B00000000 .. B11111111 ja tulostetaan LCD-näytön alariville. (Itse asiassa suurin luku menee hiukan tuon ylikin, sillä muuttujan kasvu ei pysähdy suurimpaan ASCII-numeroon, eli lukuun 255. Se on sentään mitätön haitta.)

 Painamalla painiketta muuttuja kasvaa aina kahdellakymmenellä ja jatkuu täten aina lukuun 260 saakka, minkä jälkeen se aloittaa uudelleen nollasta. Välillä riville ei tulostu mitään. Hyvin suuri osa merkeistä on kiinalaisia. Sieltä löytyvät kyllä kaikki standardin mukaiset ASCII-merkit ja myöskin pieni ä ja pieni ö, jotka pitää nyt sitten hyväksyä isojen kirjaimien tilalle.

 Sovelluksessa on hyödynnetty Rich UNO R3 kehityspohjaa, joten esimerkiksi painikevärähtelyä ei tarvitse itse ohjelmassa huomioida ja valvoa.

 

/***************************************
 *  Ohjelman nimi: LCD_AskiiB
 *  19.12.2023
 *  ASCII-bittien muunnos
 *  LCD-näytölle
 **************************************/
#include <Arduino.h>
// MÄÄRITTELYT:
// LCD-näyttö
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 13,12,11,10);
byte alku = B00000000;

// Liityntöjen määrittelyt
  const int Con_TCH1 = 3;       // Kosketuspainike 1
  boolean Bol_TCH1 = false;
  int Seq_TCH1 = 0;
  boolean Kep_TCH1 = false;     // Ohjausbitti
  int kerta = 0;
  int No = 1;
 
// ALIOHJELMAT
// Merkkien päivitys LCD-näytölle
   void Fun_Jakso(int kohta, int rivi, int lukema){
    lcd.setCursor(kohta, rivi);
    lcd.print(lukema);
   }// Numerotulostuksen loppu
  void Fun_Merkki(int kohta, int rivi, char merkki){
    lcd.setCursor(kohta, rivi);
    lcd.print(merkki);
  }// Teksti_ali loppu
  void Fun_Lause(int kohta, int rivi, String teksti){
   lcd.setCursor(kohta, rivi);
   lcd.print(teksti);}

// ASETUKSET:
void setup(){                  
 Serial.begin(9600);    
  lcd.begin(20,2);
  lcd.clear();     
  pinMode(Con_TCH1, INPUT);      // Kosketuspainike
}// Asetuksen loppu

// PÄÄLOOPPI                   
void loop(){
// Painikkeen luku
   Bol_TCH1 = digitalRead(Con_TCH1);
   if(Bol_TCH1 == true && Kep_TCH1 == false && Seq_TCH1 == 0){
    Kep_TCH1 = true;
    Seq_TCH1 = 1;
    }// Painike 1
    
// Painikesekvenssi
switch (Seq_TCH1) {
    case 1:
    if(Kep_TCH1 == true && Kep_TCH1 == true){
      Fun_Lause(0,0,"ASCII jakso:");
      Fun_Jakso(12,0,kerta);
      Fun_Merkki(15,0,'-');
      Fun_Jakso(17,0,kerta+19);      
      for(int i=0;i<20;i++){
       Fun_Merkki(i,1,alku+i+kerta);}
      Kep_TCH1 = false;}
    if(Bol_TCH1 == false){
      Seq_TCH1 = 2;}
    break;
    case 2:
     No++;
     Seq_TCH1 = 3;
    break;
    case 3:
      kerta = kerta + 20;
      if(kerta > 260){
       kerta = 0;  lcd.clear();};
     if(Bol_TCH1 == false){Seq_TCH1 = 1;}
       Seq_TCH1 = 0;
    break;
}// Painikesekvenssin loppu
delay(1);
} // Pääohjelma LOPPU

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

sunnuntai 28. toukokuuta 2023

OH2A_63

Tuossa Rich UNO R3 on odottanut varsin pitkään saadakseen sisäänsä sähköä ja ohjelmalauseita. Se on hyvä alusta kokeiluihin ja ohjelman kehitykseen, koska siinä on valmiina useita liityntöjä, kuten kosketuspainikkeita, analogiapuolella potentiometri, summeri sekä neljän numeron näyttö. Tässä mainitsin vain muutamia.

Näiden toimintaan löytyy paljon kirjasto-ohjelmia, mutta halusin lähteä liikkeelle ja kokeilemaan hyvin alhaiselta perustasolta. Hyvin pian kokeilut sortuivatkin osaamattomuuteen ja tiedon puutteeseen. Pääsin kuitenkin alkuun ja sain jotain yksinkertaista aikaan.

Alla oleva ohjelma piipittää morseaakkosia. Signaali käynnistyy painamalla hipaisupainiketta ja summeri sähköttää tekstin kuuluvasti. Sähkötysnopeus on säädettävissä arviolta välillä 20 .. 100 merkkiä minuutissa. Se ei kuitenkaan ole tarkka, sillä lyhin merkki on yksi (1) ”piste” (E-kirjain) ja pisin merkki viisi (5) ”viivaa” (numero 0). Muut ovat siltä väliltä.

Tarkoitukseni oli tulostaa nopeus tuossa näytössä, mutta siihen tämän hetkinen tietoni ja osaamiseni ei riittänyt. Kaiketi jossain vaiheessa pitänee ladata kirjasto-ohjelmia, jotta pääsen aiheessa eteenpäin.

Tässä ohjelmassa ”sanoma” on CQ CQ DE OH2A ...K. Siinä on aluksi kaksi (2) yleistä kutsua (CQ), sen jälkeen tässä (DE) sekä kutsu OH2A ja lopuksi kuuntelen (K). Tuo kutsu on Suomen radioamatööriliiton kutsu, joten ohjelma kutsuu uusia jäseniä liittymään radioamatööriharrasteen pariin. Tervetuloa minunkin puolestani!

Liukukytkimillä voi aktivoida eri toimintoja sekä tulopuolelle että ohjauspuolelle. Tässä ohjelmassa on valittu hipaisukytkimellä (TCH1, D3) sähkötyksen käynnistys. Summerin ohjaus (BUZZER, D9) sekä potentiometrin analogiatulo (KNOB, A0).

Liukukytkimen luenta on ohjelmallisesti yksinkertainen, koska tässä ei tarvitse ottaa huomioon mitään kosketinvärähtelyitä tai muita häiriötekijöitä. Kun ohjelma huomaa, että kosketinta on painettu, se asettaa ykköseksi (1) bitin (Diu_TCH1), joka käynnistää sähkötyksen. Seuraavaksi ohjelma siirtyy odottamaan painikkeen vapautumista. Käynnistysbitti (Diu_TCH1) nollataan jokaisella ohjelmakierroksella ohjelman lopussa. Täten seuraava sähkötysjakso alkaa vasta uudesta painamisesta.

 


Alla oleva ohjelma on varsin yksinkertainen ja suoraviivainen. Painike on kaksiaskelinen sekvenssi. Summerin aliohjelmalle ladataan se, onko kyse pisteestä (1) vai viivasta (2). Viivan kesto on kaksi kertaa piste. Kokonainen merkki syntyy peräkkäisistä kutsuista. Merkkien väli on myös riippuvainen pisteen kestosta.

 Tässä ohjelmassa käytössä ovat seuraavat valinnat:

            10 liukukytkimet:   vasen 3 = painike 1, oikea 3 = summeri, oikea 6 = potikka

            9 hipaisupainike TCH1

            4 summeri

            12 potentiometri

 

 

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

* Ohjelman nimi: OH2A

* 28.05.2023

* Rich UNO kehitystä

* Piippaa amatöörikutsun painiketta painettaessa.

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

#include <Arduino.h>

// MÄÄRITTELYT:

// Liityntöjen määrittelyt

// Digitaalinen tulo

const int Con_TCH1 = 3; // Kosketuspainike 1

const int Con_Ana_1 = 0; // Potentiometrin tulo


// Digitaalinen lähtö

const int Con_LEDiA = 5; // Merkkivalo

const int Con_Pilli = 9; // tämä on BUZZeri


// Muutujamäärittelyt

int Int_KierLasku = 0; // Jaksotetaan ohjelmakierroksilla

const int Con_Jakso = 140; // Perusjakso piste ja tauko

int Int_Jakso = 0; // Tähän lasketaan nopeus

boolean Bol_TCH1 = false;

boolean Kep_TCH1 = false; // Kosketuspainikkeen tilatieto

boolean Diu_TCH1 = false;

boolean Kep_Pilli = false; // Summerin tila

int Int_Nopeus = 0; // sähkötyksen nopeussäätö


// Sekvenssit

int Seq_TCH1 = 1; // Kosketuspainikkeen käsittely

int SeqPilli = 1; // Vingutuksen sekvenssi


// ALIOHJELMAT:

// Ää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);

        }//foorin loppu          

}// Pillin loppu


// ASETUKSET:

void setup(){

    Serial.begin(9600);

    pinMode(Con_TCH1, INPUT); // Kosketuspainike

    pinMode(Con_Ana_1, INPUT); // Potentiometrin tulo

    pinMode(Con_Pilli, OUTPUT);

}// Asetuksen loppu


// PÄÄLOOPPI

void loop(){ // Valvotaan painiketta ja muodostetaan ohjauskoodi

    Int_Nopeus = analogRead(Con_Ana_1);

    Int_Jakso = Con_Jakso - Int_Nopeus / 10; // Sähkötyksen nopeus potikalta


    Bol_TCH1 = digitalRead(Con_TCH1);

        switch (Seq_TCH1) { // Kosketuspainikkeen sekvenssi

            case 1:

                if(Bol_TCH1 == true){

                    Diu_TCH1 = true;

                    Seq_TCH1 = 2;

                }

        break;

        case 2:

                if(Bol_TCH1 == false){Seq_TCH1 = 1;}

        break;

    }// Sekvenssin loppu


// 1. montako merkkiä 2. kesto, 3. tauon pituus

if(Diu_TCH1 == true){

    for(int i = 1;i <= 2; i++){

        Fun_Pilli(1, 2);                  // C

        Fun_Pilli(1, 1);

        Fun_Pilli(1, 2);

        Fun_Pilli(1, 1);

        delay(3*Int_Jakso);

        Fun_Pilli(2, 2);                  // Q

        Fun_Pilli(1, 1);

        Fun_Pilli(1, 2);

    delay(3*Int_Jakso);

    } // kaksi yleistä kutsua

        Fun_Pilli(1, 2);                  // D

        Fun_Pilli(1, 1);

        Fun_Pilli(1, 1);

    delay(3*Int_Jakso);

        Fun_Pilli(1, 1);                 // E

    delay(3*Int_Jakso);             // tässä

        Fun_Pilli(3, 2);                 // O

    delay(3*Int_Jakso);

        Fun_Pilli(4, 1);                  // H

    delay(3*Int_Jakso);

        Fun_Pilli(2, 1);                 // 2

        Fun_Pilli(3, 2);

    delay(3*Int_Jakso);

        Fun_Pilli(1, 1);                  // A

        Fun_Pilli(1, 2);

    delay(7*Int_Jakso);               // OH2A

        Fun_Pilli(1, 2);                  // K

        Fun_Pilli(1, 1);

        Fun_Pilli(1, 2);

    delay(3*Int_Jakso);             // kuuntelen

}// kutsu loppu


Diu_TCH1 = false; // DifUpp nollataan joka kierroksella

delay(1);

} // Pääohjelma LOPPU