28 Arduino モールス通信キーヤーを作成 3
この記事では、モールス通信をするときに使用するエレクトリック・キーヤーを作成します。前回は送信速度設定ができるように変更しました。今回はさらにサイドトーンの周波数も変更できるよう改造します。ハードウエアの変更はありません。
押しボタンSWはUp/Downの1組しかないのに、2組のパラメータを変更しなければなりません。解決策としてこのスケッチでは、二つの押しボタンを同時に押すと設定するパラメータの切り替えができるように考えました。
プログラムの流れ
setup関数内のEEPROMからデーターを読み込む関数 ckEEPROMdata( ) を実行します。今までの送信速度(1番地)の処理に加えサイドトーン周波数(2番地)も処理します。
loop関数内では、送信速度を設定するSWが押されたか確認し、UPキーが押されればcgParaUp関数を実行、DOWNキーが押されれば cgParaDOWN関数を実行します。
- ckEEPROMdata関数
EEPROMアドレスを読み取り保存されているデータの有効性判断をします。
確認項目は、値が変更可能範囲内か? 一の位がゼロか?
もし、送信速度が無効ならEEPROMデータをデフォルト値に置き換えます。
有効が確認されたなら、文字/分を短点の時間に変換します。
今回、サイドトーン周波数の処理を追加しています。周波数は、その値を1/10にして保存されています。読み取ったデータの有効性確認をしたのちに10倍にしてサイドトーン周波数に変換します。 - cgParaUp関数
UpSWが押されると呼び出されます。SW_UPが押されている間にSW_DOWNも押されたら、パラメータの変更モード isCgSpd を反転させ「ピポ」と鳴るBeep音でモード変更を知らせて両方のSWが離されるのを待ち復帰します。
処理後の分岐先は3箇所で、
両方のSWが押された時はloop関数に直接戻りますが、
UpSWだけが押された時は変更モードに従い cgSpeedUp関数またはcgFreqUp関数を実行してから復帰します。 - cgParaDown関数
cgParaUp関数と同等の動作をします。
ただし、分岐先が cgSpeedDOWN関数またはcgFreqDown関数になります。 - cgFreqUp関数
UpSWが離れるのを待って、frequencyの値を確認します。
もし、上限に達していれば、Beep音を3回鳴らし復帰します。
上限に達していないなら、その値を100増やします。
EEPROMにはfrequencyを 1/10した値を上書きします。
Beep音は新しいサイドトーン周波数で鳴らしオペレータに完了を知らせます。 - cgFreqDown関数
cgFreqUp関数と同等の動作です。
下限に達していないなら、frequencyの値を100減らします。
スケッチの内容
前回のスケッチに周波数変更部分を追加しました。主たるプログラムフローの変更はありません。ハードウエアの変更をせずにソフトウエアで対応したためプログラムが長くなってしましました。
// Electoric keyer
// SWで送信速度を変更 両方のSWを同時に押すと
// サイドトーンの周波数変更ができる
// 2021-6-26
#include <EEPROM.h>
int keySpeed; // 短点の時間 ms
int frequency; // サイドトーン周波数
int KEY_DOT = 2; // pin 2 パドルのDot接点
int KEY_DASH = 3; // pin 3 パドルのDash接点
int SW_UP = 6; // pin 6 Up SW
int SW_DOWN = 7; // pin 7 Down SW
int PIN_SPK = 9; // pin 9 圧電スピーカー
int PIN_LED1 = 13; // ボード内蔵 LED 使用
boolean flagDot = 0; // Dotが押された
boolean flagDash = 0; // Dashが押された
boolean isCgSpd = 1; // Dashが押された
unsigned long tUp; // 完了時間
void setup() {
pinMode(KEY_DOT, INPUT_PULLUP);
pinMode(KEY_DASH, INPUT_PULLUP);
pinMode(SW_UP, INPUT_PULLUP);
pinMode(SW_DOWN, INPUT_PULLUP);
pinMode(PIN_LED1, OUTPUT);
ckEEPROMdata(); // EEPROM有効性確認
}
// EEPROMの有効性確認 ++++++++++++++++++++++
// 1番地;送信速度(文字/分)
// 2番地:トーン周波数(Hz/10)
void ckEEPROMdata(){
// keySpeedデータの確認と短点単位時間への変換
// ch/minで記録、6000/(ch/min)で単位時間
boolean notValid = 0;
keySpeed = EEPROM.read(1);
if((keySpeed % 10)!=0) notValid = 1;
if(keySpeed > 180) notValid = 1;
if(keySpeed < 20) notValid = 1;
//
if(notValid){ // EEPROMデータが無効なら
keySpeed = 60; // デフォルト値に変更
EEPROM.write(1, keySpeed); // EEPROMに上書き
delay(5); // 書き込み時間の確保
}
keySpeed = 6000/keySpeed; // 単位時間に変換
// frequencyデータの確認と周波数値への変換
// データは1/10にして2番地に保管されている
frequency = EEPROM.read(2);
notValid = 0;
if((frequency % 10)!=0) notValid = 1;
if(frequency > 100) notValid = 1;
if(frequency < 40) notValid = 1;
// 無効ならデフォルト値をセット
if(notValid){ // EEPROMデータが無効なら
frequency = 70; // デフォルト値に変更
EEPROM.write(2, frequency); // EEPROMに上書き
delay(5); // 書き込み時間の確保
}
frequency = frequency * 10; // 周波数に変換
}
void loop() {
// 短点が押されてたなら、sendDot()を実行
if(! digitalRead(KEY_DOT)) flagDot = 1;
if(flagDot)sendDot();
// 長点が押されたなら、sendDash()を実行
if(! digitalRead(KEY_DASH)) flagDash = 1;
if(flagDash)sendDash();
// 変更ボタンの確認
if(! digitalRead(SW_UP)) cgParaUp();
if(! digitalRead(SW_DOWN)) cgParaDown();
}
// UPボタンが押された処理 ++++++++++++++++++++++++++
void cgParaUp(){
boolean modeCged = 0;
while(! digitalRead(SW_UP)){ // SW_UPが押下間に
if(! digitalRead(SW_DOWN)){ // SW_DOWNも押されたら
isCgSpd = !isCgSpd; // 変更モードを反転させ
beep(400);beep(600); // 「ピポ」と通知
modeCged = 1; // モード変更を記録
break;
}
}
while(! digitalRead(SW_UP)); // 両方のSWが
while(! digitalRead(SW_DOWN)); // 離れるのを待つ
if(modeCged) delay(20); // チャタリング防止
else if(isCgSpd) cgSpeedUp(); // 送信速度変更へ
else cgFreqUp(); // 周波数変更へ
}
// DOWNボタンが押された処理 ++++++++++++++++++++++++++
void cgParaDown(){
boolean modeCged = 0;
while(! digitalRead(SW_DOWN)){
if(! digitalRead(SW_UP)){
isCgSpd = !isCgSpd;
beep(400);beep(600);
modeCged = 1;
break;
}
}
while(! digitalRead(SW_UP));
while(! digitalRead(SW_DOWN));
if(modeCged) delay(20);
else if(isCgSpd) cgSpeedDown();
else cgFreqDown();
}
void cgSpeedUp(){
while(! digitalRead(SW_UP)); // SWが離れるのを待つ
int data = EEPROM.read(1); // EEPROMの値を読み込む
if(data >= 180){ // 上限なら
beep();beep();beep(); // beep音を3回
}else{ // 変更可能なら
data += 10; // 10増加
EEPROM.write(1, data); // EEPROMに書き込む
beep(); // beep音を1回
keySpeed = 6000/data; // 短点時間に変更
}
}
void cgSpeedDown(){
while(! digitalRead(SW_DOWN)); // SWが離れるのを待つ
int data = EEPROM.read(1); // EEPROMの値を読み込む
if(data <= 20){ // 下限なら
beep();beep();beep(); // beep音を3回
}else{ // 変更可能なら
data -= 10; // 10減少
EEPROM.write(1, data); // EEPROMに書き込む
beep(); // beep音を1回
keySpeed = 6000/data; // 短点時間に変更
}
}
void cgFreqUp(){
while(! digitalRead(SW_UP)); // SWが離れるのを待つ
if(frequency >= 1000){ // 上限なら
beep();beep();beep(); // beep音を3回
}else{ // 変更可能なら
frequency += 100; // 100増加
EEPROM.write(2, frequency/10); // EEPROMに書き込む
beep(frequency); // beep音を1回
}
}
void cgFreqDown(){
while(! digitalRead(SW_DOWN)); // SWが離れるのを待つ
if(frequency <= 400){ // 下限なら
beep();beep();beep(); // beep音を3回
}else{ // 変更可能なら
frequency -= 100; // 10減少
EEPROM.write(2, frequency/10); // EEPROMに書き込む
beep(frequency); // beep音を1回
}
}
// dot信号を送る --------------------------------
void sendDot(){
flagDot = 0; // 端点フラグをクリア
digitalWrite(PIN_LED1, 1); // LED ON
tone(PIN_SPK,frequency); // サイドトーン ON
tUp = millis() + keySpeed; // Mark終了時間セット
while(tUp > millis()){ // Mark終了時間まで待つ
// 長点が押されたなら、長点フラグをセット
if(! digitalRead(KEY_DASH)) flagDash = 1;
}
digitalWrite(PIN_LED1, 0); // LED OFF
noTone(PIN_SPK); // サイドトーン OFF
tUp = millis() + keySpeed; // コード終了時間セット
while(tUp > millis()){ // コード終了を待つ
// 長点が押されたなら、長点フラグをセット
if(! digitalRead(KEY_DASH)) flagDash = 1;
}
}
// Dash信号を送る --------------------------------
void sendDash(){
flagDash = 0;
digitalWrite(PIN_LED1, 1);
tone(PIN_SPK,frequency);
tUp = millis() + (keySpeed * 3);
while(tUp > millis()){
if(! digitalRead(KEY_DOT)) flagDot = 1;
}
digitalWrite(PIN_LED1, 0);
noTone(PIN_SPK);
tUp = millis() + keySpeed;
while(tUp > millis()){
if(! digitalRead(KEY_DOT)) flagDot = 1;
}
}
//++++++++++++++++++++++++++++++++++++++++++++++
// Beep音を鳴らす ON 100ms - OFF 50ms
void beep(int freq){
tone(PIN_SPK,freq,100);
delay(150);
}
void beep(){
tone(PIN_SPK,1000,100);
delay(150);
}
動作の確認
スケッチを Arduino に書き込みプログラムがスタートしたら、接続したパドルを叩いて下ださい。ボード上の「L」LEDが点灯し、LEDに同期してサイドトーンが圧電スピーカーから聞こえます。押しボタンを押すと(正確には離した時)Beep音が1回鳴り送信速度が変更されます。パドルを叩いて確認してください。