M5Stack UI Flow Remote Function を試す

 M5Stack UI Flow に Remote Function というのがあって面白そうだったので試してみました。Remote Function はスマートフォンなどのブラウザから M5Stack を操作するための UI を提供するもので、下記ツイートで紹介されていました。

UI Flow の環境

 UI Flow の環境設定については以前この記事にも書きましたので参照いただければと思います。

blog.akanumahiroaki.com

 今回は UI Flow のバージョンについては 2018/09/29 時点で最新だった v0.7 を使用しています。

使用方法

 Remote Function は UI Flow のメニューの一番下に配置されています。

f:id:akanuma-hiroaki:20180929202857p:plain

 Remote Function のブロックは下記のようなものが用意されています。

 一つ目のブロックは、 M5Stack の LCD に Remote UI の URL の QR コードを表示するためのものです。

 二つ目のブロックは Remote UI にボタンを表示し、押された時の動作を設定するものです。

 三つ目のブロックは Remote UI にラベルを表示するためのものです。

f:id:akanuma-hiroaki:20180929203442p:plain

 今回は Remote UI でボタンが押されたら変数のステータスを切り替えて M5Stack の LCD に表示するものを作ってみます。実際は LED 等を組み合わせて点灯の状態を切り替えたりするイメージです。

 M5Stack 側の表示は下記のようにしてみました。画面下部の STAUTS: の右側の TEXT 部分にステータスが True/False で表示されます。画面中央部には Remote UI アクセス用の QR コードが表示されます。

f:id:akanuma-hiroaki:20180929204547p:plain

 ブロックは下記のように構成しました。 QR コードを表示した後、 Remote UI に Change Status ボタンを配置します。ボタンが押されたら status 変数の中身を切り替えて、 M5Stack の LCD の表示に反映します。最後に Remote UI にも status 変数の中身を表示するラベルを配置します。

f:id:akanuma-hiroaki:20180929204748p:plain

動作確認

 上記のブロックを M5Stack で実行すると、下記のような画面が表示されます。

f:id:akanuma-hiroaki:20180929212426j:plain

 この QR コードをスマートフォン等で読み取って Remote UI にアクセスします。私が試した限りでは上記 QR コードはうまく読み取れなかったのですが、 Remote UI にアクセスするための QR コードは UI Flow の右上のボタンをクリックすることでも表示できます。(下記画像は読み取れないように加工してあります。)

f:id:akanuma-hiroaki:20180929211736p:plain

 QR コードを読み取って Remote UI にアクセスすると下記のような画面が表示されます。ボタンやラベルの色はランダムに決まっているようです。

f:id:akanuma-hiroaki:20180929212605p:plain:w300

 Change Status ボタンをタップすると、 M5Stack の LCD の STATUS 表示が切り替わります。 Remote UI 側はリロードするとその時の status 変数の内容が反映されますが、試した限りではリアルタイムでは反映されませんでした。

まとめ

 全て自前でリモートのUIの環境を用意しようと思うと、サーバを用意したり、スマートフォンアプリもしくはWebのUIを実装するなどかなり手間がかかると思いますが、こんなに簡単にリモートのUIが使えるのはすごいですね。もちろん凝ったUIは作れませんが、シンプルなUIでも十分なケースは多いですし、プロトタイピングやイベント等での一時利用にはすごく便利だと思います。 UI Flow 自体は v0.7 でもまだファイルが保存できなかったり、まだまだ足りてない部分も多いと思いますが、今後のアップデートに期待したいです。

M5Stack で天気情報を表示する(OpenWeatherMap API)

 将来的には M5Stack で Google Calendar に登録してあるスケジュール情報を表示させたいと思っているのですが、認証周りなどが少しハードル高そうなので、まずは認証なしで情報を取ってこられる API から情報を取得して表示する処理を試してみたいと思います。その中でもそれなりに実用性がありそうなものとして、天気情報を取得して画面に表示する処理を作ってみました。

天気情報API

 ひとまず今回は無料で手軽に試せる API を探したところ、 OpenWeatherMap という API がみつかったのでこれを利用してみます。

openweathermap.org

 使い方についてはこちらも参考にさせていただきました。

qiita.com

 ユーザ登録をすると API Key が発行されるのでそれを使用します。アクセスする URL は下記のようになります。

http://api.openweathermap.org/data/2.5/weather?q=Tokyo,jp&appid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

 まずはブラウザでアクセスして確認してみて、情報が取得できていれば OK です。

ファームウェア実装

 MicroPython は基本的には Python3 と互換ですが、 Python の全てのモジュールが移植されているわけではありませんので、 API ドキュメント等を参照して Python との違いを確認しながら実装する必要があります。今回は天気情報の API にリクエストを送信して結果を取得するために、 MicroPython の urequests モジュールを使用しています。また、結果を json オブジェクトとして扱うためには ujson モジュールも必要になりますので、こちらも import しておきます。

 urequests の使い方についてはこちらのサイトを参考にさせていただきました。

blog.boochow.com

 ソース全体は下記のようになります。 self.api_key には実際に取得した API Key を設定します。対象の都道府県としては今回はとりあえず東京、埼玉、名古屋を指定しています。

from m5stack import lcd

import time
import ujson
import urequests

class Weather:
    def __init__(self):
        self.base_url = 'http://api.openweathermap.org/data/2.5/weather?q={},jp&appid={}'
        self.api_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
        self.prefectures = ['Tokyo', 'Saitama', 'Nagoya']

        lcd.setCursor(0, 0)
        lcd.setColor(lcd.WHITE)
        lcd.font(lcd.FONT_DejaVu24)
        self.fw, self.fh = lcd.fontSize()

    def get_weather(self, prefecture):
        response = urequests.get(self.base_url.format(prefecture, self.api_key))
        json = response.json()
        main = json['main']
        self.temp = main['temp']
        self.pressure = main['pressure']
        self.humidity = main['humidity']
        self.temp_min = main['temp_min']
        self.temp_max = main['temp_max']

    def display(self, prefecture):
        lcd.clear()
        lcd.print(prefecture, 0, self.fw * 0)
        lcd.print("temp: {}".format(self.temp), 10, self.fw * 1)
        lcd.print("pressure: {}".format(self.pressure), 10, self.fw * 2)
        lcd.print("humidity: {}".format(self.humidity), 10, self.fw * 3)
        lcd.print("temp_min: {}".format(self.temp_min), 10, self.fw * 4)
        lcd.print("temp_max: {}".format(self.temp_max), 10, self.fw * 5)

weather = Weather()
while True:
    for prefecture in weather.prefectures:
        weather.get_weather(prefecture)
        weather.display(prefecture)
        time.sleep(10)

動作確認

 それでは動作を確認してみます。上記コードを m5cloud から M5Stack にアップロードすると、10秒おきに東京、埼玉、名古屋の天気情報を API から取得して、順番に表示していきます。ちなみに API から取得できる温度は華氏表記になりますので、実際のサービスに使用するときには適宜変換する必要があるかと思います。

f:id:akanuma-hiroaki:20180922235422j:plain

f:id:akanuma-hiroaki:20180922235438j:plain

f:id:akanuma-hiroaki:20180922235455j:plain

まとめ

 認証不要で単純に情報を取得するだけであれば(API Key は必要ですが) API にリクエストを投げて処理を行うのも urequests を使用して簡単に行うことができました。 Google Calendar 等を使うには OAuth 等の認証を行う必要があるのですが、M5Stack でそれを行う方法はまだわかっていないので、調べてみたいと思います。

M5Stack クレードルの温湿度センサー(DHT12)を使ってみる

 以前この記事でも書きましたが、 M5Stack を Maker Faire Tokyo 2018 のスイッチサイエンスさんのブースで購入した時に、特典としてクレードルをいただきました。

blog.akanumahiroaki.com

 このクレードルには温湿度センサー DHT12 が付属していたようなので、今回は MicroPython で DHT12 の値を読み取って表示してみたいと思います。ちなみにこのクレードルは単品でもこちらで販売されているようです。

Buy Products Online from China Wholesalers at Aliexpress.com

ハードウェア

 クレードルの裏面は下記写真のようになっています。右下に埋め込まれている青いものが DHT12 です。

f:id:akanuma-hiroaki:20180915215550j:plain

 クレードルは M5Stack の下部のピンに接続されます。今回は DHT12 との接続にクレードル経由で I2C を使用しますので、 SDA, SCL を使用します。ピン番号は上部のピンと同じになりますので、SDA が 21、 SCL が 22 になります。

f:id:akanuma-hiroaki:20180915215707j:plain

 クレードルと DHT12 は、ちょっと基板での記載部分が見辛いですが、左から SCL, GND, SDA, 3V3 が接続されています。

f:id:akanuma-hiroaki:20180915215744j:plain

ファームウェア

 今回は m5cloud を使用して MicroPython でファームウェアを書いていきます。 DHT12 の使用については、 m5cloud のリポジトリにライブラリが公開されていました。

github.com

 サンプルについても同じリポジトリに公開されていました。 SDA, SCL のピン番号も 21, 22 になっているので、これをこのまま使用できます。

github.com

 これを dht12.py として m5cloud 上にアップロードもしくはコピペで配置します。

f:id:akanuma-hiroaki:20180915221513p:plain

 そして main.py は下記のような内容にしました。温湿度計ということで Hygrothermograph に処理内容をまとめ、コンストラクタで RTC を同期し、 DHT12 を初期化しています。フォントの指定もしておきます。

 measure() メソッドでは DHT12 から温度と湿度を取得し、インスタンス変数に格納しておきます。

 display() メソッドでは LCD に時刻、温度、湿度を表示しています。

from m5stack import lcd
from machine import RTC
import time
import dht12

class Hygrothermograph:
    def __init__(self):
        rtc = RTC()
        rtc.ntp_sync('ntp.nict.jp', tz = 'JST-9')
        for i in range(100):
            if rtc.synced():
                break
            time.sleep_ms(10)
            
        self.sensor = dht12.DHT12()
        
        lcd.font(lcd.FONT_DejaVu24)
        lcd.setColor(lcd.WHITE)
        self.fw, self.fh = lcd.fontSize()
        
    def measure(self):
        self.sensor.measure()
        self.temperature = self.sensor.temperature()
        self.humidity = self.sensor.humidity()

    def display(self):
        lcd.clear()
        lcd.print("Time:", 0, self.fh * 0)
        lcd.print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 10, self.fh * 1)
        lcd.print("Temperature:", 0, self.fh * 2)
        lcd.print("{} deg.".format(self.temperature), 10, self.fh * 3)
        lcd.print("Humidity:", 0, self.fh * 4)
        lcd.print("{} %".format(self.humidity), 10, self.fh * 5)

hygrothermograph = Hygrothermograph()

while True:
    hygrothermograph.measure()
    hygrothermograph.display()
    time.sleep(10)

実行結果

 それでは実行してみます。 m5cloud から upload ボタンをクリックして本体にアップロードして実行します。結果は下記の写真のようになり、時刻、温度、湿度が表示されて10秒毎に更新されていきます。

f:id:akanuma-hiroaki:20180915222531j:plain

 ちなみにクレードルの DHT12 は本体のすぐ下にあって、本体の熱の影響を受けると思いますので、実際の温度を測るには何らか工夫する必要があると思われます。

まとめ

 M5Stack の LCD にすぐに確認したい内容を表示させている場合、クレードルは見やすい角度で本体の位置をキープできるのでとても良い感じですね。とりあえず m5cloud と MicroPython でセンサーの値を読み出すこともできたので、画面表示の方も今後色々と試してみたいと思います。

M5Stack UI Flow を Mac で使う

 以前に下記ツイートを見てから試してみたいと思ってた UI Flow を試してみました。

 UI Flow は Scratch のようにブロックを並べることでプログラミングができ、画面レイアウトもパーツを並べることで行うことができるようになっています。ブロックではなく Micro Python でコーディングをすることもできます。

 チュートリアルとしては下記のページを参考にさせてもらいました。

forum.m5stack.com

ファームウェアのセットアップ

 UI Flow を使うにはそれに対応したファームウェアを使う必要があります。ファームウェアを簡単に選択してフラッシュすることができる M5Burner というツールが用意されていて、 UI Flow 用のファームウェアを選択することもできるのですが、このツールは Windows 用にしか用意されていないので、 Mac ではそのまま使うことができません。ですが、 M5Burner をダウンロードして解凍するとその中にファームウェアのイメージは含まれていて、フラッシュ用のコマンドが書かれた sh ファイルも含まれているので、これを利用することで UI Flow を使うことができます。

 M5Burner は M5Stack のサイトのダウンロードページからダウンロードすることができます。

f:id:akanuma-hiroaki:20180908220258p:plain

 ですが 2018/09/08 に試した時点では、ここからダウンロードできる zip に含まれている UI Flow 用のファームウェアはバージョン 0.4 までで、このバージョンだと UI Flow からプログラムを実行するところでうまく動きませんでした。

 そこで UI Flow の設定画面から取得した zip にはバージョン 0.5 まで含まれており、そちらであれば実行まで動作させることができたのでそちらを使用します。

 まずは M5UI.Flow にアクセスします。すると API Key 設定用のダイアログが表示されますが、まだ API Key はわからないので Skip します。

f:id:akanuma-hiroaki:20180908183250p:plain

 次に画面右上の設定ボタンをクリックして設定ダイアログを開きます。

f:id:akanuma-hiroaki:20180908183306p:plain

 API Key の設定フォームとファームウェア(M5Burner)のダウンロードリンクが表示されますので、ダウンロードリンクをコピーします。

f:id:akanuma-hiroaki:20180908183323p:plain

 ここからはターミナルで実行します。まずは wget で先ほどコピーしたダウンロードリンクから M5Burner をダウンロードします。

$ wget http://flow.m5stack.com/download/M5Burner-flow-only.zip
--2018-09-08 11:36:33--  http://flow.m5stack.com/download/M5Burner-flow-only.zip
Resolving flow.m5stack.com... 52.230.67.99
Connecting to flow.m5stack.com|52.230.67.99|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 12199380 (12M) [application/zip]
Saving to: 'M5Burner-flow-only.zip'

M5Burner-flow-only.zip                                      100%[===========================================================================================================================================>]  11.63M  2.65MB/s   in 4.6s   

2018-09-08 11:36:38 (2.53 MB/s) - 'M5Burner-flow-only.zip' saved [12199380/12199380]

 そして解凍します。

$ unzip M5Burner-flow-only.zip

 すると下記のようファイルが展開されます。

$ ls -l
total 27152
-rw-r--r--  1 akanuma  staff  12199380 Sep  6 20:38 M5Burner-flow-only.zip
-rw-r--r--  1 akanuma  staff     31232 Aug 21 16:42 M5Burner.exe
-rw-r--r--  1 akanuma  staff       189 Jun  9 13:37 M5Burner.exe.config
-rw-r--r--  1 akanuma  staff     34304 Aug 21 16:42 M5Burner.pdb
-rw-r--r--  1 akanuma  staff    662528 Mar 24 17:44 Newtonsoft.Json.dll
-rw-r--r--  1 akanuma  staff    684778 Mar 24 17:44 Newtonsoft.Json.xml
drwxr-xr-x  4 akanuma  staff       128 Sep  6 19:14 firmwares
drwxr-xr-x  3 akanuma  staff        96 Sep  3 15:00 tools
-rw-r--r--  1 akanuma  staff       169 Aug 31 19:51 update.log

 使用するのは firmwares ディレクトリ配下のファイルだけで、 UI Flow 用のファームウェアの最新バージョンのディレクトリへ移動します。

$ cd firmwares/M5Flow/v0.5/
$ ls -l
total 8152
-rw-r--r--  1 akanuma  staff  1351152 Aug 31 19:16 firmware_0x1000.bin
-rw-r--r--  1 akanuma  staff      335 Sep  6 19:11 flash.sh
-rw-r--r--  1 akanuma  staff  2818048 Sep  6 19:05 spiffs_image_0x150000.img

 ここに flash.sh というファイルがあり、この中身はファームウェアをフラッシュするためのコマンドが書かれたものになっています。

$ cat flash.sh 
#!/bin/bash
esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 961200 write_flash -z 0x1000 firmware_0x1000.bin
esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x150000 spiffs_image_0x150000.img

 このファイルに実行権限をつけて実行してしまっても良いのですが、それぞれのコマンドの実行結果を確認したかったので一つずつ実行します。 M5Stack を USB ケーブルで接続していれば下記のようにデバイスファイルが存在します。

$ ls -l /dev/tty.SLAB_USBtoUART 
crw-rw-rw-  1 root  wheel   21,  24 Sep  8 11:03 /dev/tty.SLAB_USBtoUART

 デバイスファイルが確認できたら、まず一つ目のコマンドで bin ファイルを M5Stack に書き込みます。

$ esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 961200 write_flash -z 0x1000 firmware_0x1000.bin
esptool.py v2.5.0
Serial port /dev/tty.SLAB_USBtoUART
Connecting........___
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse
MAC: 80:7d:3a:c4:71:bc
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 961200
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1351152 bytes to 841602...
Wrote 1351152 bytes (841602 compressed) at 0x00001000 in 13.8 seconds (effective 784.0 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

 特にエラーはなく実行できたようです。次にもう一つのコマンドを実行し、 img ファイルを書き込みます。

$ esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x150000 spiffs_image_0x150000.img
esptool.py v2.5.0
Serial port /dev/tty.SLAB_USBtoUART
Connecting........_
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse
MAC: 80:7d:3a:c4:71:bc
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 2818048 bytes to 667546...
Wrote 2818048 bytes (667546 compressed) at 0x00150000 in 18.7 seconds (effective 1205.6 kbit/s)...
Hash of data verified.

Leaving...
Staying in bootloader.

 こちらも問題なく実行できたようです。これでひとまずファームウェアの書き込みは行えたので、これ以降は Windows 環境で実行している場合と同様かと思います。

Wi-Fi 接続設定

 ファームウェアの書き込みが終了したら USB ケーブルを抜くか、 M5Stack 本体横のボタンで M5Stack を再起動すると UI Flow のロゴが表示されます。

f:id:akanuma-hiroaki:20180908183536j:plain

 そしてそのまま何もしなければ、標準でじゃんけんゲームのようなものが書き込まれているで、それが実行されます。

f:id:akanuma-hiroaki:20180908183601j:plain

 Wi-Fi の設定をするためにはもう一度 M5Stack を再起動して、 UI Flow のロゴが表示されている間に右のボタンを長押しします。

f:id:akanuma-hiroaki:20180908200058j:plain

 設定メニューが表示されますので、 set reconnect wifi を選択して真ん中のボタンを押します。

f:id:akanuma-hiroaki:20180908202532j:plain

 すると M5Stack が Wi-Fi AP として動作し、画面上に SSID とアクセス先 IP アドレスが表示されますので、 Mac からその AP に接続し、ブラウザから対象の IP アドレスにアクセスします。

f:id:akanuma-hiroaki:20180908200208j:plain

 下記のように M5Stack が接続する AP を選択する画面が表示されますので、 AP を選択してパスワードを入力し、 Configure をクリックします。

f:id:akanuma-hiroaki:20180908200402p:plain

 接続が成功すると下記のような画面になり、 M5Stack が再起動されます。

f:id:akanuma-hiroaki:20180908200456p:plain

UI Flow から M5Stack への接続

 M5Stack を再起動して UI Flow のロゴが表示されている間に、左のボタンを長押しします。

f:id:akanuma-hiroaki:20180908200624j:plain

 M5Stack から設定済み AP への接続が成功すると、下記のように API Key が表示されます。

f:id:akanuma-hiroaki:20180908201350j:plain

 これを UI Flow の設定画面から設定します。

f:id:akanuma-hiroaki:20180908201500p:plain

 API Key を設定しただけでは接続状態が画面に反映されていないので、画面左の M5Stack のイメージの Offline となっているところをクリックします。

f:id:akanuma-hiroaki:20180908201628p:plain

 接続に成功すると表示が Online に変わります。

f:id:akanuma-hiroaki:20180908201642p:plain

UI Flow でのプログラミング

 ここまででファームウェアの設定や接続等の環境の準備は完了なので、 UI Flow から簡単なプログラムを実装して実行してみます。まずは M5Stack のイメージの上部にある Label をイメージのディスプレイ上にドラッグ&ドロップします。

f:id:akanuma-hiroaki:20180908201711p:plain

 ブロックリストの Component -> Label から、 Label にテキストを表示するためのブロックを選択します。

f:id:akanuma-hiroaki:20180908201734p:plain

 元々配置されている Setup ブロックに選択したブロックを接続し、表示するテキストを変更します。画面にテキストを表示させるだけであればこれだけでOKなので、画面右上の実行ボタンをクリックして、 M5Stack 上で実行します。

f:id:akanuma-hiroaki:20180908201953p:plain

 下記のように実機の画面にテキストが表示されれば成功です。

f:id:akanuma-hiroaki:20180908202026j:plain

 テキストを変更して再度実行ボタンをクリックすれば、すぐに実機に反映されます。

f:id:akanuma-hiroaki:20180908202149p:plain

f:id:akanuma-hiroaki:20180908202239j:plain

 実行ボタンではその場で実行するだけかと思いますので、開発中は実装と動作確認を繰り返すのには良いかと思いますが、起動時に実行されるようにするには画面右上の書き込みボタンで実機に書き込んでおきます。

f:id:akanuma-hiroaki:20180908202401p:plain

まとめ

 M5Stack の Micro Python での Web IDE 環境としては M5Cloud もありますが、 UI Flow の利点としては画面イメージを視覚的に確認しながら作成できる点と、ブロックの配置で処理が実装できるので、学習等の目的としてはとても良さそうに思います。ですが現状ではまだ実装したプログラムを保存しておくことなどはできないようですので、今後 IDE としても充実してくることを期待したいと思います。

アルファ版がリリースされた Arduino CLI を試してみる

 Arduino の CLI がリリースされたということで試してみました。 Arduino からは下記ブログでアナウンスされています。

blog.arduino.cc

 Makefileやスクリプトに組み込むためというのが目的のようで、Arduino IDE の主要な機能をCLIから実行できるようにすることを目指すとのことです。下記の Github リポジトリで公開されています。

github.com

 まだアルファリリースということなので、バグを含んでいたり、予告なく変更される可能性は大きいですが、ひとまずチュートリアルに沿って試してみました。

ダウンロード

 Arduino CLI は単一のバイナリファイルで提供されているので、ダウンロードするだけで実行できるようになります。私の環境は Mac なので、下記URLからバイナリをダウンロードします。

Mac OSX 0.2.1-alpha.preview

 そのまま実行しても良いのですが、今回は /usr/local/bin にシンボリックリンクを作成してパスを通します。

$ ln -s ~/arduino-cli-0.2.1-alpha.preview-osx /usr/local/bin/arduino-cli
$ arduino-cli version
arduino-cli version 0.2.1-alpha.preview

Sketch の作成

 まず下記コマンドで Sketch を作成します。 ino ファイルが1つ作成されます。

$ arduino-cli sketch new SampleSketch
Sketch created in: /Users/akanuma/Documents/Arduino/SampleSketch
$
$ ls -l Documents/Arduino/SampleSketch/
total 8
-rw-r--r--  1 akanuma  staff  35 Sep  1 11:01 SampleSketch.ino
$
$ cat Documents/Arduino/SampleSketch/SampleSketch.ino                                                                                                                                                                                      

void setup() {
}

void loop() {
}

 今回はとりあえず Arduino 互換機の Seeduino でLチカを試してみます。 Seeeduino ではオンボードの LED は13番ピンに接続されています。

wiki.seeedstudio.com

 ino ファイルを下記のように変更します。

void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000);
}

ボードの設定とコンパイル、アップロード

 Arduino CLI を最初に使う際にはプラットフォームのインデックス情報をアップデートする必要があります。下記のコマンドでアップデートします。

$ arduino-cli core update-index
Updating index: package_index.json downloaded   

 次に Seeeduino を Mac にUSBケーブルで接続します。 arduino-cli board list コマンドで、現在接続されているボードの情報を表示します。

$ arduino-cli board list
FQBN    Port                    ID              Board Name
        /dev/cu.usbmodem1421    2886:0004       unknown   

 Board Name が unknown になっているので、正しい core をインストールする必要があるということで、下記のように core を検索します。

$ arduino-cli core search arduino
Searching for platforms matching 'arduino'

ID                      Version Installed       Name                                             
Intel:arc32             2.0.2   No              Intel Curie Boards                               
arduino:avr             1.6.21  Yes             Arduino AVR Boards                               
arduino:nrf52           1.0.2   No              Arduino nRF52 Boards                             
arduino:sam             1.6.11  No              Arduino SAM Boards (32-bits ARM Cortex-M3)       
arduino:samd            1.6.19  No              Arduino SAMD Boards (32-bits ARM Cortex-M0+)     
arduino:samd_beta       1.6.23  No              Arduino SAMD Beta Boards (32-bits ARM Cortex-M0+)
arduino:stm32f4         1.0.1   No              Arduino STM32F4 Boards                           
littleBits:avr          1.0.0   No              littleBits Arduino AVR Modules   

 チュートリアルでは MKR1000 を使っていますが、今回は Arduino Uno の互換機の Seeeduino を使うので、下記のように検索してみます。

$ arduino-cli core search uno
Searching for platforms matching 'uno'

ID              Version Installed       Name              
arduino:avr     1.6.21  Yes             Arduino AVR Boards

 見つかった core をインストールします。

$ arduino-cli core install arduino:avr
Downloading arduino:avr-gcc@4.9.2-atmel3.5.4-arduino2...
arduino:avr-gcc@4.9.2-atmel3.5.4-arduino2 downloaded                                                                                                                                                                                          
Downloading arduino:avrdude@6.3.0-arduino9...
arduino:avrdude@6.3.0-arduino9 downloaded                                                                                                                                                                                                     
Downloading arduino:arduinoOTA@1.1.1...
arduino:arduinoOTA@1.1.1 downloaded                                                                                                                                                                                                           
Downloading arduino:avr@1.6.21...
arduino:avr@1.6.21 downloaded                                                                                                                                                                                                                 
Installing arduino:avr-gcc@4.9.2-atmel3.5.4-arduino2
arduino:avr-gcc@4.9.2-atmel3.5.4-arduino2 installed
Installing arduino:avrdude@6.3.0-arduino9
arduino:avrdude@6.3.0-arduino9 installed
Installing arduino:arduinoOTA@1.1.1
arduino:arduinoOTA@1.1.1 installed
Updating arduino:avr@1.6.21 with arduino:avr@1.6.21...
arduino:avr@1.6.21 installed
$
$ arduino-cli core list
ID                      Installed       Latest  Name                                        
arduino:avr             1.6.21          1.6.21  Arduino AVR Boards
espressif:esp32    

 再度ボード情報を確認してみます。

$ arduino-cli board list
FQBN    Port                    ID              Board Name
        /dev/cu.usbmodem1421    2886:0004       unknown   

 まだ正しく認識されていないようです。試しに下記 core もインストールしてみましたが、結果は変わりませんでした。

$ arduino-cli core search ATmega328
Searching for platforms matching 'atmega328'

ID                      Version Installed       Name                    
atmel-avr-xminis:avr    0.6.0   No              Atmel AVR Xplained-minis

 ボードを正しく認識させることはできませんでしたが、 FQBN(Fully Qualified Board Name) を指定すればコンパイルできそうだったので、下記のようにコンパイルしてみます。

$ arduino-cli compile --fqbn arduino:avr:uno Documents/Arduino/SampleSketch                                                                                                                                                              
Sketch uses 928 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.

 コンパイルが成功したようなので、下記コマンドで Seeeduino にアップロードします。

$ arduino-cli upload -p /dev/tty.usbmodem1421 --fqbn arduino:avr:uno Documents/Arduino/SampleSketch

 ターミナル上には特に結果は表示されませんでしたが、正しくアップロードされたようで、オンボードの LED でLチカが実行されました。

M5Stack の Sketch をビルドしてみる

 最近 M5Stack を触っているので、ついでに M5Stack の Sketch がビルドできるか試してみます。まず M5Stack のライブラリを検索してみます。

$ arduino-cli lib search m5stack
Name: "M5Stack"
  Author:  M5Stack
  Maintainer:  Zibin Zheng <bin@m5stack.com>
  Sentence:  Library for M5Stack Core development kit
  Paragraph:  See more on http://M5Stack.com
  Website:  https://github.com/m5stack/m5stack
  Category:  Device Control
  Architecture:  esp32
  Types:  Contributed
  Versions:  [0.1.1, 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.8, 0.1.9, 0.2.0, 0.2.1, 0.2.2]
Name: "M5Stack-SD-Updater"
  Author:  tobozo@noreply.github.com
  Maintainer:  tobozo@noreply.github.com
  Sentence:  SD Card Loader for M5 Stack
  Paragraph:  Package your apps on an SD card and load them from a menu app, button or MQTT message.
  Website:  https://github.com/tobozo/M5Stack-SD-Updater/
  Category:  Uncategorized
  Architecture:  esp32
  Types:  Contributed
  Versions:  [0.0.2, 0.1.0, 0.2.2, 0.3.0, 0.3.2]
Name: "M5Stack_Avatar"
  Author:  Shinya Ishikawa
  Maintainer:  Shinya Ishikawa<ishikawa.s.1027@gmail.com>
  Sentence:  Yet another avatar module for M5Stack
  Paragraph:  See more on http://M5Stack.com
  Website:  https://platformio.org/lib/show/4529/M5Stack-Avatar
  Category:  Device Control
  Architecture:  esp32
  Types:  Contributed
  Versions:  [0.4.0, 0.5.1, 0.6.0, 0.6.1, 0.6.2, 0.6.3, 0.6.4]

 M5Stack の環境設定は以前の記事で紹介しています。

blog.akanumahiroaki.com

blog.akanumahiroaki.com

 上記記事内で行った設定で、 M5Stack ライブラリと m5stack-avatar-master ライブラリはインストールされています。

$ arduino-cli lib list
Name                            Installed       Location  
Adafruit_Circuit_Playground     1.8.1           sketchbook
Bridge                          1.7.0           sketchbook
Ethernet                        2.0.0           sketchbook
Firmata                         2.5.8           sketchbook
Keyboard                        1.0.2           sketchbook
M5Stack                         0.2.1           sketchbook
SD                              1.2.2           sketchbook
m5stack-avatar-master           0.6.2           sketchbook

 いずれも新しいバージョンがリリースされているので、アップデートします。インストール時と同様のコマンドでアップデートも実行することができます。

$ arduino-cli lib install M5Stack
M5Stack@0.2.2 downloaded                                                                                                                                                                                                                      
Replacing M5Stack@0.2.1 with M5Stack@0.2.2
Installed M5Stack@0.2.2
$
$ arduino-cli lib install M5Stack_Avatar
M5Stack_Avatar@0.6.4 downloaded                                                                                                                                                                                                               
Installed M5Stack_Avatar@0.6.4

 再度インストール済みライブラリを確認してみます。

$ arduino-cli lib list
Name                            Installed       Location  
Adafruit_Circuit_Playground     1.8.1           sketchbook
Bridge                          1.7.0           sketchbook
Ethernet                        2.0.0           sketchbook
Firmata                         2.5.8           sketchbook
Keyboard                        1.0.2           sketchbook
M5Stack                         0.2.2           sketchbook
M5Stack_Avatar                  0.6.4           sketchbook
SD                              1.2.2           sketchbook
m5stack-avatar-master           0.6.2           sketchbook

 以前 M5StackAvatar のライブラリをインストールした際にライブラリマネージャーではなく、ファイルをダウンロードして配置したため、今回インストールしたライブラリとは別の扱いになっているようです。以前のライブラリはアンインストールしておきます。

$ arduino-cli lib uninstall m5stack-avatar-master
Uninstalling m5stack-avatar-master@0.6.2
~  $ 
~  $ arduino-cli lib list
Name                            Installed       Location  
Adafruit_Circuit_Playground     1.8.1           sketchbook
Bridge                          1.7.0           sketchbook
Ethernet                        2.0.0           sketchbook
Firmata                         2.5.8           sketchbook
Keyboard                        1.0.2           sketchbook
M5Stack                         0.2.2           sketchbook
M5Stack_Avatar                  0.6.4           sketchbook
SD                              1.2.2           sketchbook

 新しい Sketch を1つ作成します。

$ arduino-cli sketch new M5StackSampleSketch
Sketch created in: /Users/akanuma/Documents/Arduino/M5StackSampleSketch

 ino ファイルを下記のように変更します。

#include <M5Stack.h>

// the setup routine runs once when M5Stack starts up
void setup(){

  // Initialize the M5Stack object
  M5.begin();

  // LCD display
  M5.Lcd.print("Hello World!!");
}

// the loop routine runs over and over again forever
void loop() {

}

 ボードの認識についてはいくつかの core を試したのですが、 Seeeduino の時と同様に unknown のままでした。

$ arduino-cli board list
FQBN    Port                    ID              Board Name
        /dev/cu.SLAB_USBtoUART  10C4:EA60       unknown   

 FQBN を指定してコンパイルしてみます。

$ arduino-cli compile --fqbn espressif:esp32:m5stack-core-esp32 Documents/Arduino/M5StackSampleSketch
Alternatives for M5Stack.h: [M5Stack@0.2.2]
ResolveLibrary(M5Stack.h)
  -> candidates: [M5Stack@0.2.2]
Alternatives for Wire.h: [Wire@1.0]
ResolveLibrary(Wire.h)
  -> candidates: [Wire@1.0]
Alternatives for SPI.h: [SPI@1.0]
ResolveLibrary(SPI.h)
  -> candidates: [SPI@1.0]
Alternatives for FS.h: [FS@1.0]
ResolveLibrary(FS.h)
  -> candidates: [FS@1.0]
Alternatives for SD.h: [SD@1.0.5 SD@1.2.2]
ResolveLibrary(SD.h)
  -> candidates: [SD@1.0.5 SD@1.2.2]
Multiple libraries were found for "SD.h"
 Used: /Users/akanuma/Documents/Arduino/hardware/espressif/esp32/libraries/SD
 Not used: /Users/akanuma/Documents/Arduino/libraries/SD
Multiple libraries were found for "M5Stack.h"
 Used: /Users/akanuma/Documents/Arduino/libraries/M5Stack
Multiple libraries were found for "Wire.h"
 Used: /Users/akanuma/Documents/Arduino/hardware/espressif/esp32/libraries/Wire
Multiple libraries were found for "SPI.h"
 Used: /Users/akanuma/Documents/Arduino/hardware/espressif/esp32/libraries/SPI
Multiple libraries were found for "FS.h"
 Used: /Users/akanuma/Documents/Arduino/hardware/espressif/esp32/libraries/FS
Error: open /var/folders/l1/5gdn8snd6gj_nfyh5j4nc1sw0000gn/T/arduino-sketch-5C8AE8258C7345D00A6E4E421EB09E5D/core/core.a: no such file or directory
Compilation failed.

 core.a が見つからないということでコンパイルエラーになってしまいました。調べてみたのですが原因はわからず。同じようにエラーになっている方もいるようです。

tech.144lab.com

 まだアルファ版ということで Arduino CLI 側に問題があるのか、私の環境の問題かはわかりませんが、ひとまず Arduino IDE からはコンパイルできるので、今後アップデートがあればまた試してみたいと思います。

まとめ

 アルファリリースということで、Stable版がリリースされるまではまだ時間がかかるかと思いますが、 IDE 以外にも選択肢が増えるのは嬉しいですね。好みとしては IDE と同じことができるならなんとなく CLI の方が好きです。とりあえずプロトタイピング等で試している段階であれば IDE の方が環境設定に苦労しないで済みそうなので便利ですが、実際のプロダクト開発では CLI で自動化できると楽なところは多そうです。今後のアップデートに期待したいですね。

M5Stack でサーモグラフィー

 M5Stack でサーモグラフィー画像を表示している例があったので、試しにやってみました。下記記事を参考にさせていただき、ほぼそのまま実行しています。

mag.switch-science.com

 先に結果を言っておくと、想定したように正しくは表示されませんでしたが、一応動作はするようになったのでやったことを書いておきます。

サーモグラフィーとの接続

 今回使ったサーモグラフィーは、上記記事で紹介されている下記のサーモグラフィーです。

www.switch-science.com

 接続方法も基本的には上記記事の通りで、M5Stack とサーモグラフィーの SCL, SDA, GND, 3.3V をそれぞれ接続します。上記の記事ではエンクロージャーまで作成していますが、そこまではできなかったので、とりあえずブレッドボードにサーモグラフィーを挿して、 M5Stack とジャンパケーブルで接続しました。

f:id:akanuma-hiroaki:20180825234432j:plain

 ちなみに M5Stack のピン配列は向かい合うピンとソケットで同じ信号が扱えるようになっていて、例えば今回使っている SCL, SDA, GND, 3.3V のピンは、向かいの辺にある 22番, 21番, GND, 3.3V のソケットと同様に扱えます。

f:id:akanuma-hiroaki:20180825234457j:plain

コードの実装

 今回は参考記事のコードをほぼそのまま使用させていただいていますが、そのままでは動かなかったので、所々変更を入れています。

 まず元のコードのコメントでも書かれていますが、ファームウェアの 0.3.4 からボタンオブジェクトが変更になっていますので、ボタンオブジェクトの import を下記のように変更します。

from m5stack import lcd, buttonA, buttonB, buttonC

 また、 I2C オブジェクトの初期化時に明示的にピン番号を指定するために、 Pin モジュールも import します。

from machine import I2C, Pin

 そして I2C オブジェクトの初期化時に、今回使用しているピンの番号で Pin オブジェクトを作成して sda, scl それぞれに指定します。

i2c = I2C(sda = Pin(21), scl = Pin(22))

 ボタンオブジェクトを変更したことに伴って、 loop() 内でのボタンオブジェクトの指定と、押されたかどうかの判定メソッドを変更します。

while True:
    if buttonA.isPressed():
        ison = True
    if buttonB.isPressed():
        minmax()
    if buttonC.isPressed():
        ison = False
    if ison:
        graph()

 コードの全体は下記のようになります。

from m5stack import lcd, buttonA, buttonB, buttonC
from machine import I2C, Pin
import sys
import ustruct

colors = (0x0000FF, 0x0008FF, 0x0010FF, 0x0018FF, 0x0020FF, 0x0028FF, 0x0030FF, 0x0038FF, 0x0040FF, 0x0048FF, 0x0050FF, 0x0058FF, 0x0060FF, 0x0068FF, 0x0070FF, 0x0078FF, 0x0080FF, 0x0088FF, 0x0090FF, 0x0098FF, 0x00A0FF, 0x00A8FF, 0x00B0FF, 0x00B8FF, 0x00C0FF, 0x00C8FF, 0x00D0FF, 0x00D8FF, 0x00E0FF, 0x00E8FF, 0x00F0FF, 0x00F8FF, 0x00FFFF, 0x00FFF7, 0x00FFEF, 0x00FFE7, 0x00FFDF, 0x00FFD7, 0x00FFCF, 0x00FFC7, 0x00FFBF, 0x00FFB7, 0x00FFAF, 0x00FFA7, 0x00FF9F, 0x00FF97, 0x00FF8F, 0x00FF87, 0x00FF7F, 0x00FF77, 0x00FF6F, 0x00FF67, 0x00FF5F, 0x00FF57, 0x00FF4F, 0x00FF47, 0x00FF3F, 0x00FF37, 0x00FF2F, 0x00FF27, 0x00FF1F, 0x00FF17, 0x00FF0F, 0x00FF07, 0x00FF00, 0x08FF00, 0x10FF00, 0x18FF00, 0x20FF00, 0x28FF00, 0x30FF00, 0x38FF00, 0x40FF00, 0x48FF00, 0x50FF00, 0x58FF00, 0x60FF00, 0x68FF00, 0x70FF00, 0x78FF00, 0x80FF00, 0x88FF00, 0x90FF00, 0x98FF00, 0xA0FF00, 0xA8FF00, 0xB0FF00, 0xB8FF00, 0xC0FF00, 0xC8FF00, 0xD0FF00, 0xD8FF00, 0xE0FF00, 0xE8FF00, 0xF0FF00, 0xF8FF00, 0xFFFF00, 0xFFF700, 0xFFEF00, 0xFFE700, 0xFFDF00, 0xFFD700, 0xFFCF00, 0xFFC700, 0xFFBF00, 0xFFB700, 0xFFAF00, 0xFFA700, 0xFF9F00, 0xFF9700, 0xFF8F00, 0xFF8700, 0xFF7F00, 0xFF7700, 0xFF6F00, 0xFF6700, 0xFF5F00, 0xFF5700, 0xFF4F00, 0xFF4700, 0xFF3F00, 0xFF3700, 0xFF2F00, 0xFF2700, 0xFF1F00, 0xFF1700, 0xFF0F00, 0xFF0700)

i2c_address = 0x68
register = 0x80

ison = False

offset = 0
rate = 1

i2c = I2C(sda = Pin(21), scl = Pin(22))

def getval(val):
    absval = (val & 0x7FF)
    if val & 0x800:
        return - float(0x800 - absval) * 0.25
    else:
        return float(absval) * 0.25

def minmax():
    global offset
    global rate
    reg = register
    min_temp = 1000
    max_temp = -1000
    for i in range(0, 64):
        val = ustruct.unpack('<h', i2c.readfrom_mem(i2c_address, reg, 2))[0]
        tmp = getval(val)
        if tmp < min_temp:
            min_temp = tmp
        if max_temp < tmp:
            max_temp = tmp
        reg += 2

    diff = max_temp - min_temp
    diff *= 1.4
    rate = len(colors) / diff
    offset = min_temp * 0.8

    lcd.clear()
    lcd.print('min:    ' + '{:.2f}'.format(min_temp), 0, 0)
    lcd.print('max:    ' + '{:.2f}'.format(max_temp), 0, 10)
    lcd.print('rate:   ' + '{:.2f}'.format(rate), 0, 20)
    lcd.print('offset: ' + '{:.2f}'.format(offset), 0, 30)
    
def graph():
    global offset
    global rate
    reg = register
    for ic in range(0, 8):
        for ir in range(0, 8):
            val = ustruct.unpack('<h', i2c.readfrom_mem(i2c_address, reg, 2))[0]
            tmp = (getval(val) - offset) * rate
            if tmp < 0:
                tmp = 0
            if 127 < tmp:
                tmp = 127
            lcd.rect(ic * 30 + 40, ir * 30, 30, 30, 0, colors[int(tmp)])
            reg += 2

def loop():
    global ison
    lcd.clear()
    lcd.print('Starting...', 0, 0)
    while True:
        if buttonA.isPressed():
            ison = True
        if buttonB.isPressed():
            minmax()
        if buttonC.isPressed():
            ison = False
        if ison:
            graph()

loop()

動作確認

 それでは動作を確認してみます。今回は上記コードを m5cloud でコーディングして M5Stack にアップロードします。

f:id:akanuma-hiroaki:20180825225238p:plain

 ボタンBを押すとキャリブレーションを行います。

f:id:akanuma-hiroaki:20180825235143j:plain

 ボタンAを押すとサーモグラフィーの画像の表示を開始します。実行結果は下記の通りです。一応動作はしましたが、結果としては微妙でした。。。手をかざすなどすると反応はするのですが、全体の一部分だけで、大部分の領域が青色のまま変化しませんでした。

f:id:akanuma-hiroaki:20180825235223j:plain

まとめ

 残念ながら結果が正しく表示されるところまでは行けませんでしたが、向かい合うピンとソケットが同じように使えることや、最新のボタンモジュールなど色々とわかったのは良かったです。効率的なデバッグ方法がまだわかっていないので、その辺りは効率的な開発のためには必要ですね。あと、サーモグラフィーやLCDの扱いについてはもう少し調べて、正しくサーモグラフィー画像が表示されるようにしてみたいと思います。

 今回ボタンモジュールについては下記記事を参考にさせていただきました。

qiita.com

M5Stack のアバターを試してみる

 前回 m5stack の環境設定だけやってみましたが、購入前からやってみたかった顔表示を試してみたいと思います。と言っても @meganetaaan さんがライブラリを公開されているので、表示するだけならすぐにできてしまいました。

github.com

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

 Arduino IDE にライブラリをインストールするには、まず下記URLからライブラリの zip ファイルをダウンロードします。

https://github.com/meganetaaan/m5stack-avatar/archive/master.zip

 次にダウンロードした zip ファイルを Arduino IDE のメニューからアップロードします。

f:id:akanuma-hiroaki:20180818204126p:plain

 これで Arduino IDE で m5stack-avatar ライブラリが使えるようになります。 Library Manager でも下記のようにライブラリが確認できます。

f:id:akanuma-hiroaki:20180818204351p:plain

サンプルの実行

 ライブラリが正しくインストールされていれば、 Arduino IDE からサンプルスケッチが選択できるようになっています。顔を表示するだけであれば basic を選択します。

f:id:akanuma-hiroaki:20180818205920p:plain

 あとはスケッチを m5stack にアップロードすれば、ディスプレイに顔が表示されるようになります。

f:id:akanuma-hiroaki:20180818211118j:plain

表情をランダムに変更する

 m5stack-avatar では普通の顔以外にもいくつか表情が用意されています。サンプルの中にはボタンを押すごとに順番に表情や画面の色を変更していくものがありますが、それをベースに一定時間ごとに表情をランダムに変更するようにしてみました。また、表情が普通の場合には事前に定義したフレーズの中からランダムに吹き出しで表示するようにしました。

#include <M5Stack.h>
#include <Avatar.h>

using namespace m5avatar;

Avatar avatar;

const Expression expressions[] = {
  Expression::Angry,
  Expression::Sleepy,
  Expression::Happy,
  Expression::Sad,
  Expression::Doubt,
  Expression::Neutral
};
const int expressionsSize = sizeof(expressions) / sizeof(Expression);
int idx = 0;

const char* phrases[] = {
  "How are you?",
  "Hungry...",
  "I'm bored."
  "What's time?",
  "Did you say something?",
  "It's time."
};
const int phrasesSize = sizeof(phrases) / sizeof(char*);
int phrase_idx = 0;

void setup()
{
  M5.begin();
  M5.Lcd.setBrightness(30);
  M5.Lcd.clear();

  avatar.init();
}

void loop()
{
  M5.update();
  idx = rand() % expressionsSize;
  Expression expression = expressions[idx];
  avatar.setExpression(expression);
  if (expression == Expression::Neutral) {
    phrase_idx = rand() % phrasesSize;
    avatar.setSpeechText(phrases[phrase_idx]);
  } else {
    avatar.setSpeechText("");
  }
  delay(30000);
}

 これを実行すると下記のように吹き出しでメッセージを表示したり色々な表情に切り替わって行きます。

f:id:akanuma-hiroaki:20180818212147j:plain

f:id:akanuma-hiroaki:20180818212226j:plain

f:id:akanuma-hiroaki:20180818212337j:plain

まとめ

 顔が表示されるようになるとそれだけで何か愛着が湧いてくるから不思議ですね。今はただ表情を変えてるだけですが、実用的な機能も追加してアシスタントっぽくして行けないかなーと思ってます。もしくは個人的には C++ よりも MicroPython の方が好きなので、 MicroPython でもアバターっぽいものが作れないかなーと考えています。