このサイトはMacを使って Arduino Uno の動作や活用法を学びます。

28 Arduino モールス通信キーヤーを作成 3

この記事では、モールス通信をするときに使用するエレクトリック・キーヤーを作成します。前回は送信速度設定ができるように変更しました。今回はさらにサイドトーンの周波数も変更できるよう改造します。ハードウエアの変更はありません。

押しボタンSWはUp/Downの1組しかないのに、2組のパラメータを変更しなければなりません。解決策としてこのスケッチでは、二つの押しボタンを同時に押すと設定するパラメータの切り替えができるように考えました。

プログラムの流れ

setup関数内のEEPROMからデーターを読み込む関数 ckEEPROMdata( ) を実行します。今までの送信速度(1番地)の処理に加えサイドトーン周波数(2番地)も処理します。

loop関数内では、送信速度を設定するSWが押されたか確認し、UPキーが押されればcgParaUp関数を実行、DOWNキーが押されれば cgParaDOWN関数を実行します。

スケッチの内容

前回のスケッチに周波数変更部分を追加しました。主たるプログラムフローの変更はありません。ハードウエアの変更をせずにソフトウエアで対応したためプログラムが長くなってしましました。

 

// 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回鳴り送信速度が変更されます。パドルを叩いて確認してください。