工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

レーザーモジュールでモールス信号通信 – Arduino二台で送受信

必要なパーツと用品

Arduino UNO ×2
ブレッドボード ×2
レーザートランスミッター ×1
フォトレジスター(CdSセル) ×1
ジャンパーワイヤー ×1

使用するアプリ

プロジェクト概要

モールス信号とは

英数字を「点(・)」と「線(−)」の組み合わせで表現する通信方式です。各文字に固有のパターンがあり、秘密通信や符号化通信に用いられます。本プロジェクトでは、レーザー光でモールス信号を送信し、受信側で光センサー(CdSセル)を使って復調・文字表示を行います。受信アルゴリズムが非常にシンプルなのが特徴です。

レーザーモジュールでモールス信号通信 – Arduino二台で送受信

ステップ1: 送信側(トランスミッター)

必要なハードウェア

配線

レーザーの+ピンをArduinoのデジタル13番ピンに、GNDをArduinoのGNDに接続します(コード内で13番ピン指定)。

レーザーモジュールでモールス信号通信 – Arduino二台で送受信
レーザーモジュールでモールス信号通信 – Arduino二台で送受信
レーザーモジュールでモールス信号通信 – Arduino二台で送受信

プログラムのアルゴリズム

  1. 送信したい文字列を char 配列で保持
  2. レーザー接続ピン(13番)を定義
  3. モールス符号の速度(ドット長)を設定
    • ドット長 = dotLen (ms)
    • ダッシュ長 = ドット長 × 3
    • 要素間スペース = ドット長
    • 文字間スペース = ドット長 × 3
    • 単語間スペース = ドット長 × 7
  4. 各文字を switch-case で判定し、対応するドット/ダッシュのパターンでレーザーをON/OFF

ステップ2: 受信側(レシーバー)

送信された光信号をCdSセルで受光し、シリアルモニタに文字を表示します。

レーザーモジュールでモールス信号通信 – Arduino二台で送受信
レーザーモジュールでモールス信号通信 – Arduino二台で送受信

必要なハードウェア

配線

CdSセルの一方を5V、もう一方を10kΩ抵抗とアナログ入力A0に接続。抵抗のもう一方をGNDに接続(分圧回路)。CdSセルは黒い厚紙でドームを作って覆い、外光を遮ると安定します。

レーザーモジュールでモールス信号通信 – Arduino二台で送受信
レーザーモジュールでモールス信号通信 – Arduino二台で送受信

受信アルゴリズム(観測ベースのシンプルな手法)

  1. レーザーが当たっていないとき、CdS値は1000未満。当たると1000を超える。外光の影響がある場合は遮光ドームで対策。
  2. 値が1000を超えたらループに入り、閾値1000で二値化:超えてたら '1'、以下なら '0' とみなす。
  3. ループ内で '1' の継続カウント(変数 a)と '0' の継続カウント(変数 f)を取る。
  4. 各文字ごとに a と f の組み合わせがユニークになるため、パターンマッチングで文字を特定。

制限事項

添付コードは特定の文字(a, b, c, e, i, j, g, o, s)のみ対応。組み合わせを拡張すれば全英数字に対応可能です。本コードの主目的はアルゴリズムの理解です。

ソースコード

CODE-1: 送信側(レーザー制御)

int led13 = 13;
int dotLen = 200;
int dashLen = dotLen * 3;
int elemPause = dotLen;
int Spaces = dotLen * 3;
int wordPause = dotLen * 7;

char stringToMorseCode[] = "HELLO WORLD";  // 送信したい文字列

void setup() {
  pinMode(led13, OUTPUT);
}

void loop() {
  for (int i = 0; i < sizeof(stringToMorseCode) - 1; i++) {
    char tmpChar = stringToMorseCode[i];
    tmpChar = toLowerCase(tmpChar);
    GetChar(tmpChar);
  }
  LightsOff(8000);  // 文字列終了後の長いポーズ
}

void MorseDot() {
  digitalWrite(led13, HIGH);
  delay(dotLen);
}

void MorseDash() {
  digitalWrite(led13, HIGH);
  delay(dashLen);
}

void LightsOff(int delayTime) {
  digitalWrite(led13, LOW);
  delay(delayTime);
}

void GetChar(char tmpChar) {
  switch (tmpChar) {
    case 'a': MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'b': MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'c': MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'd': MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'e': MorseDot(); LightsOff(elemPause); break;
    case 'f': MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'g': MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'h': MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'i': MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'j': MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'k': MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'l': MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'm': MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'n': MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'o': MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'p': MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 'q': MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'r': MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 's': MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    case 't': MorseDash(); LightsOff(elemPause); break;
    case 'u': MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'v': MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'w': MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'x': MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'y': MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); break;
    case 'z': MorseDash(); LightsOff(elemPause); MorseDash(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); MorseDot(); LightsOff(elemPause); break;
    default: LightsOff(Spaces); break;  // スペース等
  }
}

CODE-2: 受信側(CdSセル読み取り・文字判定)

int sensorPin = 0;
int sensorValue = 0;
int a, f;

void setup() {
  Serial.begin(9600);
}

void loop() {
  sensorValue = analogRead(sensorPin);
  if (sensorValue > 1000) {
    for (int i = 0; i <= 13; i++) {
      sensorValue = analogRead(sensorPin);
      if (sensorValue > 1000) {
        a++;  // '1' (光あり) のカウント
        delay(200);
      } else {
        f++;  // '0' (光なし) のカウント
        delay(200);
      }
    }
  }
  // パターンマッチングで文字判定
  if (a == 4 && f == 10) { Serial.print("a"); }
  if (a == 6 && f == 8)  { Serial.print("b"); }
  if (a == 8 && f == 6)  { Serial.print("c"); }
  if (a == 1 && f == 13) { Serial.print("e"); }
  if (a == 2 && f == 12) { Serial.print("i"); }
  if (a == 10 && f == 4) { Serial.print("j"); }
  if (a == 7 && f == 7)  { Serial.print("g"); }
  if (a == 9 && f == 5)  { Serial.print("o"); }
  if (a == 3 && f == 11) { Serial.print("s"); }
  f = a = 0;
  delay(200);
}

カスタムパーツとエンクロージャ

レーザーモジュールでモールス信号通信 – Arduino二台で送受信

回路図

レーザーモジュールでモールス信号通信 – Arduino二台で送受信

製造プロセス

  1. レーザーマーキング総合ガイド:種類、メリット、用途
  2. レーザーポインター:設計、製造、安全性の概要
  3. 半導体レーザー:現代技術を支える精密光生成
  4. バーコードスキャナ:技術、設計、将来動向
  5. レーザー誘導ミサイル:開発、製造、戦略的インパクト
  6. ZigbeeセンサーとGravioエッジプラットフォームでインタラクティブレーザープロジェクターを構築
  7. Raspberry Pi 4とHiFive1ボード間でUART通信を確立する
  8. Raspberry Pi でジェスチャー制御ロボットを構築 – 加速度センサーと RF 通信でハンドフリー操作
  9. ArduinoだけでDTMFデコーダーを構築 – 外付けIC不要
  10. Python 3からArduino UNOを制御 – シリアル通信でLED点滅デモ
  11. 産業製造におけるローコードソリューションの4つの主要メリット