FX1200のローテーター側のWiFiサーバーでは、クライアント側からの角度設定UDPデータを受信し角度数値に対して、ローティタ―の角度に準じた電圧をAD変換で0°から360°を角度補正をした角度で数値化し比較します。比較値差分が±0°になるまでローテータ―に対し制御電圧をPWM(Pulse Width Modulation)制御にて回転させ、リアルタイムで角度電圧を常に読み取り比較して同じ角度になるまで制御し続けます。近い角度プラスマイナス10°からPWM効果で平均電力を下げて、ローテータ―の回転を落とし、角度が同じ値になるまで(プラスマイナス0°)ローパワーPWMで動作し続けます。プラス1°またはマイナス1°のときもPWMにて低パワーでローテータ―へ出力し続けています。微妙に動いています。完全にクライアント角度とサーバー側のローテータ―角度の差が0°になるとローテーター制御出力は停止します。概略こんな制御です。また、サーバー側では、角度が一致するまでのローティタ―の動いている角度をUDP通信で返しています。このため、クライアント側では送ったUDPの角度になるまでのサーバーで読み取った角度をクライアントでもリアルタイムで見ることができます。もちろん、サーバー側も、クライアント側も液晶に現在の角度:Now  送った設定角度:SET として表示しています。サーバー側は現在の角度:Now  クライアントからの設定角度:SET そして、コマンドのアスキーと角度コマンドを表示しています。おおよそ、スケッチもまとまりつつありますが、実装を考えないといけません。一番問題と思っているのは、クライアントの各設定角度用のSWです。現状は送る角度の分のタクトSWをブレッドボードでは使っています。これは、ケースに組む場合は数が、0°、90°、180°、270°、360°、それに+20°、-20°のタクトスイッチの7個も必要です。このたくさんあるSWをケースに取り付けなければなりません。ネットサーフィンし、キーマトリクスのSWボードとかありましたが、新たにポートをキーマトリクス分に追加が必要です。現実的にはポート確保とキー検出のスケッチを考える必要もあります。色々と調べているうちにSWやキーボードではなく、赤外線のリモコンのボタンでSWで出力される赤外線データを受信すれば、SWもキーマトリクスと同じように使うことができそうだという案が浮かんできました。早速ネット上のESP32DEVKITCでの赤外線のリモコンからの信号を読み取る受信スケッチサンプルを見てみました。結構簡単そうで、組み込みも1ポートを赤外線センサー入力ポートで使うだけで対応できます。これだ!ということになりました。
senser


各角度SWは実験ではブレッドボード上にありますが、リモコンと併用できるように角度SW処理と直列にスケッチを組めば十分どちらも対応可能です。リモコンはテレビのCHリモコンと同じように角度ボタンを押すだけでUDP通信の角度送出で使えます。
勿論ブレッドボード上のSWもケースに取り付ければSWでもリモコンでもUDP通信で角度コマンドをサーバーへ送ることが可能というわけです。

準備として、赤外線用ライブラリ IRremote.hpp のZIPファイルをダウンロードしてスケッチのメニューからインストールします。 
使ったリモコンはArduinoのKitに入っていた物です。

arduino-remote1

スケッチでは、リモコンのボタンの設定値を知る必要があるので、uint16_t btnval; の btnvalにリモコンボタンを取り込みし、まずはボタンを読み取るスケッチを追加して、全部のボタンがどのようなデータとなっているかをシリアルモニターで読み取りました。使うリモコンの各ボタン値を知ること、これが必要不可欠です。

■ESP32DEVKITCの赤外線受信のサンプル
Arduino 1.8.19のIDEでコンパイルしています。シリアルモニターの使い勝手が良いためです。
**********************************************
#include <IRremote.hpp>  // IRremoteライブラリ
#define IR_RECEIVE_PIN 13 // GPIOピン番号を定義

uint16_t btnval;

void setup() {
          Serial.begin(115200);  // シリアル通信の初期化
  
          //  IrSender.begin(DISABLE_LED_FEEDBACK);  // 赤外線受信の初期化 間違いなので次に修正
          IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);  //START THE RECEIVER
}

void loop() {

// IRData 構造体の確認用 (ここは他のスケッチからの読み取りしました。)
//struct IRData {
//        decode_type_t protocol;
//        uint16_t address;
//        uint16_t command;
//        uint16_t extra;
//        uint8_t numberOfBits;
//        uint8_t flags;
//        uint32_t decodedRawData;
//        irparams_struct *rawDataPtr;
//};

  if (IrReceiver.decode()) {  // 信号を受信したら
    
    
          Serial.print("Received Raw Data: ");
          Serial.println();
          Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);  // 生のデータを16進数で表示
          IrReceiver.printIRResultShort(&Serial);  // 受信したデータの簡潔な概要を表示
          IrReceiver.printIRSendUsage(&Serial);    // 受信した信号を送信するためのコードを表示
   
          IrReceiver.printIRResultRawFormatted(&Serial, true);  // RAWフォーマットで結果を表示
          IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true);  // uint16_t配列として結果を出力

          //***********************************************
          // リモコンのコマンドデータを確認
          btnval = IrReceiver.decodedIRData.command;
          Serial.println(btnval);

          //***********************************************
    
          IrReceiver.resume();  // 次の信号を受信できるようにする
      }
}

**********************************************
■実際の0°(ボタン2を押した時)の赤外線(値:24)受信時のリモコンスケッチ部です。

void loop()
{
            //パケットデータ受信部スケッチ
                  省略...

           //データ送信(角度コマンドのUDP通信送出)SWによるUDPデータ送出 
               省略...

          // 赤外線受信部
          if(IrReceiver.decode())
          {
                Serial.print("Received Raw Data: ");
                btnval = IrReceiver.decodedIRData.command;
                Serial.println(btnval);
                     
                if(btnval == 24)
                {   
                          Serial.println("★   0 degree");         // シリアルモニターでの確認用、なくても良い
                            //-------------------------------------------------------------------------
                          uint8_t nkdata[256] = "M000";             //udp送出用データ  data
                          Serial.printf("%s\n",nkdata);             //シリアルモニター送出
                          uint8_t tftdata[256]="M000" ;             //tft表示用データを別に準備  tftdata
                          //****************************************
                          //clear
                          tft.setTextColor(TFT_WHITE,TFT_BLACK);
                          tft.setTextSize(3); 
                          tft.setCursor(0,44);
                          // tft.print("SET :");   
                          tft.print("          "); 

                          // tft display Logger32command
                          tft.setTextColor(TFT_WHITE,TFT_BLACK);
                          tft.setTextSize(3);

                          tft.setCursor(36,44); //22oct23
                          tft.print("      ");
     
                          //tft.setCursor(0,85);
                          tft.setCursor(72,85); //22oct23
                          tft.print("      ");
                          //tft.setCursor(0,85);
                          tft.setCursor(72,85); //22/oct/23
                          //tft.print("M000");
                          tft.print((char*)tftdata);
                          //****************************************
                          sendUdpPacket(ip,localPort  ,nkdata,strlen((char*)nkdata));       
                          delay(100);
                        //-------------------------------------------------------------------------
                 IrReceiver.resume();//次の信号を受信できるようにする
                 }
       else
                 if(btnval ==94)//45°時のスケッチ
                 {
                     省略...
                 }
       else
                 if(btnval ==90)//90°時のスケッチ
                 {
                     省略...
                 }
                     省略...

      // 135°から315°までは同様なif文スケッチが続きます。

                     省略...
                 IrReceiver.resume();//次の信号を受信できるようにする 
                 }
                 else
                 if(btnval == 28)//360°時のスケッチ
                 {
                     省略...
                 }
                 IrReceiver.resume();//次の信号を受信できるようにする 
    }
}
else 以降のスケッチは、データ値が異なるだけで同じ構成でボタン分のスケッチです。
注意:最後の360°の次がない時のIrReceiver.resume();位置が異なります。省略の後ではない事に注意!

使用したリモコンはCar mpaと型名が書いてあり、mpファイルの再生用で使えるタイプのようです。
今回は、数値の1,2,3,4,5,6,7,8,9を角度に割当てて使用します。東西南北で設定しますが、45° 135°、225°、315°も入れました。ちょうど45°ずつの角度で設置です。これがわかりやすい対応だと思います。

角度に対するリモコンボタンcommand値とボタン名(方向)です。
角度:値:ボタンと方向
    0°:24:ボタン2 (北)
  45°:94:ボタン3 (北東)
  90°:90:ボタン6 (東)
135°:74:ボタン9 (南東)
180°:82:ボタン8 (南)
225°:66:ボタン7 (南西)
270°:  8:ボタン4 (西)
315°:12:ボタン1 (北西)
360°:28:ボタン5 (北)
+20°:25:ボタン+ なし
ー20°:22:ボタンー なし

調べたリモコンのコマンドは下記でした。
今の所使うのは −、+、1,2,3,4,5,6,7,8,9です。
arduino-btn-data

+ボタン、ーボタンはまだスケッチをしていません。中途半端な45°、135°、225°、315°があるので
繰り返し押した時にエッヂ処理が今までと異なるためです。新たな修正が必要と思われます。前の0°、90°、180°、270°、360°のときはブレッドボード上で+20°、ー20°でそれぞれUP,DOWNのSW動作させてました。特に問題は無いようにエッヂの360°以上では360°で止まるようにスケッチしていました。0°以下では0°で同様です。

上記のコマンド値がわかれば、あとは簡単です。Switch文を使ったところ、Switich文内での配列設定はご法度であると叱られましたので、IF文に変更してスケッチし直しました。構造化が簡単かと思いましたが、基本的な点で使用不可でした。元のコマンドデータ設定では配列設定を各所で使用してました。

コマンドでは1°単位で送ることは仕様上問題ありません。PC用のアプリではハムログの読み取りした方位は問題なくサーバーにすべて1°単位の角度値で送出できています。今回はクライアントのSWをリモコンで対応できるようにしたことで、かなり実装が楽になるかと思います。また、今回リモコンで設定する45°単位角度の追加設定で十分角度設定は足りる(実用に供する)と思います。あくまで私のオンエアしているHFの場合です!

今回の角度SWと併用できるリモコンの追加でかなり使い勝手の面で実用性が出てきたように思います。

リモコンを使うと楽に操作ができます。今の家電ではリモコンが必須の時代ですから!このフィチャーを追加して大正解でした。また、これは、ESP32DEVKITCは本当に素晴らしい!一言に尽きます!少し大げさでした。Hi!
また、リモコンの読み取り、送出も可能なので、いろいろな家電の赤外線制御もできるという事にほかなりません!

久々にストレスなくスケッチできて、動作もすんなりと行き、とてもスッキリしました。

デバッグを続けます。

つづく?