ESP8266からMQTT送受信してみる

AdafruitのMQTTライブラリを使ってローカルに立てたブローカー(MQTTサーバー)と通信してみます。

ライブラリのインストール

ArduinoIDEで「ツール→ライブラリを管理」でライブラリマネージャーから「Adafruit MQTT Library」をインストールします。

サンプルプログラムの呼び出し

「スケッチの例→Adafruit MQTT Library→mqtt_esp8266」でサンプルプログラムを呼び出します。

これでESP8266に書き込んで実行すると、リスナー側で

という感じで送信されているのが確認できました。

Arduino IDEのシリアルモニタ側でも

という感じでPublish/Subscribeの確認ができました。

 

ArmbianにMQTT環境をインストール

syslogサーバになっているArmbianにMQTT環境をインストールします。作業内容はこちらの記事を参考にしました。(というか、そのまま)

注)ローカルネットワーク内でのテストのため、ユーザー認証なしの状態で実施しています。

サーバー (Broker) のインストール

サーバー(Broker)の起動

クライアントのインストール

リスナー(Subscribe)を動かす

リスナーの起動はサーバ(Broker)の起動後に行う。下記はその後のPublishをした際の記録を含む。トピックは mqtttest としてみた。

今回はローカルのサーバ(Broker)に対して接続(subscribe)しているが、リモートのサーバ(Broker)に対して接続(subscribe)する場合は「-h server名」とする。

別のPCでもクライアントのみ起動してサーバー(Broker)を指定してリスナーを起動すると、Publishした瞬間に同時に両方のリスナーで表示される。

Publishを動かす

今回はローカルのサーバ(Broker)に対して接続(Publish)しているが、リモートのサーバ(Broker)に対して接続(Publish)する場合は「-h server名」とする。

サーバー(Broker)を自動起動するように設定

ESP8266/ESP32でsyslog出力

ESP32でセンサ情報を収集できるようになったのですが、ESP32は電源を落とすとデータが消えてしまいます。そこでログをsyslogで出力してみます。

ぐぐると、GitHubにちょうど Arduino用の Syslog ライブラリがありましたので、これを試してみます。

GitHubからZIPでダウンロードしてきて、ダウンロードしたファイル(Syslog-master.zip)を展開、展開したディレクトリの名前を Syslog-master から Syslog に変更して、 ~/Arduino/librariesの下に移動します。

その後、Arduino IDEを起動すると、「ファイル→スケッチ例」の中に「Syslog」が出てきますので、この中の AdvancedLoggingESP8266 を開いて、冒頭の部分を修正します。

修正して実行すると、syslogサーバ側に以下のようなログが記録されました。

ESP32でマイクロ波近接センサをロギング

ESP32はしばらく放置している間にすごく使いやすくなっていたので、調子に乗って、以前買ったESP32 DevKitCOLEDモジュールをつけて、ドップラーセンサーモジュールで壁越しに動体検知するのにチャレンジしてみました。

開発はArduino環境で行いました。無線LANの初期化やNTPでの時刻同期、OLEDの表示に関する部分、Webサーバーに関する部分はT-Cameraのソースをベースに不要な部分を削除して用意しました。

今回使用したセンサはUARTで通信します。ESP32にはUARTが3つあり、1つはPC(Arduino IDE)との通信用となっていますので、残り2つが利用可能です。今回はUART1の送信を16ピン、受信を17ピンに割り当てて使用しました。

で初期化しました。

受け取ったセンサ情報は接近時、離別時、停止時の3つのパターンがありますが、それぞれ毎分0秒を境界とした1分毎、毎時0分を境界とした1時間毎に発生数を計数して Chart.js を用いてグラフ化してみました。

 

TTGO T-Cameraの画像をngrok経由で取得

NAT配下のWebサーバ等をインターネットからアクセスできるようにトンネリングをするngrokというサービスがあります。

これを使って、3Dプリンタの監視画像をインターネットから取得できないか試してみました。

テスト環境は以下のとおりです。

まず、ngrok公式サイトからサインアップをします。サインアップすると、「Setup & Installation」という画面に移行しますので、これに沿って操作していきます。

まず、ngrokのダウンロードですが、Linux(ARM)のURLをコピーして、wgetでzipファイルを取得します。(下記はURLを書き換えてありますので、必ずURLをコピーしてください)

ダウンロードしたら、②、③に沿って展開とトークンの取得を行います。トークンの取得は③のところのコマンドラインをコピー&ペーストして実行するだけです。

トークンを取得したら、 ~/.ngrok2/ngrok.yml にある設定ファイルを作成します。

1行目の内容はトークン取得で作成されている内容です。2行目以降が追加した内容になります。

作成したら、

で起動します。(終了すると tunnel も消滅するので screen と併用するとよいかと思います)

という感じで状態が表示されます。この状態でインターネット側から https://b3d16323.ngrok.io にアクセスするとBASIC認証が求められ、設定したユーザー名とパスワードを入力すると、TTGO T-Cameraへアクセスすることができました。アクセスすると上記の状態の下にHTTPリクエストの状態がリストで表示されます。なお、b3d16323の部分は起動する度にランダムに変わります。有料プランにするとこの部分を固定にすることができるようです。

実際にGet Stillをクリックすると、

という感じで実際に画像を取得できました。なお、ストリーミングについては異なるポート(81/TCP)でのアクセスが必要なのですが、ngrokのコンフィグファイルでは複数のポートの設定も記述できるものの、ポートごとに異なるURLが割り付けられます。このため、うまくいきませんでした。有料プランにするとURLを指定できるので、うまく行く方法があるのかもしれません。

TTGO T-Cameraを3Dプリンタ監視用に

TTGO T-Cameraを3Dプリンタの監視用に使ってみました。

まず支柱を設計して、3Dプリンタで出力しました。

Ender-3の左手前に共締めして取り付けるとこんな感じです。

3D Benchyを出力してみました。

PCからブラウザ上でストリーム表示させるとこんな感じです。

VGAサイズくらいであればスムーズに表示されます。スマホからでも表示可能。

暗いのでノイジーですが、UXGAでのキャプチャもこの通り。魚眼レンズなので近くても全景が入ります。画像は歪んでしまいますが、ちょっと状況を確認するには十分な出来になりました。

TTGO T-Camera 出力画像を180度回転

現在のT-Cameraのソースだと、USBコネクタが上に来る向きで天地が合う形になっているので、結構扱いにくい(一方で、USBケーブルを挿した状態で置きやすいというメリットもある)。

で、カメラモジュールで反転させる機能があるのではないか、と探してみたところ、やはりあった。

これを使えないか探しまくった結果、カメラを初期化している

の後に、

と入れれば画像が回転できることがわかった。よって、先に入れたOLEDの表示を回転させる

は削除できる。
でも、USBコネクタが上のほうが便利な場合もあるので、

とすることで反転するようにソース修正した。

TTGO T-Camera LiPO電池を接続してみました

リチウムイオン電池のコントローラ(IP5306)が搭載されているTTGO T-Cameraですが、回路図をみるとD4というダイオードが入っていて電池からIP5306に向かってしか電流が流れないので、一見充電できないように見えます。

しかし、よくみるとこれ、「2A FUSE」と書いてあります。つまり、フットプリント流用のためにダイオードのシンボルになっているようです。さらに、その右下を見ると分圧回路があり、電池の電圧がESP32で確認できるようです。そこで、電池の電圧をモニターしつつ、LiPOをつないでみることにしました。つないだのは手持ちのトイドローン用の500mAhのものをコネクタを付け替えたものです。

ソフトウェアは表示画面に3ページ目を追加してモニターするようにしてみました。

単純にIO35の電圧を読んだだけでは高インピーダンスで外部/内部のノイズの影響を受けているのか、スッチングノイズを拾っているのかわかりませんが、かなりブレがあります。本来ならまずはR43にコンデンサを抱かせたいところですが、面倒なので50ms周期で32回の平均を取っています。(1005のコンデンサなんて手持ちにないし・・・。そもそもESP32のADCの入力インピーダンスってどのくらいなんでしょうね。100kΩでは大きすぎるのかも?)

一方、充電電流を見てみると、PCにつないだ場合には入力側で0.4Aくらいでしたので、電池への充電電流もせいぜい0.5Aくらいで1C程度ということで問題ない範囲(本当はもう少し減らしたい)かと思ったのですが、Ankerのモバイルバッテリーにつないだところ、0.8Aくらい流れていて2C近い電流が流れてしまうようです。IP5306の中国語のデータシート(こちらの通販サイト?にあるもの)を見ると、最大1Aで充電するようですので、ちょっとまずいかもしれません。データシートをみても充電電流を調整する方法はなさそうです。

バッテリーで動作するWiFi IPカメラというのも悪くないですし、どうしたもんでしょうね。

TTGO T-Camera ファームウェア改造

TTGO T-Cameraのファームウェアを改造してみました。

1.ファームウェア開発環境の準備

ファームウェアはArduino環境で開発しますので、まずはLinuxMint19に開発環境を導入します。

まずは、pyserialをインストールしておきます。

自分のユーザーアカウントを dialout グループに追加した後、一旦ログアウトしてログインし直します。

Aruduino公式サイトから arduino-1.8.9-linux64.tar.xz をダウンロードしてきて展開します。生成された arduino-1.8.9 というディレクトリをホームディレクトリ直下に移動した後、
シェルを開いて、

で Arduino をインストール完了です。インストールが完了したら、 「Menu → プログラミング → Arduino」でArduino IDEを起動します。次にArduino IDEの「ファイル→環境設定」で「追加のボードマネージャのURL」に

を設定します。引き続き、「ツール→ボード→ボードマネージャ」で「esp32 by Espressif Systems」を探してインストールします。インストールが完了したら、「ツール→ボード→ESP32 Wrover module」を選択すれば、Arduino自体の準備は完了です。

2.ソースコードの導入

ソースコードは https://github.com/lewisxhe/esp32-camera-series からZIPでダウンロードしてきます。ダウンロードした esp32-camera-series-master.zip を展開し、展開したディレクトリ名をesp32-camera-seriesに変更して、~/Arduino の下に移動します。

Arduino IDEの「ファイル→開く」で ~/Arduino/esp32-camera-series/esp32-camera-series.ino を開いておきます。

3.ライブラリの準備

Arduino OneButton Library を https://github.com/mathertel/OneButton からZIPでダウンロードしてきて、OneButton-master.zip を展開します。展開したら、ディレクトリ名をOneButtonに変更して、~/Arduino/liraries の下に移動します。

BME280のライブラリについては TTGO T-Cameraでは正常な値を表示しない(そのため、途中から削除されている)のでソースコード中の

の行はコメントアウトしておきます。

esp8266-oled-ssd1306 Library を https://github.com/ThingPulse/esp8266-oled-ssd1306 からZIPでダウンロードしてきて、esp8266-oled-ssd1306-master.zipを展開します。ディレクトリ名をesp8266-oled-ssd1306に変更して、~/Arduino/liraries の下に移動します。

ここまででビルドと書き込みはできるはずです。Arduino IDEのチェックマーク(検証)を押してコンパイルしてみます。うまく行ったら、右矢印マークを押して書き込みもテストしておきます。

4.SoftAPモードからSTAモードへ変更

をコメントアウトして、SoftAPモードを禁止して、

のところに接続先のSSIDとパスワードを設定します。

5.ESP32のIPアドレスを固定IPに変更する

SSID/PASSWORDの設定の箇所の後に以下の記述を追加

WiFi.begin()の直前に以下の記述を追加

6.mDNS対応

ローカルネット内からはIPアドレスではなくホスト名でアクセスできると便利なので、mDNS対応させておきます。

先頭の

の後に

を追加します。続いて、SSID/PASSWORDの設定の箇所の後に以下の記述を追加します。

引き続き、setup()の最後の箇所の

に変更します。更に、void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) の中の

に書き換えます。(いくつかの行がコメントアウトになっているのは、表示にはIPアドレスもほしいためです。すべてURLでいい場合にはコメントを外します)
さらに、void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)の中の

に書き換えます。

7.カメラの向きとOLEDの表示が上下逆なのを修正

の後あたりに

を追加します。

これでボードに書き込むと同じサブネットのPCからは http://esp32.local で、異なるPCからは http://IPアドレス でアクセスできます。どちらもOLEDディスプレイにも表示されます。

Google Cloud Print Connectorを設定

これまでAndoidから印刷するのに、わざわざGoogle DriveかGmail経由でLinux Mint側にファイルを持ってきて、それから印刷していたのですが、これが面倒なので、Google Cloud Printが使えるように設定してみます。
プリンタはBrother HL-2240DでLinuxMint19のPCにUSBで接続しています。

1.インストールと設定ファイル生成

まずはSynapticパッケージマネージャで「google-cloud-print-connector」をインストールして、引き続き設定ファイルを生成します。

ローカル印刷は引き続き使うので「Yes」を入力

クラウドプリントを使うので「Yes」を入力

ここでGoogle Chromeを起動して、https://www.google.com/device にアクセスするとGoogleアカウントの認証を求められるので認証ログイン。さらに、コードの入力に移るので、上記のコード(XXXX-XXXX)を入力。入力すると、コンソール画面が進んで、使わせたいユーザーの

Google Cloud Printを使いたいユーザーのメールアドレスをカンマ区切りで入力

入力すると設定ファイルが生成されたことが表示されます。

2.動作テスト

試しに動かしてみます。

Android側では「クラウド プリント」をインストールします。

インストールされた状態でアプリケーションのメニューで「印刷」を選択して、「プリンタの選択」でLinux側でCUPSで管理されているプリンタを選択して、プリンタのアイコンをタップすると印刷できました。

3.自動起動の設定

cloud-print-connector というユーザー/グループを作成します。ホームディレクトリは不要、ログインしないのでログインシェルも不要です。

実行ファイルへのシンボリックリンクを作成します。

設定ファイルを /opt/cloud-print-connector にコピーして適切な権限を付けます。

systemd のサービスファイルをダウンロードしてインストールします。

Google Cloud Print CUPS Connector serviceを許可してスタートします。

停止する場合は、

とします。