見出し画像

Arduinoを使ったDTMF信号解析

皆さん、こんにちは

今日は、DTMF信号解析装置を紹介します。この装置は、M8870Aモジュール、Arduino、1602ALCDモジュールを使用して、
DTMF信号のシーケンス、トーンの遅延を表示するものです。以下では、装置の構成、動作の様子、そして技術的な詳細を順を追って解説します。

M8870Aモジュールの動作確認


まずは、M8870Aモジュールの動作をアップで見てみましょう。DTMF信号を1~0, *, #の順番で鳴らし、その際のM8870AモジュールのLEDの光り方を確認します。このモジュールはDTMF信号を受信すると、対応する信号を二進数に変換し、LEDで表示します。

LEDの光り方の解説
M8870Aモジュールの各LEDは、二進数のビットを表しています。例えば、「1」を押すと、LEDは0001、「2」を押すと0010のように点灯します。各キーに対応する二進数の表示は以下の通りです
1:0001 2:0010 3:0011 4:0100 5:0101 6:0110
7:0111 8:1000 9:1001 0:1010 *:1011 #:1100

受け取った信号を元にLEDが光る(2進数)


装置の構成


Arduino、M8870Aモジュール、1602ALCDモジュールの接続図です

配線図

配線図詳細

Arduino     M8870A
D3       Q1
D4       Q2
D5       Q3
D6       Q4
D7       STQ
5V                          VCC
GND                      GND

Arduino                 1602A_LCD I2C
A4                          SDA
A5                          SDL
5V                          VCC
GND                      GND



接続の詳細

M8870Aモジュール:DTMF信号を受信し、二進数データとしてArduinoに送信します。各出力ピン(Q1, Q2, Q3, Q4)は、対応するデジタルピンに接続されています。
Arduino:M8870Aモジュールからの信号を受け取り、解析して1602ALCDモジュールに表示します。デジタルピンでM8870Aからの入力を受け取り、I2C通信でLCDにデータを送ります。
1602ALCDモジュール:解析されたDTMF信号を表示します。I2Cモジュールを使用してArduinoと接続しています。

  1. 1602ALCDモジュールでの表示確認
    DTMF信号を1~0, *, #の順番で2秒間ずつ鳴らし、その結果が1602ALCDモジュールに正しく表示される様子を確認しましょう。LCDには対応する数字や記号がリアルタイムで表示されるのが確認できます。これにより、信号が正しく受信・解析されていることがわかります。

  2. 高速信号の解析
    最後に、1602ALCDモジュールを、DTMF信号を100ms間隔で鳴らしても正しく数値を読み取る様子をお見せします。短い間隔で鳴らしても、装置が正確に信号をキャッチし、LCDに表示できることを確認します。これにより、装置の高い精度と信頼性が証明されます。

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

unsigned long lastToneTime = 0;  // 前のトーン検出時の時間を記録
unsigned long currentToneTime = 0;  // 現在のトーン検出時の時間を記録
unsigned long intervalSum = 0;  // 全ての間隔の合計
int intervalCount = 0;  // 間隔の数
String dtmfCode = "";  // DTMFコードの連結を記録
bool detectionDisplayed = false; // detection表示フラグ

// LCDの設定
LiquidCrystal_I2C lcd(0x27, 16, 2);  // 0x27はLCDのI2Cアドレス、16x2のLCD

void setup() {
  Serial.begin(9600);
  Wire.begin();
  lcd.init();
  lcd.backlight();

  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
}

void loop() {
  uint8_t number;
  bool signal;
  signal = digitalRead(7);
  if (signal == HIGH) { /*When DTMF tone is detected, STQ will read HIGH for the duration of the tone*/
    if (!detectionDisplayed) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("detection");
      detectionDisplayed = true;
    }
    
    currentToneTime = millis();  // 現在の時間を記録
    if (lastToneTime != 0) {
      unsigned long interval = currentToneTime - lastToneTime;
      intervalSum += interval;
      intervalCount++;
    }
    lastToneTime = currentToneTime;

    delay(100); // デバウンス処理

    number = ( 0x00 | (digitalRead(3) << 0) | (digitalRead(4) << 1) | (digitalRead(5) << 2) | (digitalRead(6) << 3) );
    switch (number) {
      case 0x01:
        dtmfCode += "1";
        break;
      case 0x02:
        dtmfCode += "2";
        break;
      case 0x03:
        dtmfCode += "3";
        break;
      case 0x04:
        dtmfCode += "4";
        break;
      case 0x05:
        dtmfCode += "5";
        break;
      case 0x06:
        dtmfCode += "6";
        break;
      case 0x07:
        dtmfCode += "7";
        break;
      case 0x08:
        dtmfCode += "8";
        break;
      case 0x09:
        dtmfCode += "9";
        break;
      case 0x0A:
        dtmfCode += "0";
        break;
      case 0x0B:
        dtmfCode += "*";
        break;
      case 0x0C:
        dtmfCode += "#";
        break;
    }
  }

  // 1秒以上トーンが検出されなかった場合、信号送信が終了したと判断
  if (lastToneTime != 0 && millis() - lastToneTime > 1000) {
    if (intervalCount > 0) {
      unsigned long averageInterval = intervalSum / intervalCount;

      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(dtmfCode);

      lcd.setCursor(0, 1);
      lcd.print("interval: ");
      lcd.print(averageInterval);
      lcd.print(" ms");

      Serial.print("DTMF CODE: ");
      Serial.println(dtmfCode);
      Serial.print("interval: ");
      Serial.print(averageInterval);
      Serial.println(" ms");
    } else {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("No intervals");
      lcd.setCursor(0, 1);
      lcd.print("recorded.");
      Serial.println("No intervals recorded.");
    }
    
    // 変数のリセット
    lastToneTime = 0;
    intervalSum = 0;
    intervalCount = 0;
    dtmfCode = "";  // DTMFコードのリセット
    detectionDisplayed = false; // フラグのリセット
  }
}

高速信号処理の実装
100ms間隔で信号を解析するためには、Arduinoの処理速度と信号の安定性が重要です。短い遅延時間で正確にデータを読み取るため、上記のコードではdelay()関数を最小限に抑え、データの取得と表示を効率的に行っています。


結論

このDTMF信号解析装置は、M8870Aモジュール、Arduino、1602ALCDモジュールの連携によって実現されています。電話システムのデバッグやセキュリティシステムの設定、教育や研究、DIYプロジェクトにおいて非常に有用です。興味のある方はぜひ試してみてください。

それでは、次回の記事をお楽しみに!


この記事が気に入ったらサポートをしてみませんか?