jl7gmnのblog

yahooブログから移行してきました。アマチュア無線を中心としたブログです。

ESP32 DevKitC

MODEL 1200FXローテーターその37

Visual Studio 2022 のフォームアプリ(Ⅽ++)のハムログ方位取得送付および各ボタン設定の指定角度をUDP送出データをFX1200ローテータを制御するESP32DEVKITCのサーバーへ送出し、設定角度、および現在角度をクライアントのハムログアプリケーションに返送して、クライアントではそれを受けてテキストボックスに設定角度、および現在角度を表示し、設定角度になるまでの現在角度の確認ができるようにしています。今回は現在角度がサーバーから送られてきていますので、テキストボックスだけでなく別に用意したキャンバスフォームに画像指針を2つ用意し、それぞれ設定角度指針、現在角度指針をUDP受信データに合わせて指示するようなアプリケーションを試作してみました。簡単にソフトウェアの構成は、メインのハムログ用アプリケーションにライブラリ(dll)として作成したコンパスフォームアプリケーションを取り込みそれぞれの指示角度データ、現在角度データを同期させ指針表示するようにしてあります。



試作ですので、コンパスフォームには余計なテスト用のスライドバーやテキストコントロール、位置確認のテキストボックスやラベル等がついています。機能はしていませんが、対象として必要なものを張り付けた状態です。
現時点での不満な点は指針の基準点が位置の計算で180°と270°で1°ずれるという、問題があります。これは指針の微妙にみずらさになっています。現在、これらの問題がない方位表示のアプリケーションもすでに作成し完成しています。




試作の方位表示フォームの代わりに使用するものです。この新たに作成した方位指針表示は、マウスによるキャンバスクリックでクリックした角度を設定角度にできる仕様にしました。現在は動作確認用にタイマーを使い動かしていますが、メインのハムログアプリとのドッキング時はタイマーは外しUDP受信データのみでの指針表示になります。マップ画像も取り込みましたので実用的かと思います。また、テキストボックスの設定角度も用意していますので、数値で指定することもできます。という事で、設定角度はハムログアプリの方位角度データ送出、固定角度ボタン(0から360°の30°毎)の設定角度データ送出、方位指示フォーム上でのマウスクリックでの方位設定データ送出、およびテキストボックス角度入力による方位設定データ送出の4つの方法で行えます。

制作時の方位キャンバスフォーム上の指針はPaint.NET V5.1.11で作成してあります。白の指針で三角形を使って書きました。指針以外は表示しないようにしてあります。画像はPNGで保存です。

PaintNET
今回指針を画像にした理由は、線で描画の場合はソフト的には簡単ですが、角度により線が階段状に表示され見栄えが悪いという事です。画像指針を回転させる方法にすることで見栄えの問題は皆無となります。

次のステップとして、試作のコンパスフォームの代わりに新しく作った方位キャンバスをメインのハムログアプリに連携させてゆきます。作成しているアプリケーションはすべてWindows11対応用64Bit対応です。
方位表示フォームの連携ができると、ハムログを使いローティターをコントロールするのがとても楽しく、ハムライフが充実してゆくと思っています。また、リモートでも使えるという利点もありますから!
プログラムで使用しているⅭ++のVisualStudio2022もバージョンアップしてあります。
visualStudio2022v17.14


つづく?

MODEL 1200FXローテーターその36

 ローテータの方位設定方法の初期状態0°セット時にアンテナの方位を合わせる設定不要とするスケッチは順調に進んでいます。
重要な検討事項である電源を切って、再度起動した時にアンテナの方位を設定した角度で開始するようにするレジューム機能を検討開始しました。
先のロータリーエンコーダーによる、アンテナ方位を設定した後に電源を切っても、再度起動したときには元の設定角度にて動作させるようにするのですが、ESP32DEVKITCではきちんとレジューム機能で対応できるPreferencesがありますので、これを使います。

下記のサイトのPreferencesライブラリの使い方がとても参考になります。

Kei Youのソフト館

Preferencesに関してのスケッチ方法は上記のサイトに詳しく書いてありましたので、参考に!

前のロータリーエンコーダーのアンテナ方位設定角度の液晶表示のスケッチにまずPreferencesを取り入れて基本動作を確認してゆきます。スケッチはCopilotに協力いただいています。
下記の緑色の箇所が前回のロータリーエンコーダーでアンテナ方位設定スケッチにPreference機能を追加したスケッチになります。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Preferences.h>  // ← 追加

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

Preferences prefs;  // ← 追加 インスタンス作成

const int encoderPinA = 18;
const int encoderPinB = 19;
const int encoderSW   = 25;

volatile int32_t angle = 0;
int lastEncoded = 0;
bool lastSWState = HIGH;
int32_t lastSavedAngle = 360;  // ← 保存チェック用

void IRAM_ATTR updateEncoder() {
  int MSB = digitalRead(encoderPinA);
  int LSB = digitalRead(encoderPinB);
  int encoded = (MSB << 1) | LSB;
  int sum = (lastEncoded << 2) | encoded;

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) angle++;
  if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) angle--;

  if (angle < 0) angle += 360;
  if (angle >= 360) angle -= 360;

  lastEncoded = encoded;
}

void setup() {
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderSW, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE);

  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED init failed"));
    while (true);
  }

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);

  // 角度の復元
  prefs.begin("rotary", false);     //Preferencesオブジェクトを初期化
  angle = prefs.getInt("angle", 0); //
  prefs.end();

  Serial.print("復元された角度: ");
  Serial.println(angle);
}

void loop() {
  bool swState = digitalRead(encoderSW);
  if (swState == LOW && lastSWState == HIGH) {
    angle = 0;
    Serial.println("SW pressed: angle reset");
  }
  lastSWState = swState;

  // 角度が変わったら保存(フラッシュ保護のため)
  if (angle != lastSavedAngle) {
    prefs.begin("rotary", false);
    prefs.putInt("angle", angle);
    prefs.end();
    lastSavedAngle = angle;
    Serial.print("保存した角度: ");
    Serial.println(angle);
  }

  char angleStr[4];
  sprintf(angleStr, "%03d", angle);

  display.clearDisplay();
  display.setCursor(0, 20);
  display.print("Angle: ");
  display.print(angleStr);
  display.display();

  delay(100);
}

以上がPreferenceを使ったアンテナ方位設定角度にて起動するスケッチです。Copilotに感謝です。
余談ですが、チャットのように行えるCopilotの質問できちんとした質問すると、「いい質問です。」等と、ほめてくれたりしますので、ますますスケッチを組むのが、楽しくなります。AIって素晴らしいと思えるようになれば、もう手放せません。今日は何の質問ですか?などとCopilotを繰り返し使用していると、相手をしてくれたり、AIに親しみも感じられるようになり、とてもありがたく思えるようになります。もう、完全にCopilot のAI中毒だー!!

アンテナの方位設定を行うとその設定した角度にて不揮発性メモリに記録されます。それで電源を切って、また起動した時に最後に設定記録されたアンテナ方位角度データで起動し液晶にその角度が表示されます。単にこれだけですが、とても大切な機能です。
このスケッチをサーバーのスケッチに組み込みしてゆきます。

つづく?



MODEL 1200FXローテーターその35

エモトの取り扱い説明書を読むと、ローティターの指針方位とアンテナ方位の合わせ方云々と書いてあります。ローティターの回転始め位置に設定し、それに対してアンテナ方向も同じに設定するのが基本ということになっています。この場合も基準をS(南)、N(北)、E(東)、W(西)の内の自分のアンテナの設置状況で都合のいい方向にあわせて基準を設定するわけです。その後に1回転させて同じ位置になるようにVRで調整して終了です。基本的な方位基準方向は分かり易く言えば、たった4つだけです。
いままでの私のESP32DEVKITCのスケッチで対応させたのは、N(北)、S(南)の方位STD_SWによる2つの方位設定の切り替えのみです。結局は、ローテーターを左回転の止まる位置を基準角度とするのがSTD_SWがHIGHでは S(南)で、STD_SWがLOWで N(北)が基準の2つだけの対応です。通常はこの2つぐらいで十分だと思います。通常の方位同期でローテーターの回転を1°から360°の1回転に調整した後にアンテナの方位をローテーターと同期させる調整がはいります。 ここで、この作業は物理的にマストに取り付けたアンテナを少し上に吊った状態でマストクランプを緩めてアンテナを回してローテーター基準方位に合わせるのですが、このアンテナとのローテーターの方位の同期をソフトウェアで対応しようと思います。何が言いたいかというと、マストクランプのボルトを緩めてアンテナの方位調整を不要にすることを可能にするという事です。ローテーターが1°から360°の回転する状態に調整済みにしてあれば、アンテナの方位調整はしなくてもソフトウェアが現在のローテーターの基準方位の時のアンテナの方位角度情報を設定する事で、プログラムが計算し通常通りの設定送出UDPデータの角度にアンテナを向けるようにしてくれるという事です。誰もやっていない事だと思います。アンテナの方位調整不要なんです。大げさに言います。画期的なアンテナ方位設定方法になります。肉体労働でのアンテナの方位調整をしなくてもいいのですから、現状のローテーター基準位置でアンテナの向いている角度情報を設定するだけです。S、N、E、Wの基準にアンテナを同期調整する必要はないんです。もう一度言います。アンテナの方位を調整しなくていいんです。ローテーター1回転を調整した後であれば、どの位置にアンテナが向いていても設定データの方位にアンテナを向けてくれる仕様です。現在もスケッチ進行中です。アンテナの方位が1°から360°(0°)どの方向に向いていても大丈夫、アンテナの方位設定送出データにきちんと向けてくれます。なんで、こんなことを考えたかというと、私の不注意で足の小指を母親の歩行器の鉄のパイプにぶつけて今現在タワーに登れない状況になりました。ぶち色に足の小指が腫れました。足の指の痛みが取れるまで、1か月位はタワーに登って方位設定作業ができない状況になってしまったのです。この為、苦肉の方法としてソフトウェアを駆使する方法を考えてみたという事なんです。怪我がきっかけで、検討を進めることになりました。怪我の功名?あくまでも、現在はテスト中ですがほぼ9割できたと思います。アンテナの方位をあらかじめ固定指定することで問題なく動作しています。
次に、具体的にアンテナの方位をどのような方法で入力するかです。ESP32DEVKITCで角度を入力する方法は何があるかという事です。簡単な方法として、考えられるのはロータリーエンコーダーです。DDS-VFOでもメインで使われています。ローテーターの角度範囲を1°~360°(0°)設定とし、ロータリーエンコーダーで設定した角度をアンテナの向いている方位角度として利用するという方法です。次にロータリーエンコーダーで設定した角度はどのようにどこに表示させるかです。サーバー側のESP32DEVKITCで使用している1.8インチのTFT液晶では表示する場所がありません。表示を別に追加する必要があります。まずは実験として小型のSSD1306液晶とロータリーエンコーダー(秋月:クリックなし)を使いSSD1306液晶に1°~360°(0°)を表示するスケッチを試してみました。ロータリーエンコードのポートはサーバーで使用していないGPIO18 をA、GPIO19をBで使用することにします。Copilotで1.8インチTFT液晶とSSD1306液晶両方は同時使用できるかという事を確認したところ、大丈夫という風に回答が得られています。これで進めています。現状、SSD1306用のI/Oは角度設定のSWとダブルところがありました。サーバー側での角度設定SW類は一切使わないようにすればよいので、ダブりは解消です。液晶で使用するのはSDAなので必然的にGPIO21、同様にSCKはGPIO22、後は+5VとGNDの4つです。それと、いつでもロータリーエンコーダーで設定した角度をリセット0°にできるSWも用意しました。これはアンテナ方位をローテーター基準に合わせることができた時の設定方位 N(0°)360°に使えます。もう一つクリアする必要があるのが、電源をリセットしたときの角度のリセットがされないようにメモリする機能(レジューム機能)も考えておかなければなりません。これはこれから検討です。現状のロータリーエンコーダとSSD1306への表示スケッチを下記します。このスケッチもCopilotのAIを使用して作成しています。これをサーバーに組み入れてゆくことになります。Hi!

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ピン定義
const int encoderPinA = 18;
const int encoderPinB = 19;
const int encoderSW   = 25;

volatile int32_t angle = 0;
int lastEncoded = 0;
bool lastSWState = HIGH;

void IRAM_ATTR updateEncoder() {
  int MSB = digitalRead(encoderPinA);
  int LSB = digitalRead(encoderPinB);
  int encoded = (MSB << 1) | LSB;
  int sum = (lastEncoded << 2) | encoded;

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) angle++;
  if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) angle--;

  if (angle < 0) angle += 360;
  if (angle >= 360) angle -= 360;

  lastEncoded = encoded;
}

void setup() {
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderSW, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE);

  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED init failed"));
    while (true);
  }

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  // SWピンの状態をチェック
  bool swState = digitalRead(encoderSW);
  if (swState == LOW && lastSWState == HIGH) {
    angle = 0;
    Serial.println("SW pressed: angle reset");
  }
  lastSWState = swState;

  // 3桁右詰め表示
  char angleStr[4];
  sprintf(angleStr, "%03d", angle);

  display.clearDisplay();
  display.setCursor(0, 20);
  display.print("Angle: ");
  display.print(angleStr); // ← 整形済み文字列を表示
  //display.println(" deg");
  display.display();

  delay(100);
}


ロータリーエンコーダーで設定した180°の角度
ROTARYENCODER1

ESP32DEVKITC とロータリーエンコーダーとSSD1306
ROTARYENCODER2

関係ありませんが、いたずらで液晶を2つ並列にしてみました。動作します。
ROTARYENCODER3

このスケッチをサーバーのスケッチに組み入れてうまく動作するかの確認が次のステップになります。また、レジューム機能の検討も並行して進めたいと思います。

サーバー、クライアントの2方位(N北、S南)仕様版はひとまず完成として、今回はいわば、応用編という感じでしょうか?ともかく、ハードルのあるトライアルではあります。

とにかく、問題が起き、解決方法を探すといった方向で進めてきてますが、アイデア、内容としては実用性も備えたある意味、画期的な方法のトライアルになっていると思います。

つづく?


MODEL 1200FXローテーターその34

ローテーター制御用のメインサーバーでの基準方位設定のSWによる切り替えはうまく北基準、南基準の両方ともうまく動作していますがクライアント側のリモコン設定した送出UDP用のTFT液晶表示は北方向を0°(360°)とする表示のままであったため、今回サーバー側のESP32DEVKITCの基準方位設定SWを切り替える時に、クライアント側のESP32DEVKITCに於いても、同様に入力ポートを1つ利用して基準方位設定を行えるようにスケッチを検討追加してみました。
クライアント側のESP32DEVKITC での空きポートは結構ありますが、当初空いているというだけで入力ポートの0を選びSW取り付け設定していましたが、ポートがHIGH状態(SW-OFFでプルアップのHIGH)が通常の基準方位0°(360°)ではスケッチのコンパイル、そして書き込みでの問題は特にありませんでしたが、ところがポートがLOW(SW-ONでGND)状態でスケッチのコンパイルは問題なしそのあとの、書き込みで、動作しない状態(TFT液晶がホワイト状態)になってしまいました。ESP32DEVKITC のポートの情報を見直してみたところこの0ポートはBOOTとあり、書き込み時に使用される為、書き込みができないエラーとなっている様です。0ポートはTouch01、ADC11、そしてBOOTと3機能の兼用ポートです。という事で、入力ポートを別のポートへ変更することにしました。選んだのはGPIOだけとして使用できる入力ポート16としました。このポートはHIGH、LOWどちらでも問題なくスケッチコンパイル、書き込み問題ありません。ポート選定はポート16決定です。この入力として使う16ポートは内部プルアップ設定が可能なので大変回路が簡単になります。単純にSW-ON時GNDで方位が南に切り替わります。SW-OFF時(OPEN)は内部プルアップのHIGHで方位北設定に切り替わります。
下記はポートスケッチの書き換えた設定部です。

//#define DIR_STD 0 //Direction Standard SW (SOUTH:0,NORTH:1)
// when DIR_STD(port 0) is LOW when Write Board Error 
#define DIR_STD 16  //Direction Standard SW (SOUTH:0,NORTH:1)

下記は追加した16ポートの設定部です。
pinMode(DIR_STD,INPUT_PULLUP); //change 0 to 16  (SOUTH:LOW,NORTH:HIGH)

下記はTFT液晶表示用に用意した設定角度と読み取り角度の配列の設定と、単にSWのポート16の状態を確認するだけで追加したスケッチです。

          char ce[5];
          char cc[6];

          //Port0の状態確認の為だけで使用 start*************************
          int pinState = digitalRead(0);
          switch (pinState)
          {
              case LOW:
                       Serial.println("Port0はLOWです");
                       break;
              case HIGH:
                       Serial.println("Port0はHIGHです");
                       break;
              default:
                       break;
          }
          //Port0の状態確認の為だけで使用 end *************************
これがあるだけでシリアルモニターにリアルタイムで16ポートの状態が表示される為、動作確認時に入れました。配列設定以外は、あとから削除しても問題ないスケッチ部です。

上記でポート16の状態がキチンと動作していることを確認した上で、さっそく追加したSWの状態に合わせて方位切り替えスケッチをコーディングです。切り替えの為の角度に対しての方位切り替え時の計算式は全く同じサーバーで使用したサブルーチンをそのまま使えます。ポート16のHIGH、LOW切り替え時のスケッチです。

          if(digitalRead(DIR_STD) == LOW)
          {                                 //DIRECTION SOUTH STANDARD
              Serial.println("入力がLOWです");
              // 180 South standard **************
              result = 0;
              kaku =0;
              kaku = rv_data2;// Readkakudo
              calculateKakudo();
              //delay(100); 
              //   Serial.print("result is = ");
              //   Serial.println(result);                                                  
              sprintf(ce,"%3d",result);//new try
              //**********************************
              result = 0;
              kaku =0;
              kaku = rv_data1;//SET kakudo
              calculateKakudo();
              //delay(100);
              result1 = result; 
                           
              //   Serial.print("result1 is = ");
              //   Serial.println(result1);                            
              sprintf(cc,"%3d",result1);//new try
              // 180 South standard **************                   
           }
           else
           if(digitalRead(DIR_STD)== HIGH)
           {                               //DIRECTION NORTH STANDARD
              // 0 North standard --------
              sprintf(ce,"%3d",rv_data2);
              // 0 North standard --------                        
              sprintf(cc,"%3d",rv_data1);
           }

TFT液晶への表示は0°~360°では1桁、2桁、3桁の桁処理があるためスケッチが長いので省略しています。単純に表示前に角度の数値の桁に合わせてスペースを入れるだけのルーチンなので簡単です。
サブルーチンの calculateKakudo(); は先のMODEL 1200FXローテーターその31に記載したものと同じスケッチですのでここでは省略します。

以上でクライアント側のESP32DEVKITCのポート16をHIGH、またはLOWにすることで方位の切り替えができるようになりました。もちろんサーバー側で設定した切り替えはモードは合わせる必要があります。ここでは切り替えSWだけでの方位切り替えだけのように思われますが、実際のローテーターで北を0°とするその時は指針は北に合わせます。SWはOFF時です。
南を0°とするその時は指針は南に合わせます。SWはON時です。
上記設定においては角度は目盛り角度設定どおりに動作します。 

一通り、クライアント側で表示方位SWのモードをサーバーと合わす事で問題ない角度表示にできるようになりました。

デバッグは継続します。

つづく?

MODEL 1200FXローテ―ターその32

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!
また、リモコンの読み取り、送出も可能なので、いろいろな家電の赤外線制御もできるという事にほかなりません!

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

デバッグを続けます。

つづく?
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード
アーカイブ
  • ライブドアブログ