Top Page トランスバータ用CI-V周波数変換
自作工程のメモとして
02.May.2018
2018/11/23:更新


 昨年のテーマ「IC-7600 のトランスバータ端子を使う」でIC-7600にトランスバータ(以下:TRV)を接続しましたが、TRVモードにしてもIC-7600のCI-V出力は親機の28MHzのままで、例えばMMVARIを使うと周波数情報が144MHzに成りません。
本当なら、IC-7600側のファームウェアで処理してもらえれば何の問題も無いのですが、対応してもらえそうも無いので少し困っていました。
そこで、PICを使ってCI-Vの周波数情報を変換する装置を作ろうと基板を作りかけましたが、「Mikro C」を長いこと使ってなかったので重い腰が上がらず、試しにArduino を使って変換装置を作ってみようとブレッドボードで組んでみると、思いのほか簡単に実現できたようなのでArduino Nanoを使って掲載します。


簡単なものですが完成品です。
最初のもの(改善前)

次項に有る回路の内、抵抗とダイオードをそれぞれ1本使うだけで、その他は組込み先の回路を流用しています。

STM32F103で改善したもの

2018/11/23:Arduino NanoからSTM32F103に変更しました。

Edit by bluegriffon3.0.1


1.回路図

 動作確認は、Arduino UNO(互換)で実施しましたが、UNOでは大き過ぎるので実装はNanoを使います。
Serialポートは1つだけなので、SoftwareSerial機能を使い単純な回路としています。


■ 回路図(改善前)


おまじないのLとC、衝突回避のRとDだけで、通常でしたらL2の右側に付けるプルアップ抵抗は省略しました。


2.スケッチ(ソースプログラム)

 このスケッチでは、Rig側のCI-Vスピードを9600bps・パソコン(以下:PC)側を19200bpsに設定しています。
同じスピードでも問題無いと思いますが、速度変換も実現する試みとしてこのまま使用する予定です。
また、SoftwareSerial 側はスピードがそんなに上げられないと思いますが、変換だけの処理しかしていないので9600bpsでは問題はないようです。
なお、周波数変換をせずにスピード変換だけでしたら、void loop()内の記述は2行で済んでしまうほど単純な処理になります。

■ トランスバータ用周波数変換のスケッチ(IC-7600 + 144MHzTRVを想定)(改善前)

// 2018/04/30
/*
  IC-7600+144M トランスバータ(TRV)対応用のCI-V(周波数データ)変換

  例)ハムログ等では、TRV使用を前提とした周波数加減算用の設定は有るが、
  MMVARIでは、その変換が無い。
  そのため、PCが受信する周波数データのみ+116MHz加算したCI-Vデータに変換する。
  参考:Arduino 日本語リファレンス の ソフトウェアシリアルのサンプルコード
*/

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // SoftRX Pin, SoftTX Pin
int state = 0;
byte rxchar;
int trvON = 0;

void setup() {
  Serial.begin(19200); // ハードウェアシリアルを準備
  mySerial.begin(9600); // ソフトウェアシリアルの初期化
}

void loop()
{
  // if (mySerial.available()) Serial.write(mySerial.read());  // この行を以下のように変更する。
  if (mySerial.available()) {
    rxchar = mySerial.read();
    switch (state) {
      case 10:
        state = 0;
        break;
      case 9:
        if ((trvON == 1) && (rxchar == 0x00)) rxchar = 0x01;
        state++;
        break;
      case 8:
        if ((rxchar >= 0x28) && (rxchar <= 0x29)) {
          rxchar = rxchar + 28;
          trvON = 1;
        } else {
          trvON = 0;
        }
        state++;
        break;
      case 7:
      case 6:
      case 5:
      case 3:
      case 2:
        state++;
        break;
      case 4:
        if ((rxchar == 0x00) || (rxchar == 0x03))   // 5Byte目のコマンド00 or 03 のみ
          // stateをカウントUP
        {
          state++;
        } else {
          state = 0;
        }
        break;
      case 1:
      case 0:
        if (rxchar == 0xfe)
        {
          state++;
        } else {
          state = 0;
        }
        break;
    }
    if (rxchar == 0xfd) state = 0;
    Serial.write(rxchar );
  }
  if (Serial.available()) mySerial.write(Serial.read());
}





3.ケースへの実装

 実装に当たっては小さな箱を探しましたが適当なものが見つからず、別テーマの「CI-V_HUBの製作」の箱にスペースが有るのでそこに入れ込むことにしました。

■ 別の箱(CI-V_HUB)の空きスペースに実装した状態(改善前)

回路上のチョークコイル(L)は、CI-V_HUBの物を使用しています。




9.その他気づいたこと

(1)144MHz帯でjtdx wsjt-x 等を使用するとき、RadioにIC-7600を指定すると「Rig Control error」になります。
jtdx wsjt-x 等の設定(File ==>Setting==>Radio)でRig にIC-7600を指定すると、本来の周波数範囲外(144MHz)のため、エラーとなります。そのため、Rigは無し(None)として使用します。
この時はCATでの送信ができないため、「PTT Method」で「Port」とRTS・DTR等を選択する必要が有ります。
MMVARIでは、CI-Vアドレスを指定する設定のため、144MHz帯の周波数読取やCI-Vでの送受信操作も問題無く使えます。

(2)上記(1)にwsjt-xでの設定について記述しましたが、周波数の設定項目にトランスバータが有り、設定してみました。(2018/10/14)

Settings ==> Frequencies

先に周波数の設定で、Station Informationに2mバンドのOffset(116MHz)を記述します。

Settings ==> Radio
次にRigの設定で、HF/6m機のIC-7600を設定すると、周波数関係のエラーが出ずに使えるようです。
ついでに、PTT MethodをCAT指定に変えてみました。
また、Modeは今までNoneにしていましたが、Data/Pktに変えています。これでRig側がUSBモードでも自動的に[USB-D1]等に切り替わってくれます。
さらに、Sprit Operationは、Rigになっていた(Spritモードになる)のでNoneにして変更しています。

PSK31はほとんど見かけなくなりましたので、今後MMVARIを使うことが無くなれば、本変換装置は不要になってしまいます。

(3)都度追記します。




99.STM32F103による改善(2018/11/23)

 上記のArduino Nanoを使ったCI-V信号の変換では、RIGからの周波数データを受け取るだけなら問題が無いようでしたが、PC側から送出中のCI-V信号の受信がSoftwareSerialではできず、大幅な文字化け・欠落が起きていました。
また、USBケーブルを外しているときにCI-Vの信号ラインが1.3V程度に引き落とされていることが分かりました。
そこで、ほとんど使わないような機能かも知れませんが、2ch以上のUSARTを持つCPUを探して作り直すことにしました。


(1)CPU検討

Arduino系ではUSARTを2ch持っているのはDUE・MEGAしか思い当たりません。
しかし、簡単な処理にそこまでの物を使うことも大げさですし、Arduino Nanoを使った収納サイズの制約が有りますので、同程度のサイズであるSTM32F103を採用することにしました。


(2)USBケーブルを外しているときのCI-V信号処理

以前も経験していたことですが、電源OFF時の処理を省略して済ませていたことから、作り直しに併せて新しいフォトリレーによる方法を採用することにしました。

以前の電源OFF時のCI-V信号引き落とし防止処理

46 SD330 コントローラ製作 2010.12.31 より

(3)回路構成

画像クリックで拡大します。
1.STM32F103(Blue Pill)にもUSBが有り、ハードウエアーシリアルと同様の操作をしますが、HOST(PC側)でDTR信号をONにしないと受信ができないようなので、別のUSB端子を付けてその受けにFT230を使っています。
(STM32F103のR10 は事前に 1.5kΩ抵抗 (152) に取り換え済)
2.電源OFF(USBケーブルを外しているとき)の処理には、フォトリレーTLP222を使ってCI-V信号の遮断を行っています。

(4)作り直したCI-Vコンバータ(写真3枚を合成)


STM32F103は、赤基板の表・裏の両面に取り付けられるようにして、ケースの高さ(30mm)の関係から裏面設置にしています。
ただし、取り付け穴の関係からケースへの実装時には、全体を裏返しにし取り付けています。
また、フォトリレーTLP222も両面に取り付けられるよう、パターンを工夫をしています。
合計40ピンのピンヘッダは、全部を付けると抜き差しが重くなるので、信号の有る部分を中心に半分程度にしています。
LED(D1)は、ケース収納時に見ることが無いので未実装です。
わざわざ基板を起こすほどでもありませんが、USB Micro-Bソケットを取付けるためにFusionPCBに3枚発注しました。
また、Micro-Bソケットは、手ハンダし易いように信号ピンの長いタイプを選択しています。

(5)スケッチ

/*
 * 2018/10/04
 * STM32F103C8T6 ARM Cortex-M3 CPU 72MH 用
 * Arduino IDE のボード設定
 * ===========================================
 * ボード:"Generic STM32F103C series"
 * Variant:"STM32F103C((20k RAM,64k flash"
 * CPU Speed(MHz):72MHz(Normal
 * Upload method:STM32duino bootloader"
 * Optimize:"Smallest(default)"
 * シリアルポート:"COM10(Maple Mini)"
 * ============================================
*/
#define LED_PIN PC13 // PC13 or 32 or D32
int RDposi = 0;
int PCposi = 0;
byte RDchar, PCchar;
int RDtrvON = 0;
int RDfreqDATA = 0;
int PCtrvON = 0;
int PCfreqDATA = 0;

const byte RealRadio = 0x7A;    // ◆◆実際のCI-Vアドレス IC-7600
const byte VirtRadio = 0x60;    // ◆◆仮想のCI-Vアドレス IC-910

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial1.begin(19200); // ハードウェアシリアル1(PC側)
  // while (!Serial) delay(50); // STM32 USB-シリアル用  書込み後のUSBシリアルの解放を待つ。
  Serial3.begin(9600); // ハードウェアシリアル3(Radio側)
  digitalWrite(LED_PIN, LOW);
  delay(50);
  digitalWrite(LED_PIN, HIGH);
}
void loop()
{
  if (Serial3.available()) { // ■■■■Radio(RD)からPCに向かってのCI-V信号処理■■■■
    RDchar = Serial3.read();
    if (RDchar == 0xfd) {
      RDtrvON = 0;
      RDfreqDATA = 0;
      RDposi = 0;
    } else {
      switch (RDposi) {
        case 9:
          if ((RDtrvON == 1) && (RDchar == 0x00)) RDchar = 0x01;
          RDposi++;
          break;
        case 8:
          if ((RDfreqDATA == 1) && (RDchar >= 0x28) && (RDchar <= 0x29)) {
            RDchar = RDchar + 28; // (0x28=40) + 28  = (68=0x44)
            RDtrvON = 1;
          } else {
            RDtrvON = 0;
          }
          RDposi++;
          break;
        case 4:
          if ((RDchar == 0x00) || (RDchar == 0x03) || (RDchar == 0x05) )   // 5Byte目のコマンド00 or 03 のみ
            RDfreqDATA = 1;
          else
            RDfreqDATA = 0;
          RDposi++;
          break;
        case 3:
          if (RDchar == RealRadio)   // IC-7600からの信号なら
          {
            RDchar = VirtRadio; // 仮想の機種に変換
          }
          RDposi++;
          break;
        case 2:
          if (RDchar == RealRadio)   // PCから送出した信号のエコーバック(CI-V折り返し信号)
          {
            RDchar = VirtRadio; // 仮想の機種に変換
          }
          RDposi++;
          break;
        case 1:
        case 0:
          if (RDchar == 0xfe)
          {
            RDposi++;
          } else {
            RDposi = 0;
          }
          break;
        default:
          RDposi++;
          break;
      }
    }
    Serial1.write(RDchar );
  }

  if (Serial1.available()) { // ■■■■パソコン(PC)からRADIOに向かってのCI-V信号処理■■■■
    PCchar = Serial1.read();
    if (PCchar == 0xfd) {
      PCtrvON = 0;
      PCfreqDATA = 0;
      PCposi = 0;
    } else {
      switch (PCposi) {
        case 9:
          if ((PCtrvON == 1) && (PCchar == 0x01)) PCchar = 0x00;
          PCposi++;
          break;
        case 8:
          if ((PCfreqDATA == 1) && (PCchar >= 0x44) && (PCchar <= 0x45)) {
            PCchar = PCchar - 28; // (0x44=68)  - 28  = (40=0x28)
            PCtrvON = 1;
          } else {
            PCtrvON = 0;
          }
          PCposi++;
          break;
        case 4:
          if ((PCchar == 0x00) || (PCchar == 0x03) || (PCchar == 0x05) )   // 5Byte目のコマンド00 or 03 のみ
            PCfreqDATA = 1;
          else
            PCfreqDATA = 0;
          PCposi++;
          break;
        case 2:
          if (PCchar == VirtRadio)   // 仮想の機種向けの信号なら
          {
            PCchar = RealRadio; // IC-7600へ変換してRADIO側へ送信する
          }
          PCposi++;
          break;
        case 1:
        case 0:
          if (PCchar == 0xfe)
          {
            PCposi++;
          } else {
            PCposi = 0;
          }
          break;
        default:
          PCposi++;
          break;
      }
    }
    Serial3.write(PCchar );
  }
}



以上で、双方向の信号を取り逃すことが無くなりました。