久々に使う Arduino Uno R3 の使い方を思い出してみる(中編)
という事で前回、久しぶりに頭の引き出しから出してみたモールスの知識。だいたいの設計は完了したので、実際に書くための準備に入ります。
コードへの落とし込み
Arduinoに落とし込む場合、CPMだ!WPMだ!と言ったところで スケッチ上意味をなさない(Ariduinoが理解できない)単位を持ち出しても意味がありません。Arduinoで理解できる単位で落とし込んでいく必要があります。
最初に定義されたモールス符号の条件
- 基準となるのは「短点」これを任意の時間で定める。
- 「長点」は「短点」の3倍の長さと定める。
- 各点の間は「短点」の長さと同じと定める。
- 各文字の間は「短点」の3倍の長さと定める。
- 各単語の間は「短点」の7倍の長さと定める。
これを眺めると、すべてが「短点」の長さに紐づく話になっています。
なので、単純に1短点がどの程度の長さなのかを考えればいいことになります。
Lチカのコードをそのまま流用することを考えると、delayを使用するわけですが、これは “ms” 記述。なら、それぞれのWPMの時の短点の”ms”を計算すればいい。という簡単な結論になります。
WPMと”ms”の変換の検討
1WPM は 1分間に 1Word を打つ計算。1Word は 50Dots ですから、単純に50DPS。 60Sec で 50Dots 打つとなると1Dot あたり 1.2Secで打つ計算になります。ただ 50Dots は Dot が 50キーイングする計算ではなく、Dot幅で50回分の意味。なので、実際にキーイングされる数は十分に小さい数になります。(PARISと打った場合、10 Dots・4 Dashsで、実際にキーイングされている時間は 24Dots 分で、26Dots 分は間の部分になっています。)
これを計算式にすると
Dot = 60 / (50 * WPM) ※ (Sec)
という感じ。この数式をスケッチにいれときゃOKってことになるでしょうか。
参考までに、手計算した結果。
ライセンス | Words Per Minute | Dots Per Minute | Seconds Per Dot |
---|---|---|---|
1アマ | 12WPM | 600DPM | 100ms |
2アマ | 9WPM | 450DPM | 133ms |
電信アマ | 5WPM | 250DPM | 240ms |
割と資格によって速度差があったみたいですね。
単純にこのアイデアを書くとこれだけ。
// int WPM2SPD(int WPM){ int Dot; Dot = (60 / (50 * (double)WPM))*1000; return Dot; }
うん、単純。
WPMの前に(double)をつけてるの。これは単純に割り算が理由。 この数式。最後の*1000するまでは「小数点以下」の値が出てくる。 だけど、WPMがintだと計算結果が小数点以下切り捨てられてゼロになっちゃう。 なので、キャストしておく。 *1000の部分は単純にSecからmSecへの変換。
モールス符号を仕込む
次は実際にモールスで送信(キーイング)するための情報を準備。 実際に”A”という文字を”・-”に置き換える為の諸情報を与えて上げる必要があります。
ベタにやるなら…
a[] = {1,2,0,0}; b[] = {2,1,1,1}; c[] = {2,1,2,1}; d[] = {2,1,1,0}; ... x[] = {2,1,1,2}; y[] = {2,1,2,2}; z[] = {2,2,1,1};
こんなアホなやり方もあるだろうけど、これはこれでスタイリッシュさに欠けます。
別方法を考えてみます。文字に対する符号を配列でぶち込んでやればきれいに収まります。 Arduinoの配列は C と同じ感じでこんな感じで記述します。
int morseCode[26][4] = { // DOT=1 , DASH=2 , BLANK=0 {1,2,0,0}, {2,1,1,1}, {2,1,2,1}, {2,1,1,0}, {1,0,0,0}, // A,B,C,D,E {1,1,2,1}, {2,2,1,0}, {1,1,1,1}, {1,1,0,0}, {1,2,2,2}, // F,G,H,I,J {2,1,2,0}, {1,2,1,1}, {2,2,0,0}, {2,1,0,0}, {2,2,2,0}, // K,L,N,M,O {1,2,2,1}, {2,2,1,2}, {1,2,1,0}, {1,1,1,0}, {2,0,0,0}, // P,Q,R,S,T {1,1,2,0}, {1,1,1,2}, {1,2,2,0}, {2,1,1,2}, {2,1,2,2}, // U,V,W,X,Y {2,2,1,1} }; // Z
あとは、ABC…の文字に対応して変数の中身が取り出せればいいわけですね。 そうなると、文字を文字コードに変換して数字として取り出してみればいい。 Arduino的には、文字を文字コードにするのはどうすんのよ?となるのですが。これ、考えるまでもなく。
int CharCode = (int)keyingChar;
で終わりです。”A”が文字コードで 66 ですから、(int)keyingChar-66とすれば対応できることになります。
実際に指定した文字を打ってみる
ここまでおぜん立てしたら、とりあえず、任意の文字を打ってみましょう。 モールスの定義のところで、アルファベット以外の部分を端折ったので、その部分は無いものとして簡単に考えます。
void keying (String Text) { int i, j; for ( i=0; i<Text.length(); i++) { for ( j=0; j<4; j++) { switch (morseCode[(int)Text.charAt(i)-65][j]){ case 1: // DOT digitalWrite(LED_BUILTIN, HIGH); delay(KeyingSpeed); digitalWrite(LED_BUILTIN, LOW); delay(KeyingSpeed); break; case 2: // DASH digitalWrite(LED_BUILTIN, HIGH); delay(KeyingSpeed*3); digitalWrite(LED_BUILTIN, LOW); delay(KeyingSpeed); break; default: // BLANK break; } delay(KeyingSpeed*2); } delay(KeyingSpeed*4); } }
delayを使っているので、美しい書き方ではないけれど、Blinkを基準に作るならこんな感じでしょうかね。
と、ここまで考えて時間切れ。 大人の自由研究は本当に時間との戦いだなぁ。 昔ならまとまった時間で一気に遊べたのに…。
という事で次回に続く。