加速度センサー MMA8452Q の値を Seeeduino で読み取る

 なんとなく興味があったので、加速度センサーを買ってみました。

www.switch-science.com

 Raspberry Pi や BLE Nano から使ってみようかとも思ったのですが、公式のチュートリアルでは Arduino での使い方が書いてあり、ライブラリもあるようだったので今回は Arduino Uno 互換の Seeeduino で加速度センサーの値を読み取ってみます。

チュートリアル
MMA8452Q Accelerometer Breakout Hookup Guide - learn.sparkfun.com

ピンヘッダの実装

 今回買った MMA8452Q の Breakout Board にはピンヘッダが実装されていません。

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

 ブレッドボードで色々試してみるにはやはりピンヘッダがあった方が便利なので、自分で半田付けして実装しました。

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

動作電圧

 MMA8452Q の動作電圧は 3.3V です。電源供給についてはマイコン側のピンで選べるようになっていることが多いかと思いますが、電源以外のピンの電圧も 3.3V に調整する必要があります。 Arduino Uno だと 5V なので、抵抗をかませるなどで 3.3V に調整しなくてはなりませんが、 Seeeduino は動作電圧を 5V にするか 3.3V にするかをスイッチで選べるようになっています。デフォルトでは 5V になっているので、 3.3V 側にスイッチを切り替えておきます。

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

フックアップ

 MMA8452Q の出力インタフェースは I2C なので、 Seeeduino の SCL/SDA をそれぞれ MMA8452Q の SCL/SDA に接続します。 3.3V ピンと GND ピンもそれぞれ接続します。

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

ファームウェア実装

 MMA8452Q の Arduino 用ライブラリが下記リポジトリで公開されています。

github.com

 IDE にライブラリをインポートするため、下記 URL からライブラリをダウンロードします。

https://github.com/sparkfun/SparkFun_MMA8452Q_Arduino_Library/archive/master.zip

 今回は IDE に Arduino Web Editor を使用します。 Web Editor の使い方の詳細は割愛しますが、左側メニューの「Libraries」の画面から先ほどダウンロードしたライブラリをインポートします。成功すると下記のような画面が表示されます。

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

 コードについてはまずはサンプルをそのまま動かしてみます。ライブラリのリポジトリの下記 URL にてサンプルが公開されていますので、これをそのまま Web Editor でコピペします。

SparkFun_MMA8452Q_Arduino_Library/SparkFun_MMA8452Q_Basic.ino at master · sparkfun/SparkFun_MMA8452Q_Arduino_Library · GitHub

 コピペ後の画面は下記のような感じになります。 Seeeduino を USB で接続して正しく認識されていれば、対象のボードが表示されているかと思います。

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

動作確認

 サンプルをそのまま動かすだけであればここまでで準備完了です。 Web Editor で Verify して問題なければ Seeeduino にファームウェアを Upload します。正しく動作すれば、 Web Editor の Serial Monitor に加速度センサーの値と、センサーの向きの情報が表示されていきます。

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

傾きに応じて LED を点灯させる

 サンプルにちょっとだけ手を加えて、センサーの傾きに応じて LED を点灯させてみたいと思います。サンプルコードからコメントを削除して、 LED を動作させるようにしたコードを下記に載せておきます。やっていることは単純で、 LED を4つ配置し、サンプルコードで判定しているセンサーの向きに応じて対応する LED を点灯させているだけです。

#include <Wire.h> // Must include Wire library for I2C
#include <SparkFun_MMA8452Q.h> // Includes the SFE_MMA8452Q library

MMA8452Q accel;

const int ledPortraitUp = 13;
const int ledPortraitDown = 12;
const int ledLandscapeRight = 10;
const int ledLandscapeLeft = 11;

void setup()
{
  Serial.begin(9600);
  Serial.println("MMA8452Q Test Code!");
  
  accel.init();
  
  pinMode(ledPortraitUp, OUTPUT);
  pinMode(ledPortraitDown, OUTPUT);
  pinMode(ledLandscapeRight, OUTPUT);
  pinMode(ledLandscapeLeft, OUTPUT);
}

void loop()
{
  if (accel.available())
  {
    accel.read();
    
    printCalculatedAccels();
    
    printOrientation();
    
    Serial.println(); // Print new line every time.
  }
}

void printAccels()
{
  Serial.print(accel.x, 3);
  Serial.print("\t");
  Serial.print(accel.y, 3);
  Serial.print("\t");
  Serial.print(accel.z, 3);
  Serial.print("\t");
}

void printCalculatedAccels()
{ 
  Serial.print(accel.cx, 3);
  Serial.print("\t");
  Serial.print(accel.cy, 3);
  Serial.print("\t");
  Serial.print(accel.cz, 3);
  Serial.print("\t");
}

void printOrientation()
{
  byte pl = accel.readPL();
  switch (pl)
  {
  case PORTRAIT_U:
    digitalWrite(ledPortraitUp, HIGH);
    digitalWrite(ledPortraitDown, LOW);
    digitalWrite(ledLandscapeRight, LOW);
    digitalWrite(ledLandscapeLeft, LOW);
    Serial.print("Portrait Up");
    break;
  case PORTRAIT_D:
    digitalWrite(ledPortraitUp, LOW);
    digitalWrite(ledPortraitDown, HIGH);
    digitalWrite(ledLandscapeRight, LOW);
    digitalWrite(ledLandscapeLeft, LOW);
    Serial.print("Portrait Down");
    break;
  case LANDSCAPE_R:
    digitalWrite(ledPortraitUp, LOW);
    digitalWrite(ledPortraitDown, LOW);
    digitalWrite(ledLandscapeRight, HIGH);
    digitalWrite(ledLandscapeLeft, LOW);
    Serial.print("Landscape Right");
    break;
  case LANDSCAPE_L:
    digitalWrite(ledPortraitUp, LOW);
    digitalWrite(ledPortraitDown, LOW);
    digitalWrite(ledLandscapeRight, LOW);
    digitalWrite(ledLandscapeLeft, HIGH);
    Serial.print("Landscape Left");
    break;
  case LOCKOUT:
    digitalWrite(ledPortraitUp, LOW);
    digitalWrite(ledPortraitDown, LOW);
    digitalWrite(ledLandscapeRight, LOW);
    digitalWrite(ledLandscapeLeft, LOW);
    Serial.print("Flat");
    break;
  }
}

 動作させた時の様子は下記のようになります。傾きに応じて持ち上がっている側の LED が点灯するようになっています。

まとめ

 Arduino 用のライブラリが公開されているおかげで値の読み取りはとても簡単にできてしまいました。 Raspberry Pi 等で扱う場合はどうすれば良いのかも気になるところなので、今後調べてみようと思います。

CdS + Seeeduino + LED で常夜灯をつくる

 子どもが夜中に起きた時に部屋が暗いのが嫌だというので、暗い時だけ LED を点灯させるように CdS セルを使って常夜灯を作ってみました。 CdS セルについては以前 BLE Nano と一緒に使ってみたことがありますが、今回は Seeeduino(Arduino互換機) を使ってみました。

 以前 CdS を使ってみたときの記事はこちらです。

blog.akanumahiroaki.com

回路図

 まずは直接回路を組むのではなく、 Tinkercad でシミュレートしてみます。 Seeeduino は Arduino互換機なので、回路図では Arduino を配置しています。 Tinkercad については以前も下記記事で紹介しました。

blog.akanumahiroaki.com

 LED は一つではさすがに暗いので、とりあえず並べられるだけ並べて12個を並列に配置します。これでどれぐらい明るくなるかはわかりませんがひとまずやってみます。それぞれのアノード側に 4.7Ω の抵抗を配置して、 Seeeduino の13番ピンに接続します。カソード側は GND に接続します。

 CdS の出力はアナログ出力なので、 Seeeduino のアナログ入力で読み取ります。 CdS の一方を GND に接続し、もう一方は 1kΩ の抵抗を挟んで5V出力とアナログ入力の A0 ピンに接続します。

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

コーディング

 コードもまずは Tinkercad で実装します。今回はネットワーク接続等は考慮していないのでごくシンプルに、下記のようなコードで実装しました。 analogRead() で13番ピンから CdS の値を読み取り、閾値以上だったら(暗かったら) LED を点灯、閾値未満だったら(明るかったら)消灯しています。

int led_pin = 13;
int lux_pin = 0;
int lux = 0;
int lux_threshold = 900;

void setup()
{
  Serial.begin(9600);
  pinMode(led_pin, OUTPUT);
}

void loop()
{
  lux = analogRead(lux_pin);
  Serial.println(lux);
  if (lux >= lux_threshold) {
    digitalWrite(led_pin, HIGH);
  } else {
    digitalWrite(led_pin, LOW);
  }
  delay(100);
}

シミュレーション実行

 それでは Tinkercad でのシミュレーションを実行してみます。シミュレーションを開始してから CdS を選択するとスライダーが表示され、明るさをコントロールすることができます。今回のコードでは CdS の値をシリアルで出力するようにしているので、Serial Monitor に値が表示されていきます。スライダーで明るさを暗くすると値が大きくなりLEDが点灯し、明るくすると値は小さくなって消灯することが確認できます。

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

実物で実行

 では実際の回路を組んで実行してみます。手元にあったもので組んだので、ジャンパーコードの色は回路図とは合ってませんが、回路は同じようにしています。回路を組んだら Tinkercad で書いたコードを Arduino Web Editor にインポートし、 Seeeduino にファームウェアをフラッシュします。するとコードが実行され、以下の動画のように手で CdS を覆って暗くすると LED が点灯します。 Web Editor の Serial Monitor には CdS の値が表示されています。

まとめ

 とりあえず手元にあったもので想定していた動作をさせることはできました。普通の LED では12個並べても明るさは不足してそうですが、暗い部屋での目印暗いニアなりそうです。実際に子ども部屋に置くとなると、電源はAC電源でUSB給電しようと思っているので、コンセントの壁面にコンパクトに設置できるようにする方法を考える必要がありそうです。ケーブルの長さなどもちゃんと調節してスッキリさせたいですね。作ってる過程としては単純にLEDがたくさん点灯するとそれだけで楽しかったりします。それにしても Tinkercad は便利ですね。

 今回は下記の記事を参考にさせていただきました。

deviceplus.jp

BLE の接続シーケンスを Wireshark で確認してみる

 前回 BLE Sniffer と Wireshark で BLE パケットをスニッフィングする方法を書きましたが、 Wireshark で確認できる内容から BLE の接続シーケンスを確認してみたいと思います。手元にあった BLE デバイスで簡単に確認してみた結果を書いてみます。

ADV_IND

 BLE デバイスがアドバタイジングを開始するとアドバタイジング・パケットを送出し始めます。 PDU(プロトコル・データ・ユニット)のタイプとしては4タイプありますが、今回使用したデバイスでは ADV_IND となっていました。

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

 ADV_IND を含め、アドバタイジング・パケットのタイプは下記の4タイプになります。

  • ADV_IND:不特定多数のデバイスから接続可能
  • ADV_NONCONN_IND:デバイスからの接続は不可能
  • ADV_SCAN_IND:デバイスからのスキャン可能
  • ADV_DIRECT_IND:特定デバイスから接続可能

SCAN_REQ

 セントラルデバイスがペリフェラルデバイスからアドバタイジング・パケットを受け取った時に、アドバタイジング・パケットのペイロードのデータだけでは情報が不足している場合、 スキャン・リクエスト(SCAN_REQ)パケットを送信します。

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

SCAN_RSP

 ペリフェラルデバイスが SCAN_REQ パケットを受け取ると、その応答として SCAN_RSP パケットを送信します。

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

CONNECT_REQ

 アドバタイジング・パケットの送受信が完了し、セントラルデバイスからペリフェラルデバイスに対して接続要求が行われると、 CONNECT_REQ パケットが送信され、接続状態に切り替わります。セントラルとペリフェラルはそれぞれマスター(Master)とスレイブ(Slave)になり、 Wireshark での Source と Definition のデバイス表示も、 MAC アドレス表示から Master, Slave に切り替わります。

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

LL_VERSION_IND

 リンク層の接続制御に使われるロジカル・リンク・コントロール PDU では、オペコード(Opcode)でその種別が表されています。 LL_VERSION_IND はコントローラのバージョン番号を示すためのものです。

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

Exchange MTU Request/Response

 Exchange MTU Request/Reponse はアトリビュート・プロトコルの最大長(MTU: Maximum Transfer Unit)を決定するために使われます。まずはクライアント側から自身が扱える ATT_MTU をサーバ側に通知します。そのレスポンスとしてサーバからはサーバ側で扱える ATT_MTU を返します。

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

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

Read Request/Response

 サーバのアトリビュートをクライアントから読み取るには Read Request/Response が使われます。 Read リクエストには下記の5種類があります。

  • Read
  • Read Multiple
  • Read Blob
  • Read By Type
  • Read By Group Type

 Read By Group Type ではアトリビュートのグループを読み出します。下記の例では GATT の Primary Service Declaration を読み取っています。

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

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

 Read By Type ではアトリビュート・タイプを指定した読み出しに使用します。下記は GATT の Characteristic Declaration の例です。

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

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

 アトリビュートが存在しない場合は下記のように Error Response が返ってくるようです。

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

 Read ではアトリビュート・ハンドルを指定して値を読み出します。

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

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

 長さが ATT_MTU を超えるアトリビュート・バリューを持つアトリビュートはロング・アトリビュートと呼ばれ、その値を読み出す場合には Read Blob が使われます。

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

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

Find Information Request/Response

 アトリビュート・ハンドルの範囲を指定してアトリビュート・ハンドルとアトリビュート・タイプを読み出すには Find Information が使われます。アトリビュートのタイプとバリューが指定できる Find By Type Value リクエストもありますが、今回は使われていなかったようです。下記は Find Information の例です。

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

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

Write Request/Response

 アトリビュート・ハンドルを指定して書き込みを行うには Write が使用されます。

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

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

 Write には他にも下記の4種類がありますが、今回は使われていなかったようです。

  • Prepare Write
  • Execute Write
  • Write Command
  • Signed Write Command

Handle Value Notification

 サーバからクライアントへの通知には Handle Value Notification が使われます。

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

Connection Parameter Update Request

 コネクションのパラメータを変更する場合には Connection Parameter Update Request が送信されます。

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

 オペコードとしては LL_CONNECTION_UPDATE_REQ が使われます。

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

 パラメータが変更されると Connection Parameter Update Response が返されます。

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

LL_CHANNEL_MAP_REQ

 コネクションのチャンネル・マッピングを変更する際には LL_CHANNEL_MAP_REQ というオペコードが使われます。

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

LL_TERMINATE_IND

 コネクションを切断するには LL_TERMINATE_IND オペコードが使われます。

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

まとめ

 ざっとですが手持ちの一デバイスで確認できた内容を書いてみました。 BLE デバイスを使ったサービスを開発する場合に、BLEデバイスとの接続に問題がありそうな場合には、今回のように接続シーケンスを確認することで何か解決への手がかりが見つかるかもしれません。使用方法もとても簡単なので、勉強のためにも今後色々と使ってみたいと思います。

 今回は下記のサイトを参考にさせていただきました。

blog.reinforce-lab.com

dsas.blog.klab.org

BLE Sniffer + Wireshark で BLE パケットをスニッフィングする

 BLE デバイスを使ったシステムを開発していると、BLE デバイスがどんな状態かを確認したいことが時々あります。アドバタイズメントを出しているかは LightBlue などのツールでも確認できますが、通信状態の詳細はわかりませんし、接続後の状態は接続しているデバイス側でデバッグ用の対応を入れる必要があります。

 そこで今回は、 BLE Sniffer を使ってみました。BLE Sniffer を使うと周囲のBLEデバイスの通信状況を確認することができますし、 Wireshark と連携することでさらに詳しくパケットを確認することができます。

 今回使ったのは Adafruit の Blueftuit LE Sniffer です。

Bluefruit LE Sniffer - Bluetooth Low Energy (BLE 4.0) - nRF51822 - v3.0
https://www.adafruit.com/product/2269

f:id:akanuma-hiroaki:20180407194943j:plain:w450

 スイッチサイエンスにも掲載はありましたが在庫切れだったので、 mouser で購入しました。

https://www.mouser.jp/ProductDetail/Adafruit/2269?qs=%2fha2pyFadujCcMq4sbQCcNuQKfV2ZrTBUyTuH62%2f2DAJK9B%252b%2f1bGJ3muPYq2CyZ9

www.switch-science.com

ユーティリティのインストールなど

 基本的な使用手順は下記のイントロダクションページで紹介されています。

Introducing the Adafruit Bluefruit LE Sniffer
https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-sniffer

 Windowsユーザの方であれば上記ページにて紹介されている手順通りに Nordic の公式ユーティリティをインストールして使用できるのですが、 Mac には対応していないので、 Mac ユーザ向けのページが別途用意されています。

OS X Support
https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-sniffer/os-x-support

 上記ページで Roland King さん提供の OS X 用のユーティリティが紹介されていますので、こちらを使用します。

nrf-ble-sniffer-osx
https://sourceforge.net/projects/nrfblesnifferosx/

 インストール手順や使用方法は上記プロダクトの Wiki ページに記載されていますので、そちらに従います。

https://sourceforge.net/p/nrfblesnifferosx/wiki/ble_sniffer/

 インストールはプロダクトのページからパッケージインストーラをダウンロードして実行するだけです。

ble-sniffer-osx Download
https://sourceforge.net/projects/nrfblesnifferosx/files/latest/download

Wireshark のインストール

 BLE Sniffer 単体で利用してもある程度の利用状況はわかるのですが、パケットアナライザを使うことでより詳細にパケットの状況を確認することができます。 Bluefruit LE Sniffer では Wireshark と連携することができるようになっています。

Wireshark · Go Deep.

 上記サイトからダウンロードしてインストールするのですが、 Bluefruit LE Sniffer の OS X Support ページには下記のように記載があります。 

Be sure to download Wireshark version 2.0.x NOT the new 2.2.7 that was released June 2017

 Wireshark の新しいバージョンではなく、 2.0系を使うようにということなので、下記から過去のバージョンを探します。

Wireshark All Versions
Index of /pub/network/security/wireshark/osx/all-versions

 2.0系の最新バージョンは 2.0.16 のようなので、こちらをダウンロードしてインストールします。

Wireshark 2.0.16 Intel 64.dmg
http://ftp.yz.yamagata-u.ac.jp/pub/network/security/wireshark/osx/all-versions/Wireshark%202.0.16%20Intel%2064.dmg

 下記のように tshark コマンドが使えるようになっていれば正しくインストールされています。

$ tshark -v
TShark (Wireshark) 2.0.16 (v2.0.16-0-gd60ab50 from refs/heads/master-2.0)

Copyright 1998-2017 Gerald Combs <gerald@wireshark.org> and contributors.
License GPLv2+: GNU GPL version 2 or later <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Compiled (64-bit) with libpcap, without POSIX capabilities, with libz 1.2.5,
with GLib 2.36.0, with SMI 0.4.8, with c-ares 1.12.0, with Lua 5.2, with GnuTLS
3.4.17, with Gcrypt 1.7.7, with MIT Kerberos, with GeoIP.

Running on Mac OS X 10.13.3, build 17D102 (Darwin 17.4.0), with locale
C/UTF-8/C/C/C/C, with libpcap version 1.8.1 -- Apple version 79.20.1, with libz
1.2.11, with GnuTLS 3.4.17, with Gcrypt 1.7.7.
Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz (with SSE4.2)

Built using llvm-gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build
2336.9.00).

スニッフィング実行

 必要なもののインストールが終わったので、スニッフィングを実行してみたいと思います。ユーティリティは Applications ディレクトリ内で下記のようなアイコンで表示されますので、起動します。

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

 BLE Sniffer を接続していないと下記のような表示になります。

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

 ここで BLE Sniffer を接続します。接続して少し待つとスニッフィングが始まり、アドバタイズメントを出しているデバイスのリストが表示されます。項目としては、デバイス名、MACアドレス、電波強度(RSSI)、アドバタイズ用の3つのチャネルそれぞれでのインターバルが表示されます。

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

 デバイスリストの中から特定のデバイスについて詳しく見たい時には、そのデバイスを選択して Sniff Device をクリックします。

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

 すると「Currently Sniffing」というフィールドの表示が追加になり、スニッフィング中のデバイスの情報が表示されます。

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

 デバイスの情報までは確認できたので、パケットの状況を詳しく見るために、 Wireshark と連携してみます。 Capture to Wireshark ボタンをクリックします。

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

 すると Wireshark が起動し、 スニッフィングしたパケットが Wireshark で表示されます。

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

 起動時のデフォルトでは時系列で並んだ一番古いパケットの部分が表示されていますが、メニューの下記ボタンを押すことで常に最新のパケットが表示されるようにスクロールされます。

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

 下側のペインではBLEパケットのさらに詳しい情報が表示されます。一つ目はフレームの詳細です。

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

 二つ目は BLE Sniffer のメタデータです。

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

 三つ目はデータリンク層の情報です。

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

まとめ

 BLEデバイスを使うサービスを開発するときは、BLEデバイス側に問題があるのか、アプリ側に問題があるのかの切り分けが難しい場合がありますが、このツールを使うことでアドバタイズメントの状況や詳しいパケットの情報が見られるので、問題の切り分けがしやすくなりそうです。BLEでどういったパケットがどういう順番でやり取りされるかを知らないと見てもわからない部分もありますが、逆にそれを理解するためにもこういったツールは有効かと思います。

Arduino Cloud に Raspberry Pi を接続して Lチカ

 Arduino ではオンライン上でのオールインワンの開発プラットフォームとして Arduino Create というものを提供しています。

create.arduino.cc

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

 以前の記事で使った Arduino Web Editor も Arduino Create で提供されているサービスです。そのほかのサービスとして Arduino Cloud という、 Arduino を簡単にインターネットに接続したり、ほかの Arduino と相互に接続したり、デバイスを管理したりできるサービスを提供しています。現在 Arduino Cloud の対応デバイスはまだ少なく、 YUN SHIELD、 MKR1000、 WIFI SHIELD 101 の3つのようで、いずれも技適を通っていないため日本ではまだ Arduino Cloud に対応している Arduino 端末はないようです。前回の記事で使用した WROOM-32 も Arduino 互換なので、なんとか接続できないかと色々試してみたのですが、今のところまだ接続できていません。

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

 とりあえず対応している Arduino 端末が日本でも使えるようになるのを待ちたいと思いますが、 Arduino Cloud では Arduino 以外にも、 Raspberry Pi や BeagleBone などの Linux 端末も接続することができるので、今回は Raspberry Pi を接続してみたいと思います。

Arduino Cloud に Raspberry Pi を登録

 まずは Arduino Cloud に Raspberry Pi をデバイスとして登録します。Raspberry Pi の通常の初期セットアップは事前に終わらせておき、ネットワークに接続されている状態にしておきます。 Arduino Cloud にアクセスすると下記のようなメニュー画面になります。 Arduino Cloud 対応の Arduinoボードを登録する場合には右下の Arduino Cloud を選択すれば良いのですが、 Raspberry Pi などの Linux 端末を登録する場合には、左下の My Devices を選択します。

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

 デバイスを登録するとできるようになることなどの説明が表示されるので、 ADD NEW DEVICE をクリックします。

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

 登録するデバイスを選択する画面になりますので、今回は Set up a Raspberry Pi を選択します。

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

 セットアップの手順内で行われる内容の説明が表示されます。セットアップでは PC 側にまだ Arduino Plugin がインストールされていなければインストールし、 Raspberry Pi 側に Arduino Connector がインストールされます。 NEXT をクリックして先に進みます。

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

 Raspberry Pi がオンラインになっていることを確認するように促す画面が表示されますので、オンラインになっていれば MY DEVICE IS READY をクリックします。

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

 セットアップの実行の仕方の選択肢として、 Raspberry Pi の IP アドレスがわかるか、 Raspberry Pi にモニタとキーボードが使えるようになっているかを選択します。今回はモニタとキーボードは繋いでいないですが、 IP アドレスはわかっているので、 I KNOW THE IP ADDRESS OF MY DEVICE を選択します。

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

 すると IP アドレスの入力欄が表示されるので、 IP アドレスを入力して NEXT をクリックします。

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

 Raspberry Pi にアクセスするためのアカウント情報が求められるので、フォームに入力して DONE をクリックします。

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

 セットアップが開始され、処理中は下記のような画面が表示されます。ここで Arduino Connector のインストールなどが行われます。処理が終わると画面は自動的に切り替わりますので、このまま待ちます。

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

 セットアップが無事終了すると下記のように Arduino Cloud に登録するデバイス名の入力フォームが表示されますので、わかりやすい名前をつけて SAVE をクリックします。

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

 これでひとまず登録は完了ですので、 GO TO MY DEVICES をクリックしてデバイス一覧画面に移動します。

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

 デバイス一覧には登録した Raspberry Pi が表示され、ネットワークに接続されていれば ONLINE という表示になっています。

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

 ここでデバイスを選択すると下記のようにデバイスの状態についてのダッシュボードが表示されます。

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

 ちなみに登録した Raspberry Pi でホームディレクトリを見てみると、Arduino Connector 関連の下記のようなファイルが追加されています。

$ ls -ltr ~
合計 28368
〜〜〜抜粋〜〜〜
-rwxr-xr-x  1 pi   pi   11346716  35 15:31 arduino-connector
-rw-------  1 root root      227  321 08:32 certificate.key
-rw-------  1 root root     1099  321 08:32 certificate.pem
-rw-r-----  1 pi   root      203  321 08:32 arduino-connector.cfg
-rw-r--r--  1 pi   pi        445  321 08:32 arduino-connector.log

 ログにはインストール時のものと思われるログが記録されています。 MQTT のサーバとしては AWS IoT を使っているっぽいです。

$ cat arduino-connector.log 
Version: 1.0.94
Generate private key
Generate csr
Request certificate
Request mqtt url
Write conf to arduino-connector.cfg
Check successful mqtt connection
setupMQTT certificate.pem certificate.key akanuma:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xxxxxxxxxxxxxx.iot.us-east-1.amazonaws.com
WARN: memstore.go:137: [store]    memorystore wiped
WARN: net.go:328: [net]      errorWatch stopped
WARN: net.go:318: [net]      logic stopped
Setup completed

 設定ファイルは下記のような内容で作成されていました。

$ cat arduino-connector.cfg 
id=akanuma:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
url=xxxxxxxxxxxxxx.iot.us-east-1.amazonaws.com
http_proxy=
https_proxy=
all_proxy=
authurl=https://hydra.arduino.cc/
apiurl=https://api2.arduino.cc

スケッチの実行

 Arduino Cloud にデバイスを登録すると、 Arduino Uno 等の Arduino ボードと同様に、 Web Editor からスケッチをフラッシュして実行させることができます。そのデバイスがオンラインであれば Web Editor の接続先ボードとして選択できるようになりますので選択します。

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

 今回はとりあえず下記のような Lチカのスケッチで試してみます。

const int ledPin = 12; // GPIOピン番号ではなく物理ピン番号

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

void loop()
{
  digitalWrite(ledPin, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(ledPin, LOW);
  delay(1000); // Wait for 1000 millisecond(s)
}

 上記コードを用意したら Arduinoボードの時と同様に、 Verify ボタンでコンパイル可能か確認して問題なければ Upload ボタンで Raspberry Pi にスケッチをアップロードして実行します。成功すると下記のように Web Editor のコンソールに Raspberry Pi で実行されているプロセスの ID が出力されます。

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

 Raspberry Pi 上で確認してみると、確かにその PID でスケッチが実行されています。

$ ps aux | grep 1474 | grep -v grep
root      1474  0.1  0.2   4340  2520 pts/2    Ss+  22:35   0:00 /home/pi/sketches/CoolDensor1

 アップロードからLチカ実行の様子は下記動画のようになります。

 さらにプロセスの実行/停止もWeb上から操作できます。 Web Editor の RUN/STOP ボタンをクリックします。

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

 すると登録済みのスケッチのリストと、各スケッチの実行状況がトグルボタンで表示されますので、このトグルを切り替えることでプロセスの実行/停止を行うことができます。

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

 操作してみた様子は下記動画の通りです。トグルの切り替えでLチカの実行/停止を操作することができています。

まとめ

 Raspberry Pi 側では初期セットアップさえ終わっていれば、簡単に Arduino Cloud に登録できますし、登録してしまえば Raspberry Pi 側で直接操作することなく、他の Arduino ボードと同様に Web Editor から触ることができて便利ですね。 Arduino 以外にも mbed をはじめ、各社がクラウド環境でのプラットフォームを提供するようになってきていますが、それぞれできることが違っているので、デバイスを選定する場合はボード自体の機能だけでなく、プラットフォームの内容も含めて検討するのが良さそうです。

ESPr Developer 32 で WROOM-32 を Wi-Fi に繋いでみる

 前回 Seeeduino という Arduino Uno 互換ボードで Arduino に初めてさわってみたわけですが、 Arduino Uno は標準ではネットワークインタフェースを持っておらず、 Wi-Fi シールドも技適を通っているものを使うとなると選択肢は少なく、あっても結構高くついてしまうようでした。また、 ESP-WROOM-02 のような Wi-Fi モジュールを使おうと思うと、 Arduino Uno の 3.3V 出力では電流量が足りずに正しく動作しないようなので、それであれば Arduino Uno との組み合わせではなく単体でも Arduino 互換ボードとして動作し、 Wi-Fi だけでなく Bluetooth/BLE にも対応している ESP-WROOM-32 を使ってしまうのが良さそうということで、購入してみました。モジュールのサイトは下記になります。

www.espressif.com

 実際に使うにあたってはモジュール単体よりも開発ボードを買った方が色々とやりやすいので、今回はスイッチサイエンスで販売されている ESPr Developer 32 を購入しました。

www.switch-science.com

 ESP-WROOM-32 の開発ボードの選択肢としては他にも秋月電子で販売されている ESP32-DevKitC などもありますが、ESPr Developer 32 であれば突入電流対策が行われているということでしたので、値段的には ESP32-DevKitC よりも若干高いですが、 ESPr Developer 32 を選んでみました。

akizukidenshi.com

開発環境の準備から動作確認まで

 Seeeduino は Arduino Uno 互換ということで、 Arduino Web Editor を使ったのですが、 WROOM-32 は Web Editor では対応できないようだったので、 Arduino IDE を Mac にインストールして使用しました。インストール手順は下記リンク先で紹介されています。特に難しいことはないと思いますのでここでは詳細は割愛します。

Arduino - MacOSX

 次に、 Arduino IDE で WROOM-32 のファームウェアの開発ができるように、 Arduino core for ESP32 をインストールします。

github.com

$ mkdir -p ~/Documents/Arduino/hardware/espressif
$ cd ~/Documents/Arduino/hardware/espressif
$ git clone https://github.com/espressif/arduino-esp32.git esp32
$ cd esp32
$ git submodule update --init --recursive
$ cd tools
$ python get.py

 インストールが終わったら、 Mac と ESPr Developer 32 を USB ケーブルで接続します。

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

 そして Arduino IDE を起動します。起動したら Tools メニューの Board の選択肢から、 ESP32 Dev Module を選択します。

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

 これでひとまず環境の準備はできましたので、とりあえず正しく ESPr Developer 32 にファームウェアが書き込めるか確認してみます。下記スケッチを Arduino IDE で作成します。シリアル接続してシリアルモニタに文字を出力するだけのコードです。

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("Hello World from ESPr Developer 32 :)");
  delay(1000);
}

 コードを入力したらまずは IDE の Verify ボタンでビルドできるか確認します。下記のような感じでエラーなくビルドされれば成功です。 

Sketch uses 162273 bytes (12%) of program storage space. Maximum is 1310720 bytes.
Global variables use 11052 bytes (3%) of dynamic memory, leaving 283860 bytes for local variables. Maximum is 294912 bytes.

 それでは IDE の Update ボタンで ESPr Developer 32 に書き込みます。

Sketch uses 162273 bytes (12%) of program storage space. Maximum is 1310720 bytes.
Global variables use 11052 bytes (3%) of dynamic memory, leaving 283860 bytes for local variables. Maximum is 294912 bytes.
esptool.py v2.1
Connecting....
Chip is ESP32D0WDQ6 (revision 0)
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 8192 bytes to 47...

Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 4364.7 kbit/s)...
Hash of data verified.
Compressed 14128 bytes to 9196...

Writing at 0x00001000... (100 %)
Wrote 14128 bytes (9196 compressed) at 0x00001000 in 0.1 seconds (effective 1022.1 kbit/s)...
Hash of data verified.
Compressed 163424 bytes to 84070...

Writing at 0x00010000... (16 %)
Writing at 0x00014000... (33 %)
Writing at 0x00018000... (50 %)
Writing at 0x0001c000... (66 %)
Writing at 0x00020000... (83 %)
Writing at 0x00024000... (100 %)
Wrote 163424 bytes (84070 compressed) at 0x00010000 in 1.4 seconds (effective 929.0 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 122...

Writing at 0x00008000... (100 %)
Wrote 3072 bytes (122 compressed) at 0x00008000 in 0.0 seconds (effective 1712.6 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting...

 書き込みが成功すると自動的にプログラムが実行され、シリアルモニタでは下記のように文字列の出力が繰り返されます。

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

Wi-Fi 接続確認

 ひとまず動作確認ができたので、 Wi-Fi への接続も確認してみます。とりあえず Wi-Fi に接続して、Webサーバへのリクエストを投げてみます。接続先としては同じ LAN に接続している Mac で下記のように HTTP サーバを起動しておきます。

$ python -m SimpleHTTPServer                                                                                                                                                                                                          
Serving HTTP on 0.0.0.0 port 8000 ...

 ESPr Developer 32 で動かすコードは下記のようになります。 Wi-Fi への接続自体は WiFi.begin() で SSID とパスワードを指定するだけでOKで、あとは WiFi.status() で接続ステータスが WL_CONNECTED になれば接続完了です。 loop() の処理としては先ほど動かした HTTP サーバに GET リクエストを投げてレスポンスを表示しているだけの単純なものです。

#include <WiFi.h>
#include <HTTPClient.h>

const char SSID[] = "aterm-xxxxxx-g";
const char PASSWORD[] = "xxxxxxxxxxxxx";
const char URL[] = "http://192.168.10.5:8000/";

void setup() {
  Serial.begin(115200);
  while(!Serial);

  WiFi.begin(SSID, PASSWORD);
  Serial.printf("Connecting to the WiFi AP: %s ", SSID);

  while(WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println(" connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  HTTPClient http;
  http.begin(URL);

  Serial.printf("Response: %d\n", http.GET());
  String body = http.getString();
  Serial.print("Response Body: ");
  Serial.println(body);

  delay(1000);
}

 これを Verify して問題なければ Upload で ESPr Developer 32 に書き込みます。書き込みが終わって起動すると、下記のようにシリアルモニタに出力され、 Wi-Fi へ接続して HTTP サーバからコンテンツを取得していることがわかります。

Connecting to the WiFi AP: aterm-xxxxxx-g ......... connected.
IP address: 192.168.10.10
Response: 200
Response Body: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
<hr>
<ul>
</ul>
<hr>
</body>
</html>

 HTTP サーバ側でも下記のようにリクエストを受信しているログが出力されます。

192.168.10.10 - - [17/Mar/2018 16:30:09] "GET / HTTP/1.1" 200 -
192.168.10.10 - - [17/Mar/2018 16:30:09] "GET / HTTP/1.1" 200 -
192.168.10.10 - - [17/Mar/2018 16:30:10] "GET / HTTP/1.1" 200 -

まとめ

 ネットワークインタフェースを搭載していないボードの場合、まずネットワークに接続できるようになるまでで結構苦労しそうですが、 ESPr Developer 32 のようなネットワークモジュールを積んだ開発ボードを使うことで簡単にネットワークに接続できてしまいます。値段的にも Arduino Uno やその互換ボードと比べても高くないですし、特に理由がなければ WROOM-32 などを最初から使ってしまう方が良さそうです。 ESPr Developer 32 にはピンヘッダがついていないので、今後自分ではんだ付けしてセンサー等との連携も試してみたいと思います。

Seeeduino(Arduino互換ボード)+ Tinkercad で Lチカ

 今まで Arduino は触ったことがなかったのですが、 Arduino 互換ボードの Seeeduino を買ったのでとりあえず Lチカしてみました。

www.switch-science.com

 Seeeduino は Arduino 互換というだけでなく、 GROVEコネクタが搭載されていますので、 Arduino よりも手軽にいろんなデバイスが接続できそうです。

f:id:akanuma-hiroaki:20180313074204j:plain:w450

 注意点として、PCと接続するためのUSBケーブルが、 Arduino Uno は A - B のタイプですが、 Seeeduino では A - microB ですので、そこはお気をつけください。

まずは Tinkercad でシミュレーション

 早速回路を組みたくなるところですが、まずは Tinkercad でシミュレーションしてみたいと思います。 Tinkercad は電子回路の作成と Arduino でのコード実行をシミュレートできるツールで、以前会社のブログで紹介させていただきましたので詳細はそちらをご覧ください。

tech.unifa-e.com

 Seeeduino は Tinkercad のパーツとしては用意されていないので、 Arduino を使っています。ブレッドボードに LED と抵抗(330Ω)を配置して、 Arduino に接続しています。コードはデフォルトで用意されている Lチカのコードそのままで、下記のようになります。これでシミュレーションを実行すると LED が点滅します。コードのダウンロードもできますので、あとで実機で動かすためにダウンロードしておきます。右上のダウンロードボタンをクリックすると、.ino形式のファイルとしてダウンロードすることができます。

f:id:akanuma-hiroaki:20180313082955p:plain:w450

Arduino Web Editor にコードをインポート

 Arduino ではプログラム(スケッチ)を開発するためのIDEが提供されています。

Arduino - Software

 IDE にはブラウザからアクセスしてオンラインで使える Arduino Web Editor と、MacやPCにインストールして使用する Arduino IDE があります。今回は Arduino Web Editor を使ってみます。

create.arduino.cc

 使用するにはアカウント登録が必要です。特に登録手順で難しいことはないのでここでは詳細は割愛します。

 Web Editor に初めてアクセスすると利用規約への同意が求められますので、名前と国を選んで NEXT をクリックします。

f:id:akanuma-hiroaki:20180313083730p:plain:w450

 Web Editor から実機にスケッチをフラッシュするにはプラグインをインストールする必要があり、その案内が表示されます。 NEXT をクリックして先へ進みます。

f:id:akanuma-hiroaki:20180313083747p:plain:w450

 左上で OS の種類を選択し、 DOWNLOAD PLUGIN ボタンをクリックするとインストーラがダウンロードされますので、 Mac であればダウンロードされた .dmg ファイルを実行し、案内に従ってインストールします。インストール自体は特に難しいことはないのでここでは割愛します。

f:id:akanuma-hiroaki:20180313083803p:plain:w450

 インストールが終了するとブラウザでの表示が下記のように変わりますので、 NEXT をクリックします。

f:id:akanuma-hiroaki:20180313083856p:plain:w450

 機能説明を実行するか選べるようになってます。機能説明を見るなら YES! をクリックします。

f:id:akanuma-hiroaki:20180313083916p:plain:w450

 一通り説明が終わると、下記のように手持ちのスケッチブックデータをインポートするか聞かれますので、 YES! をクリックします。

f:id:akanuma-hiroaki:20180313083936p:plain:w450

 アップロードできるのは .Zip .Ino .Pde 形式のいずれかという注意書きが表示されます。Tinkercad からダウンロードしたファイルは .Ino 形式ですので、 IMPORT をクリックしてファイルを選択してアップロードします。

f:id:akanuma-hiroaki:20180313083958p:plain:w450

 これでエラーにならなければ無事アップロード完了ということで、下記のように Tinkercad からダウンロードしたコードが Web Editor にインポートされて表示されます。

f:id:akanuma-hiroaki:20180313084014p:plain:w450

回路作成と接続

 それでは実際に回路を作成します。 Tinkercad で作ったものと同様の回路を構成して、 USB で接続します。

f:id:akanuma-hiroaki:20180313084132j:plain:w450

 Web Editor で、PCに接続しているボードとポートを選択します。プルダウンメニューから Board at 〜 もしくは Select Other Board & Port を選択します。

f:id:akanuma-hiroaki:20180313091600p:plain:w450

 Seeeduino は Arduino Uno 互換なので、 BOARDS から Arduino/Genuino Uno を選択します。 ポートは一台しか接続していなければ一つしか表示されないので、それを選択して、 OK をクリックします。

f:id:akanuma-hiroaki:20180313091616p:plain:w450

 画面上部の Verify ボタンを押して、ボードの選択が正しく行われているか確認します。 Success: Done verifying 〜 と表示されれば成功です。

f:id:akanuma-hiroaki:20180313091632p:plain:w450

動作確認

 それでは Upload ボタンを押して、ボードにスケッチをフラッシュします。 Success: Done uploading 〜 と表示されれば成功です。

f:id:akanuma-hiroaki:20180313091652p:plain:w450

 フラッシュ後は下記動画のようにLEDが点滅します。

まとめ

 Tinkercad で事前にシミュレーションすることで動作を確認した上で回路を組むことができますし、 Arduino Web Editor を使えばプラグインのインストール以外の環境構築も必要なく、手軽にプログラミングすることができました。 Seeeduino は価格的にも Arduino より安いですし、それでいて GROVE コネクタもついているので、色々と遊んでみたいと思います。