10月28日のブログで紹介した「ESP32とPCをBluetoothで接続する」に少々手を加えて、ICOMの無線機に標準装備されているCIVを使ってBluetoothでワイヤレス接続しました。
最近の無線機はUSBケーブル1本で遠隔操作も音声信号の入出力もできるようになっているので、わざわざBluetoothで遠隔操作するまでもないと思われるかもしれませんが、USB接続の場合、無線機とPCとのGNDが相互に接続されてしまい、コモンモードノイズに弱いためインターフェア(干渉・回り込み)による悪影響を受けることがあります。BlutoothだとワイヤレスなのでGNDは隔離されているため、インターフェアの心配がありません。 11月14日のブログで紹介した「IC-7851でFT8を2波同時受信する」に用いたS/PDIF光オーディオで無線機とPCを接続すれば、FT8などのデジタルモードの運用時にもPCと無線機を隔離することができます。
前置きが長くなりましたが、ESP32基板に、文末に示すソースコードをコンパイルして書き込みました。
ESP32基板はCIVとBlutoothのブリッジの役割を果たします。CIVのボーレートはソースコードに記述しているように9600bpsに固定されています。
Bluetooth側からデータを1バイト受信したらCIV側に1バイト書き込みます。CIVはパーティーライン(バス接続)なので、送信したデータを受信してしまいますので、これを読み捨てます。
CIV側からデータを1バイト受信したらBluetooth側に1バイト書き込みます。
BluetoothとCIVのいずれのポートからデータを受信した場合でも、USBシリアルポートにデータを送信するようにしています。
CIVプロトコルではFDというバイト値はデリミタなので、データがFDの時はUSBシリアルポート側に改行コードを送信して見やすくしています。
書き込みや実験の際にはESP32ボードをPCにUSB接続しましたが、使用する時には電源(DC5V)をUSBコネクタから供給してやればOKです。
ESP32基板とPCをUSBケーブルで接続して、TeraTerm等のターミナルソフトを接続すれば、CIVのプロトコルアナライザ的な使い方ができます。次の画像はターミナルソフトとしてArduinoのシリアルモニタを使ってPC側でWSJT-Xを動作させている時の様子です。PCから周期的にIC-7851(アドレス8E)に問合わせをして、その応答を得ていることが分かります。
/* Connecting ICOM radio to PC via Bluetooth
* ESP32 act as a bridge between radio and PC
* by Hidef NAMVA JH4ADK 2022.11.06
*/
#include "BluetoothSerial.h" //Header File for Serial Bluetooth, will be added by default into Arduino
HardwareSerial SerialCIV(2); //Use UART2 for serial connection to radio PIN16(RX), 17(TX) pair
BluetoothSerial ESP_BT; //Object for Bluetooth
int incoming, inByte;
int LED_BUILTIN = 2;
void setup() {
Serial.begin(115200); //start serial monitor via USB port(UART0)
SerialCIV.begin(9600); //start CIV port(UART2)
ESP_BT.begin("ESP32_CIV"); //Name of your Bluetooth Signal
Serial.println("Bluetooth Device is Ready to Pair");
pinMode (LED_BUILTIN, OUTPUT);//Specify that LED pin is output
digitalWrite(LED_BUILTIN, HIGH);
}
void loop() {
if (ESP_BT.available()) //Check if we receive anything from Bluetooth
{
incoming = ESP_BT.read(); //Read a byte from Bluetooth
SerialCIV.write(incoming);
SerialCIV.flush();
Serial.print('>');
if (incoming < 0x10)
{
Serial.print('0');
}
Serial.print(incoming, HEX);
if (incoming == 0xFD)
{
Serial.println(' ');
}
Serial.flush(); //To make a little delay
inByte = SerialCIV.read(); //Read and drop it that is an echo
if (inByte < 0)
{
delay(1);
SerialCIV.read(); //Read again after delay
}
}
if (SerialCIV.available()) {
inByte = SerialCIV.read();
ESP_BT.write(inByte);
Serial.print('<');
if (inByte < 0x10)
{
Serial.print('0');
}
Serial.print(inByte, HEX);
if (inByte == 0xFD)
{
Serial.println(' ');
}
}
delay(20);
}