私たちはあなたのプライバシーを大切にします
「すべてのクッキーを許可」をクリックすると、サイトのナビゲーションを向上させ、サイト使用状況を分析し、マーケティングおよびパフォーマンスの取り組みを支援するために、クッキーをデバイスに保存することに同意したことになります。この件に関する詳細情報は、ポリシーをご覧ください。プライバシーポリシー
前回の技術記事「Smart Display RS485 Introduction」では、RS485およびModbusプロトコルの基本について紹介しました。本記事では、複数ページを使用した例を通して、Smart Displayの開発でよく使用される以下のテクニックについて詳しく解説します。
このプロジェクトは3つのページで構成されており、Button widgetを使用してページを切り替えることができます。各ページの内容と機能は以下のとおりです。
ページ1:
右側に次のページへ移動するためのボタンがあり、その下に画面の明るさを調整するHorizontal Sliderがあります。プレビュー画面は以下のとおりです。

ページ2:
左側に前のページへ戻るためのボタン、右側に次のページへ移動するためのボタンがあります。また、下部には3つのボタンがあり、それぞれ短・中・長の異なる長さのブザー音を鳴らすことができます。

ページ3:
左側に前のページへ戻るためのボタンがあります。可変抵抗器を使用してアナログ入力をシミュレートし、その結果をGraph widgetに表示します。

本例ではRS485拡張ボードを使用するため、プログラミングを開始する前にLibrary Managerから必要なライブラリをダウンロードしてください。

まず、GUI Builderを使用してページコンテンツを作成します。各ページのText widgetには直接テキストを入力できるため、プログラム側で定義する必要はありません。

各widgetの詳細は以下の表を参照してください。

手元にある機材に応じてSmart Displayのモデルを選択し、異なるwidgetを使用してさまざまな画面を作成できます。ただし、各ページのwidget IDとtypeは、プログラム内の定義と一致させる必要があります。複雑になるのを避けるため、本例ではこの表に記載されているwidget IDとtypeに従ってページコンテンツを作成することをお勧めします。
次に、プログラムについて説明します。
ModbusMasterライブラリをダウンロードしたら、#includeディレクティブを使用して読み込みます。

また、管理しやすいようにSmart Display関連の定数をSmartDisplayModbus.hにまとめています。このファイルもあわせて読み込んでください。
前回の記事では、widget IDからレジスタアドレスへの変換方法を以下のように説明しました。

ただし、この表は1ページあたりのwidget数が最大10個だった当時の仕様に基づいています。現在は、1ページあたり最大64個のwidgetを配置できます。この表は最初の10個のwidgetには引き続き適用できますが、11個目以降のwidgetについては、新しいレジスタ領域を使用する必要があります。そのため、以下のマクロを定義しています。

使いやすくするため、widget IDに基づいて読み書きを行う関数を定義し、その関数内でレジスタアドレスへの変換を行います。

GUI Builderを使用してページコンテンツを設計する際、widget IDを一致させる必要があることを説明しました。そのため、プログラムでは以下のようにwidget IDの定数を定義しています。

これらの定数を定義しておくことで、widgetの種類を把握しやすくなり、実際のページ設計との照合も容易になります。今後GUI設計を変更する場合は、エラーを防ぐため、これらの値もあわせて確認してください。
ファームウェアでは、カウンタによる一定時間の遅延後に0/1信号をブザーへ送信して音を鳴らし、別のカウンタを使用して音の開始と停止のタイミングを制御します。ブザーを鳴らすには、以下の4つのレジスタに書き込む必要があります。

ブザー音の長さを調整するため、SMARTDISPLAY_BUZZER_HIGHをパラメータとして受け取る関数を作成します。関数の例は以下のとおりです。

SMARTDISPLAY_BUZZER_ACTIVEは、前回書き込んだ値と異なる場合にのみブザーが鳴るため、この値を関数内でstatic変数として保持し、呼び出すたびに値を反転させます。
最後に、ページ処理関数内でボタンの状態に応じて、異なる長さのブザー音を鳴らすことができます。

ページを切り替える前に、まずCONFIG_MODEに移行する必要があります。新しいページを設定した後、DISPLAY_MODEに切り替えます。ページを切り替えると、Smart Displayは新しいページ上のすべてのwidgetを再読み込みします。Smart Displayの再読み込みが完了する前に読み書きを行わないよう、通常は一定の待ち時間を設けます。この待ち時間はページの複雑さによって異なります。ページ切り替え後に異常が発生する場合は、待ち時間を長くすることで改善するか確認してください。

ページ切り替え後、新しいページ上のwidgetはデフォルト値になります。そのため、ページ切り替え、widgetの値の記録、およびwidgetの値の復元を行う処理フローを作成します。
まず、ページテーブルを作成し、各ページに処理関数を割り当てられるよう、ページ処理用の関数ポインタを定義します。

次に、ページテーブルを作成します。

定数MAX_WIDGETS_PER_PAGEは、各ページで値を記録するwidgetの数を定義します。今後widgetを追加する場合は、この値もあわせて更新してください。
最後に、loop()関数内でページ切り替えとwidgetの処理を行います。

現在のページ_curPageと次のページ_nextPageが異なる場合は、ページ切り替えフラグnewPageをtrueに設定します。これにより、ページ処理関数で初期化が必要であることを判別できます。以下ではPage0を例に説明します。

initパラメータがtrueの場合は、そのページに切り替わった直後であることを示します。この場合、WIDGET_P0_BUTTON_NEXTの値を0に設定します。新しいページに切り替わった直後のボタンのデフォルト値は0です。ボタンが押され、値が0から1に変化したときだけ特定の処理(本例ではPAGE_1への切り替え)を実行するため、値を0にリセットする必要があります。これは、以前の操作ですでに値が1になっている可能性があるためです。
Slider widgetも、読み込み時の初期値は0です。ただし、以前に明るさを変更している場合があるため、現在の明るさの値_brightnessに復元する必要があります。
それ以外の場合(initがfalseの場合)は、widgetの値が変化したかどうかに応じて処理を行います。最後に、すべてのwidgetの値を保存し、次回の処理時に参照できるようにします。
次のページ_nextPageの設定には、以下の関数を使用します。

ページ処理関数では、初回以外は毎回widgetの内容を確認します。ボタンの値が0から1に変化したことを検出した場合は、以下のように関数を呼び出してページ切り替えを要求します。

Graph widgetは、書き込まれた値をグラフ形式で表示できます。本例では、A0に接続した可変抵抗器を使用してアナログ入力をシミュレートし、データの変化をGraph widgetに表示します。Arduinoのアナログ入力範囲は0~1023ですが、Graph widgetが受け付ける値の範囲は0~100のため、map()関数を使用して値の範囲を変換します。
Graph widgetは、値が変化した場合にのみ画面を更新する仕様です。一定間隔で更新されているように表示するには、値を定期的に確認し、新しい値が前回読み取った値と同じ場合に、その値をわずかに変化させます(1を加算または減算)。これにより、一定間隔でグラフが更新される動的な表示を実現できます。

以上で、本サンプルプログラムの解説は終了です。本記事が、Smart Displayを使用した開発への理解を深める一助となれば幸いです。また、本サンプルは今後のプロジェクト開発における基本フレームワークとしても活用でき、開発時間の短縮に役立ちます。完全なプログラムは、以下のリンクからダウンロードできます:Modbus-MultiPageOperation on GitHub。
RS485 / Modbusについて詳しくない場合は、以下の前回の記事もあわせてご参照ください:Smart Display RS485 Introduction。
「すべてのクッキーを許可」をクリックすると、サイトのナビゲーションを向上させ、サイト使用状況を分析し、マーケティングおよびパフォーマンスの取り組みを支援するために、クッキーをデバイスに保存することに同意したことになります。この件に関する詳細情報は、ポリシーをご覧ください。プライバシーポリシー