Arduino Uno Qの利用 ⑪ 入門編 従来のArduinoと互換性を保ち新しい機能を追加されたArduino Uno Q<Arduino Uno Q単独でApp Labを動かす>

 今回はマイコン・ボードArduino Uno Q単独でApp Labを利用して、前回テストしたCopy of UNO Q Pin Toggleを動かします。


Arduino Uno Q とドッキングステーションをつなぐ

 第3回では、ドッキングステーションにエレコム製のDST-S060BPSVを使用しましたが、今回はHDMI出力のON/OFFスイッチがないだけで同等な機能を持つナカバヤシのUDS-2K01Pを使用します。安価で2000円台半ばで購入しました。

 このドッキングステーションをArduino Uno QのUSB type-Cのコネクタに接続します。HDMIケーブル用の端子はモニタと接続し、USB2.0の端子にはマウスとキーボードを接続します。

ログインするとApp Labが起動する 

 電源を投入するとしばらくするとログイン画面が表示され、ログインIDがデフォルトの「arduino」でパスワードの入力が要求されます。第3回目でArduino Uno Qに設定したログインID arduinoのパスワードを入力し「Log in」のボタンをクリックすると、しばらくしてArduino App Labが開きます。

 次に示す画面は、マシンが立ち上がって、GUIが表示されたところです。Arduino App Lab が動いています。デフォルトで起動時に立ち上がるアプリがApp Labとなっているようです。それらの仕組みは、後の回で検討する予定とします。

サンプルUNO Q Pin Toggleの動作確認

 今回は、前回と同様にサンプルのUNO Q Pin Toggleを動かして仕組みを確認します。

 Arduino Uno Qには、次に示すようなD0~D21の汎用のディジタル・ポート、そのうちD14~D19はA0~A5のアナログ6ポートとなっています。
 このほかに、オンボードの二つのカラーLEDの制御を行うためのRGB×2の6ポートのディジタル・ポートが用意されています。


 Webブラウザに表示されているトグル・スイッチをマウスでクリックすると、Uno QのポートがON/OFF(HIGH/LOW)と変化します。

 README.mdで表示される全体構成で、この仕組みを説明します。

 具体的なボードのポートの制御はスケッチが対応します。Webブラウザの表示、Webブラウザからの指示に従いArduinoのポートの制御データをスケッチに渡す処理は、ArduinoのPython側で行います。

 Webブラウザとのやり取りはBrickのWebUIが担っています。

 次の図は、それらの関係を図示したものです。 


スケッチの行っていること

 スケッチでは、ピン名とピン番号の組み合わせの構造体の配列に、制御に必要となるArduino Uno Qのピン番号をセットします。

 関数 set_pin_by_name(String name, bool s)で、ピン名とON/OFFの状態を示すデータを受け取ります。指定されたピンの状態を指示に従い設定します。

ArduinoとPythonの間はRouterBridge

 Arduinoとpythonの間の連携を図るためのライブラリを用意します。


#include <Arduino_RouterBridge.h>

 PinEntry型の配列 kPins[]で、WebブラウザからArduinoの制御対象を示す構造体の定数を定義します。ピン名を示すnameとピン番号を組み合わせた構造体となります。

 Arduinoのプログラムのリファレンスには説明はありませんが、C++のリファレンスには説明があります。


struct PinEntry { const char* name; uint8_t pin; };


 対象のピンを指定するためにPinEntry型の配列を定義しています。


static const PinEntry kPins[] = {
  {"D21", D21}, {"D20", D20}, {"D13", D13}, {"D12", D12},
  {"D11", D11}, {"D10", D10}, {"D9",  D9 }, {"D8",  D8 },
  {"D7",  D7 }, {"D6",  D6 }, {"D5",  D5 }, {"D4",  D4 },
  {"D3",  D3 }, {"D2",  D2 }, {"D1",  D1 }, {"D0",  D0 },
  {"A0",  A0 }, {"A1",  A1 }, {"A2",  A2 }, {"A3",  A3 },
  {"A4",  A4 }, {"A5",  A5 },
  {"LED3_R", LED_BUILTIN}, {"LED3_G", LED_BUILTIN + 1}, {"LED3_B", LED_BUILTIN + 2},  {"LED4_R", LED_BUILTIN + 3}, {"LED4_G", LED_BUILTIN + 4}, {"LED4_B", LED_BUILTIN + 5},
};


ピン名から配列の番号を得る関数

 制御ピンのnameからピン番号を得るための関数findIndex()が用意されています。この関数の中で使われているstrcmp()関数は、二つの文字列を比較し一致を調べる関数です。Arduinoのリファレンスには記述はありませんが、C++などの標準ライブラリに用意されています。

 char*のポインタで示された文字列のピン名 nを渡し、同じ文字列が格納されている配列の番号が戻されます。


static inline int findIndex(const char* n) {


 配列 kPins[]について0から最終の配列まで格納されている名前とnの名称が一致するか調べます。一致したらその配列の戻り値として関数を抜け出します。


  for (size_t i = 0; i < sizeof(kPins)/sizeof(kPins[0]); ++i) {
    if (strcmp(kPins[i].name, n) == 0) return (int)i;
  }
  return -1;
}


 一致するものがなければ -1 が戻されます。


ピン名と設定値によりON/OFFを設定

 pythonから呼び出され、ピン名とON/OFFの状態を引数として設定します。


// Generic setter: name + bool
voidreturn; set_pin_by_name(String name, bool s) {
  int idx = findIndex(name.c_str());  // nameから配列の指標を得る
  if (idx < 0)               // unknown name  // -1 なら戻る
  digitalWrite(kPins[idx].pin, s ? HIGH : LOW);   // sの値でH,Lを決める
}
//この関数はmain.pyの Bridge.call("set_pin_by_name", name,  state_for_hw)から呼び出される。
void setup()
{
  // Arduino Uno Qの全ポートを出力に設定するfor文。 
   for (auto &e : kPins) pinMode(e.pin, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    digitalWrite(LED_BUILTIN + 1, HIGH);
    digitalWrite(LED_BUILTIN + 2, HIGH);
    digitalWrite(LED_BUILTIN + 3, HIGH);
    digitalWrite(LED_BUILTIN + 4, HIGH);
    digitalWrite(LED_BUILTIN + 5, HIGH);
    Bridge.begin();           // Bridgeを起動する
    Bridge.provide("set_pin_by_name", set_pin_by_name);  // pythonからの呼び出しを待つ
}
void loop() {}  // 何もせず待機


 初期化処理(setup())の最初では、各ポートの入出力状態を格納している配列の全ポートを出力に設定しています。このfor文は全配列に対して処理を行うためのもので、通常のfor文よりシンプルに記述できます。

 auto &eは、配列kPinsの全要素を先頭から最終要素まで順番に処理することを指示しています。この命令の一般的な書式は次のようになります。

 例では実行文が1行なので{}は省略され、文の最後に;に付加されています。


  for (auto &e : 配列名) { // 各要素 e に対する処理 }
 
 その後、LEDに接続されているポートは消灯の初期設定値であるHIGHに設定します。
 Bridgeライブラリを開始し、Bridge.provideでpython側から起動する関数の設定を行い、初期設定を終わります。

 loop()関数ではなにも行わず、python側から関数の呼び出しを待ちます。


プログラムが行っていること


Webブラウザの表示

 index.htmlでHTML表示画面の骨格を構成し、style.cssで表示の大きさ、色などの装飾を分担し、app.jsで表示内容の変化、クリックなどの対応などを分担します。


Arduinoの高機能マイコンの処理

 main.pyはプログラムのWebブラウザ、Arduino側のスケッチと連携し、全体の司令塔の役割をはたしています。


従来のArduinoマイコンのスケッチ

 Webブラウザからの情報をもとにArduino Uno Qの各ポートの変更データをmain.pyが設定します。この設定データをsketch.inoが受け取り、ポートの状態を変更します。


Webブラウザ表示のindex.html

 Webブラウザのためのindex.htmlの28行目に、


  <!-- switches are injected here by app.js →


が記述されています。この記述部分にはプログラムが最初に展開されるときに各ポートのスイッチ部分はapp.jsプログラムの makeSwitch()関数で展開されます。

 次に示すD21からLED4_Bまでの28ポートの記述はソースにはありませんが、実行時の展開されたHTML文は次のようになっています。


 

 D7のポートの記述を展開すると、次に示すように記述されています。


 D7のポートを例に内容を確認します。

 label要素のtitle=”D7”は、Webブラウザに表示されたArduino Uno Qのポートにマウスを載せたときに表示されるテキストです。このinput要素はcheckboxタイプで、クラス名はswitch-inputでこのクラスの表示についてはstyle.cssに.switch-inputのタイトルで記述されています。

 switch-iosはトグル・スイッチの土台部分です。::afterはトグルスイッチの可動部分の指定です。style.cssには.switch-iosと .switch-ios::afterについて丸みのついた横長の四角と丸いボタンが左右に移動することが示されています。


Webブラウザのポートがクリックされると

 クリックされたトグル・スイッチのstyle.cssの該当するスイッチの表示が変化します。app.jsで設定されたui.send_message('pin_toggle', ...) を利用して、該当するポート名とスイッチの状態をmain.pyのon_pin_toggle()関数に渡します。

 この関数の中にあるBrige.call関数で、Arduinoのスケッチのポート出力を制御する関数を呼び出し、実際のボードの出力の状態をセットします。


Arduino Uno Qをフルに利用するには

 Arduino Uno R4まではArduinoを利用するにはわかりやすいスケッチを利用するだけで済んでいました。しかしUno Qからは、Webブラウザの利用のためHTML、javascript、CSSなど新しいツールを利用しなければなりません。pythonでのプログラムの作成も必要になります。

 しかし、このように画面回り、実際にハードを動かすプログラム、橋渡しをするプログラムなどを分離しておくと、クラウドのAI、画像認識などの外部の強力な資源を容易に利用することができるようになります。

 この後、サンプルの動作確認からコピーをもとに追加修正を行うことを考えます。


神崎康宏

前へ

Arduino UNO R4 WiFi で外気温を測る ④ 7セグメントLEDに温度、湿度、気圧を表示