jde's ham salon

D-STARを主に最近のデジタル通信の情報や地域活動などいろいろと投稿しています。

M5Stackを利用してICOM製無線機用のBluetoothリモコンを作ってみた。(画像変更)

2021-08-01 10:22:23 | アマチュア無線
M5Stackを利用してICOM製無線機用のBluetoothリモコンを作ってみた。
ID-4100+Bluetoothユニット(UT-137)の構成で無事ペアリングも出来てリモコン操作も出来るようになりました。
スマホ用片耳Bluetoothヘッドセットと同時接続で無線機から離れていてもQSOが出来る事も確認しました。
リモコンと言っても機能限定で、【送信(X'mit)】、【受信(Rcv)】、【電源断(Poff)】の3つだけです。
 バッテリー残量表示を追加しました。


【仕様変更】
・Bluetoothが接続されないと、上記のボタンの表示をしないようにしました。
 10秒間隔で、接続要求をM5Stack側から出すように変更。
・接続するRig のBluetooth名とCI-Vアドレスを変数として定義する様に変更しました、Rigに合わせてこの2か所の変数を書き換えるだけにしました。

X'mit】(Aボタン):誤操作防止用に,100ms程度ボタンを押さないと有効にならないようにしました。
 CI-Vコマンド: FE FE 9A 10 1C 00 01 FD  
【Poff】 (Bボタン):1秒以上押していると、無線機電源オフします。
           緊急時の電源切断用に準備しました。
 CI-Vコマンド: FE FE 9A 10 18 00 FD
【Rcv】 (Cボタン):押すだけで即反応し、「Recive」の表示は0.5秒で消えます
 CI-Vコマンド: FE FE 9A 10 1C 00 00 FD

起動時の接続も、無線機が起動すれば自動的にM5と接続する事も確認できました。
CI-Vアドレスを各無線機に合わせて変更すればその他Bluetooth搭載のICOM製無線機も利用可能です。(未検証ですが・・)
作成した拙いスケッチのサンプルを公開します。
改善点などが有りましたらご教授頂けると大変助かります。
※ブログのエディターの関係で上手く掲載できませんでした。

【BT_PTT_for_ID4100】
// ICOM製 Bluetooth付き無線機用リモートPTTユニットProgram
// Bluetooth名 、CI-Vアドレスを利用する無線機用に変更する事で利用可能
#include <M5Stack.h>
#include "BluetoothSerial.h"

// 接続するRIGに合わせて値を書き換えて下さい
int8_t id = 0x9a ; // Icom CI-V アドレス(ID-4100)
String BTname = "ICOM BT-003"; // Bluetoothアダプタ名(ID-4100用)

// Battery残量表示用
#define RGB(r,g,b) (int16_t)(b + (g << 5) + (r << 11)) //色0~31 緑0~63
unsigned long currentMillis;
unsigned long lastupdateMillis = 0;
int lastbattery = -1;

// Bluetooth通信用
BluetoothSerial SerialBT;

void setup() {
M5.begin();
Wire.begin();
SerialBT.begin("M5-PTT"); // M5 Bluetooth名の設定及び初期化
M5.Lcd.clear();

M5.Lcd.setCursor(0, 0);
M5.Lcd.setTextSize(2);
M5.Lcd.println(String("Connecting to ") + BTname );
M5.Lcd.setTextSize(1);
bool connected = SerialBT.connect(BTname);

// BT接続完了するまでループ
if (connected) {
M5.Lcd.println("Connected Succesfully!");
} else {
while (!SerialBT.connected(10000)) {
M5.Lcd.println("Failed to connect. retry ...");
bool connected = SerialBT.connect(BTname); // BT接続Fail表示後、接続要求再送信
}
}
M5.Lcd.clear();
Lcdinit();
M5.Speaker.setBeep(3800, 1000); // Beep音設定
// バッテリー残量表示用タスク
xTaskCreatePinnedToCore(task0, "displayBatteryLevel", 4096, NULL, 1, NULL, 1);
}

// マルチタスクにて10秒間隔でバッテリ残量チェック及び表示
void task0(void *args) {
while (1) {
currentMillis = millis();

if (currentMillis - lastupdateMillis > 1000) {
int battlevel = 0;
byte retval;
Wire.beginTransmission(0x75);
Wire.write(0x78);
if (Wire.endTransmission(false) == 0 && Wire.requestFrom(0x75, 1)) {
retval = Wire.read() & 0xF0;
if (retval == 0xE0) battlevel = 25;
else if (retval == 0xC0) battlevel = 50;
else if (retval == 0x80) battlevel = 75;
else if (retval == 0x00) battlevel = 100;
}
if (lastbattery != battlevel) {
M5.Lcd.fillRect(250, 5, 56, 21, RGB(31, 63, 31)); // バッテリー本体部分
M5.Lcd.fillRect(306, 9, 4, 13, RGB(31, 63, 31)); // バッテリーの電極部分
M5.Lcd.fillRect(252, 7, 52, 17, RGB(0, 0, 0)); // バッテリー本体中抜き
if (battlevel <= 25)
M5.Lcd.fillRect(253, 8, battlevel / 2, 15, RED); // バッテリー25%残表示
else if (battlevel == 50)
M5.Lcd.fillRect(253, 8, battlevel / 2, 15, YELLOW); // バッテリー 50%
else if (battlevel == 75)
M5.Lcd.fillRect(253, 8, battlevel / 2, 15, BLUE); // バッテリー 75%
else if (battlevel == 100)
M5.Lcd.fillRect(253, 8, battlevel / 2, 15, GREEN); // バッテリー 100%
lastbattery = battlevel;
}
lastupdateMillis = currentMillis;
}
}
delay(10000);
}

// ボタン A,B,C 選択アクション
void selectButton() {
M5.update();
// Aボタン 0.15秒間オンで送信開始
if (M5.BtnA.pressedFor(100)) {
M5.Lcd.setCursor(0, 80);
M5.Lcd.print(" X'mit ");
ICOMciv(0x1C, 0x00, 0x01, 3); // 送信コマンド
M5.Speaker.beep();
delay(70);
M5.Speaker.mute();
}

// Bボタン 1秒間オンで無線機電源断
if (M5.BtnB.pressedFor(1000)) {
M5.Lcd.setCursor(0, 80);
M5.Lcd.print(" P-Off ");
ICOMciv(0x18, 0x00, 0x00, 2); // Powerオフコマンド、3バイト目はダミー
M5.Speaker.beep();
delay(1000);
M5.Speaker.mute();
delay(2000); // 表示後1秒待機
// M5.Power.powerOFF(); // M5のSoftPower OFF
M5.Lcd.setCursor(0, 80);
M5.Lcd.print(" ");
}

// Cボタン オンで送信取り消し
if (M5.BtnC.pressedFor(0)) {
M5.Lcd.setCursor(0, 80);
M5.Lcd.print(" Recive");
ICOMciv(0x1C, 0x00, 0x00, 3); // 送信停止コマンド
M5.Speaker.beep();
delay(70);
M5.Speaker.mute();
delay(800); // 表示後0.5秒待って表示消去、この間ボタン操作不可
M5.Lcd.setCursor(0, 80);
M5.Lcd.print(" ");
}
}

// ボタンのA,B,C機能表示 ;
void Lcdinit() {
M5.Lcd.setTextFont(2); // Fontサイズ設定
M5.Lcd.setTextSize(2);

M5.Lcd.fillRect(30, 200, 70, 40, RED); // Aボタン送信
M5.Lcd.setCursor(37, 203);
M5.Lcd.print("X'mit");

M5.Lcd.fillRect(125, 200, 70, 40, GREEN); // Bボタン電源断表示
M5.Lcd.setCursor(132, 203);
M5.Lcd.print("Poff");

M5.Lcd.fillRect(220, 200, 70, 40, PINK); // Cボタン受信表示
M5.Lcd.setCursor(232, 203);
M5.Lcd.print("Rcv");

M5.Lcd.setCursor(0, 80);
M5.Lcd.setTextFont(4); // 24ピクセルFontに変更
M5.Lcd.setTextSize(3);
}

// ICOM CI-Vコマンド送信
// c1:コマンド、s1:サブ、d1:データ、 x:変数の数
void ICOMciv(int8_t c1, int8_t s1, int8_t d1, int x)
{
SerialBT.write(0xFE); // FEh プリアンブル
SerialBT.write(0xFE); // FEh プリアンブル
SerialBT.write(id); // CI-Vアドレス、使用RIGに合わせて設定済
SerialBT.write(0x10); // 10h 送信元アドレス(適当)
SerialBT.write(c1); // コマンド
SerialBT.write(s1); // コマンド・サブ
if (x == 3) {
SerialBT.write(d1); // データ バイト送信選択
}
SerialBT.write(0xFD); // ポストアンプル
}

void loop () {
selectButton();
delay(500) ;
}


最新の画像もっと見る

コメントを投稿