Radioamatööri – lehden
lokakuun numerossa on artikkelini Arduinolla toteutetusta
automaattisesta sähkötysavaimesta. Artikkelissa käsitellään
ainoastaan muutamia ohjelmatoteutuksen kohtia, sillä ohjelma olisi
ollut turhan pitkä lehtiartikkeliin. Tässä on viimeisin
ohjelmaversio. Tämä on vapaasti käytettävissa ja halutessa myös
muutettavissa. Rivit 63, 64 ja 65 (sijaisevat asetusosassa) on joka
tapauksessa muutettava vastaamaan kunkin radioamatöörin tarpeita.
(Noissa on vakiolauseet esim. yleiskutsua, nimeä ja lopetusta
varten.)
/*
Nimi: CW_Test_16v21
Luotu: 11.2.2016
Luoja: Antti Isännäinen
KUVAUS:
Automaattiavain amatöörikäyttöön. Viiva vasemmalle, piste
oikealle.
Lisäksi painikkeilla voi valita kolme valmista sanomaa esim:
yleiskutsu,
nimi ja QTH sekä yhteyden lopetus kiitoksineen.
Nämä ovat vapaasti valittavissa, mutta ainoastaan
ohjelmointivaiheessa
kirjoitettavissa selvätekstinä ja ladatavissa ohjelman käännöksen
ja
latauksen yhteydessä. Ääkköset olen jättänyt pois, koska niillä
ei ole
yhden merkin ASCII-koodia. Nekin on saatavissa sähkötysmerkeiksi,
mutta
tekstissä toisilla merkeillä.
Sähkötysnopeus on säädettävissä potentiometrillä. Samoin
suuriohmisille
kuulokkeille tarkoitettu myötäkuuntelun voimakkuus.
Kuunteluäänen korkeus on vakio, mutta määriteltävissä
ohjelmointivaiheessa.
Versiossa 10 ensimmäistä kertaa oikea avain käytössä.
Espoossa 5.2.2016
Versio 20 käsittää lopullisen hardiksen, eli itetaidetta
Tyydyttävä toiminta versiolla 20.
Huomioi, ettei lähetyksen nopeuitta voi muuttaa kesken sanoman,
ainoastaan sanomien välillä. Käsin sähkötettäessä nopeutta voi
muuttaa
merkkien välillä.
Espoossa 11.2.2016
Versiossa 21 muutetaan tauko hiukan pistettä lyhemmäksi, koska
se netin mukaan on elegantimpaa.
*/
//
MÄÄRITTELYT:
int
Int_Taajuus = 750; // Myötäkuuntelun taajuus
int
Int_Nopeus = 0;
int
Int_Piste = 0; // Pisteen kesto viiva/3
int
Int_Vali = 0; // Merkkiväli Hiukan lyhempi kuin piste
//
int Int_SanaVali = 3*Int_Nopeus;
int
Seq_Sanoma = 0;
int
p
= 3; // piste
int
v
= 1; // viiva
int
i
= 0;
int
j
= 0;
int
k
= 0;
//
Yksittäisten merkkien taulukot; ensin merkin pituus, sitten merkit
int
A[] ={2,p,v,0,0,0};int
B[] ={4,v,p,p,p,0};int
C[] ={4,v,p,v,p,0};
int
D[] ={3,v,p,p,0,0};int
E[] ={1,p,0,0,0,0};int
F[] ={4,p,p,v,p,0};
int
G[] ={3,v,v,p,0,0};int
H[] ={4,p,p,p,p,0};int
I[] ={2,p,p,0,0,0};
int
J[] ={4,p,v,v,v,0};int
K[] ={3,v,p,v,0,0};int
L[] ={4,p,v,p,p,0};
int
M[] ={2,v,v,0,0,0};int
N[] ={2,v,p,0,0,0};int
O[] ={3,v,v,v,0,0};
int
P[] ={4,p,v,v,p,0};int
Q[] ={4,v,v,p,v,0};int
R[] ={3,p,v,p,0,0};
int
S[] ={3,p,p,p,0,0};int
T[] ={1,v,0,0,0,0};int
U[] ={3,p,p,v,0,0};
int
V[] ={4,p,p,p,v,0};int
W[] ={3,p,v,v,0,0};int
X[] ={4,v,p,p,v,0};
int
Y[] ={4,v,p,v,v,0};int
Z[] ={4,v,v,p,p,0}; // 90 ASCII
int
nol[] ={5,v,v,v,v,v}; int
yks[] ={5,p,v,v,v,v}; int
kak[]
={5,p,p,v,v,v};
int
kol[] ={5,p,p,p,v,v}; int
nel[] ={5,p,p,p,p,v}; int
vii[]
={5,p,p,p,p,p};
int
kuu[] ={5,v,p,p,p,p}; int
sei[] ={5,v,v,p,p,p}; int
kah[]
={5,v,v,v,p,p};
int
yhd[] ={5,v,v,v,v,p};
int
Arr_Merkki[6]; int
Arr_ABC[36][6]; // Merkin ja merkkien välitaulukot
char
Arr_Lause1[] = {"CQ CQ DE OH2WJ OH3YD OH6KVE PSE K "};
char
Arr_Lause2[] = {"MY NAME ANTTI ANTTI ES QTH ESPOO QTH ESPOO
"};
char
Arr_Lause3[] = {"TNX FER QSO 73 73 GL ES CUAGN "};
int
Int_Pituus1 = 0; int
Int_Pituus2 = 0; int
Int_Pituus3 = 0;
int
Int_Merkki = 0; int
Int_AsciiEro = 0;
//
Liitynnät
const
int
Con_Key = 3;
const
int
Con_LED = 4;
const
int
Con_Aani = 5;
const
int
Con_Txt1 = 6; boolean Bol_Txt1 = false;
const
int
Con_LedPois = 7; boolean Bol_LedPois = false;
const
int
Con_Txt2 = 8; boolean Bol_Txt2 = false;
const
int
Con_RelePois = 9; boolean Bol_RelePois = false;
const
int
Con_Txt3 = 10; boolean Bol_Txt3 = false;
const
int
Con_Viiva = 11; boolean Bol_Viiva = false;
const
int
Con_Piste = 12; boolean Bol_Piste = false;
const
int
Con_AnaTulo = 0; int Int_AnaTulo = 0;
//
ASETUKSET:
void
setup(){ // Alustetaan muuttujat sekä määritellään
I/O-tyyppi
Serial.begin(9600); // Alustetaan sarjaliikennne testiä
varten
//while (!Serial) { ; } // Odottaa sarjaportin kytkeytymistä
pinMode(Con_Key, OUTPUT);
pinMode(Con_LED, OUTPUT);
pinMode(Con_Txt1, INPUT);
pinMode(Con_Txt2, INPUT);
pinMode(Con_Txt3, INPUT);
pinMode(Con_Viiva, INPUT);
pinMode(Con_Piste, INPUT);
pinMode(Con_LedPois, INPUT);
pinMode(Con_RelePois, INPUT);
//
Ladataan kaksiulotteinen merkkitaulukko. Tarvitsee tehdä vain
käynnistettäessä
for(i
= 0; i < 6; i++){Arr_ABC[0][i] = A[i];} for(i = 0; i < 6;
i++){Arr_ABC[1][i] = B[i];}
for(i
= 0; i < 6; i++){Arr_ABC[2][i] = C[i];} for(i = 0; i < 6;
i++){Arr_ABC[3][i] = D[i];}
for(i
= 0; i < 6; i++){Arr_ABC[4][i] = E[i];} for(i = 0; i < 6;
i++){Arr_ABC[5][i] = F[i];}
for(i
= 0; i < 6; i++){Arr_ABC[6][i] = G[i];} for(i = 0; i < 6;
i++){Arr_ABC[7][i] = H[i];}
for(i
= 0; i < 6; i++){Arr_ABC[8][i] = I[i];} for(i = 0; i < 6;
i++){Arr_ABC[9][i] = J[i];}
for(i
= 0; i < 6; i++){Arr_ABC[10][i] = K[i];} for(i = 0; i < 6;
i++){Arr_ABC[11][i] = L[i];}
for(i
= 0; i < 6; i++){Arr_ABC[12][i] = M[i];} for(i = 0; i < 6;
i++){Arr_ABC[13][i] = N[i];}
for(i
= 0; i < 6; i++){Arr_ABC[14][i] = O[i];} for(i = 0; i < 6;
i++){Arr_ABC[15][i] = P[i];}
for(i
= 0; i < 6; i++){Arr_ABC[16][i] = Q[i];} for(i = 0; i < 6;
i++){Arr_ABC[17][i] = R[i];}
for(i
= 0; i < 6; i++){Arr_ABC[18][i] = S[i];} for(i = 0; i < 6;
i++){Arr_ABC[19][i] = T[i];}
for(i
= 0; i < 6; i++){Arr_ABC[20][i] = U[i];} for(i = 0; i < 6;
i++){Arr_ABC[21][i] = V[i];}
for(i
= 0; i < 6; i++){Arr_ABC[22][i] = W[i];} for(i = 0; i < 6;
i++){Arr_ABC[23][i] = X[i];}
for(i
= 0; i < 6; i++){Arr_ABC[24][i] = Y[i];} for(i = 0; i < 6;
i++){Arr_ABC[25][i] = Z[i];}
for(i
= 0; i < 6; i++){Arr_ABC[26][i] = nol[i];} for(i = 0; i < 6;
i++){Arr_ABC[27][i] = yks[i];}
for(i
= 0; i < 6; i++){Arr_ABC[28][i] = kak[i];} for(i = 0; i < 6;
i++){Arr_ABC[29][i] = kol[i];}
for(i
= 0; i < 6; i++){Arr_ABC[30][i] = nel[i];} for(i = 0; i < 6;
i++){Arr_ABC[31][i] = vii[i];}
for(i
= 0; i < 6; i++){Arr_ABC[32][i] = kuu[i];} for(i = 0; i < 6;
i++){Arr_ABC[33][i] = sei[i];}
for(i
= 0; i < 6; i++){Arr_ABC[34][i] = kah[i];} for(i = 0; i < 6;
i++){Arr_ABC[35][i] = yhd[i];}
}//
Asetuksen loppu
//
PÄÄLOOPPI
void
loop(){
//
Tekstipainikkeiden luku
Bol_Txt1
= digitalRead(Con_Txt1);
Bol_Txt2
= digitalRead(Con_Txt2);
Bol_Txt3
= digitalRead(Con_Txt3);
Bol_Viiva
= digitalRead(Con_Viiva);
Bol_Piste
= digitalRead(Con_Piste);
//
Nopeustiedon luku ja nopeuden käsittely
Int_AnaTulo
= analogRead(Con_AnaTulo);
Int_Nopeus
= map(Int_AnaTulo, 0, 1023, 100, 600);
//Serial.println(Int_Nopeus);
Int_Piste
= Int_Nopeus / 3;
Int_Vali
= Int_Piste * 8 / 10;
//
Viivan lähetys avaimella
if(Bol_Viiva
== true){
tone(Con_Aani, Int_Taajuus);
Bol_LedPois = digitalRead(Con_LedPois);
if(Bol_LedPois == false){ digitalWrite(Con_LED, HIGH);}
Bol_RelePois = digitalRead(Con_RelePois);
if(Bol_RelePois == false){digitalWrite(Con_Key, HIGH);}
delay(Int_Nopeus);
noTone(Con_Aani);
digitalWrite(Con_LED, LOW);
digitalWrite(Con_Key, LOW);
delay(Int_Vali); // merkkiväli
}//
Viivan loppu
//
Pisteen lähetys avaimella
if(Bol_Piste
== true){
tone(Con_Aani, Int_Taajuus);
Bol_LedPois = digitalRead(Con_LedPois);
if(Bol_LedPois == false){ digitalWrite(Con_LED, HIGH);}
Bol_RelePois = digitalRead(Con_RelePois);
if(Bol_RelePois == false){digitalWrite(Con_Key, HIGH);}
delay(Int_Piste);
noTone(Con_Aani);
digitalWrite(Con_LED, LOW);
digitalWrite(Con_Key, LOW);
delay(Int_Vali); // merkkiväli
}//
Pisteen loppu
//
Sanomapainikkeiden runnistus
if(Bol_Txt1
== true){ Seq_Sanoma = 1;}
if(Bol_Txt2
== true){ Seq_Sanoma = 2;}
if(Bol_Txt3
== true){ Seq_Sanoma = 3;}
//
Tekstin valinta
switch
(Seq_Sanoma) {
case 1: // Ensimmäinen sanoma
for(k = 0; k < sizeof(Arr_Lause1)-1; k++){
Int_Merkki = Arr_Lause1[k];
if(Int_Merkki == 32){delay(Int_Nopeus * 2); // Tunnistetaan sanaväli
(SPACE)
}else if(Int_Merkki < 65){Int_AsciiEro = 22;// Tunistetaan numero
Fun_Merkki(Int_Merkki - Int_AsciiEro);
}else {
Int_AsciiEro = 65; // Loput ovat kirjaimia
Fun_Merkki(Int_Merkki - Int_AsciiEro);}}
Seq_Sanoma = 4;
break;
case 2: // Toinen sanoma
for(k
= 0; k < sizeof(Arr_Lause2)-1; k++){
Int_Merkki = Arr_Lause2[k];
if(Int_Merkki == 32){delay(Int_Nopeus * 2); // Tunnistetaan sanaväli
(SPACE)
}else if(Int_Merkki < 65){Int_AsciiEro = 22;// Tunistetaan numero
Fun_Merkki(Int_Merkki - Int_AsciiEro);
}else {
Int_AsciiEro = 65; // Loput ovat kirjaimia
Fun_Merkki(Int_Merkki - Int_AsciiEro);}}
Seq_Sanoma = 4;
break;
case 3: // Kolmas sanoma
for(k
= 0; k < sizeof(Arr_Lause3)-1; k++){
Int_Merkki = Arr_Lause3[k];
if(Int_Merkki == 32){delay(Int_Nopeus * 2); // Tunnistetaan sanaväli
(SPACE)
}else if(Int_Merkki < 65){Int_AsciiEro = 22;// Tunistetaan numero
Fun_Merkki(Int_Merkki - Int_AsciiEro);
}else{
Int_AsciiEro = 65; // Loput ovat kirjaimia
Fun_Merkki(Int_Merkki - Int_AsciiEro);}}
Seq_Sanoma = 4;
break;
case 4: // Sanoman lähetyksen lopetus
Seq_Sanoma = 0;
break;
}
delay(1);
// IO-stabilointia varten tämä lyhyt tauko
} //
Pääohjelma LOPPU
//
Merkkien muuntaminen sähkötykseksi
void
Fun_Merkki(int x){
int Purku[6];
for(int i = 0; i < 6; i++){Purku[i] = Arr_ABC[x][i];}
for(int i = 0; i < Purku[0]; i++){
tone(Con_Aani, Int_Taajuus);
Bol_LedPois = digitalRead(Con_LedPois);
if(Bol_LedPois == false){ digitalWrite(Con_LED, HIGH);}
Bol_RelePois = digitalRead(Con_RelePois);
if(Bol_RelePois == false){digitalWrite(Con_Key, HIGH);}
delay(Int_Nopeus/Purku[i+1]);
noTone(Con_Aani);
digitalWrite(Con_LED, LOW);
digitalWrite(Con_Key, LOW);
delay(Int_Vali); // merkkiväli
}
delay(Int_Nopeus
- Int_Nopeus/10*4); // Kirjainväli
}//
Merkki-funktion loppu