📝

Toit×Soracomでマイコンを使ったIoTをより簡単に!

2021/12/07に公開

IoTプロジェクトで最初に悩むこと

IoTプロジェクトを計画するとき、まず何から考えますか?たぶん皆さんまずどのようなデバイスを使用するかを考えると思います。

さまざまな選択肢やパラメータがありますが、その中でも重要なのは、デバイス側でロジックを実行するために何を使うかということです。大まかに言うと、2つのカテゴリーがあるかなと思っています。

Linuxベースのデバイス: LinuxやフルOSを搭載したコンピュータ。ラズパイや類似のシングルボードコンピュータ(SBC)、LinuxをOSとして動作させるゲートウェイなどは、IoTユースケースのロジックを実装するのに便利で人気ですよね

マイクロコントローラー: よりシンプルにCPUとメモリ、GPIOなどのインターフェースと無線通信を備えた小型のボードも、IoTユースケースの有力な選択肢となります。数が出るエッジデバイスでは、シンプルで低コストであることは大事です。ESP32のようなネットワーク・インターフェースを統合したシステム・オンチップ・マイクロコントローラーを使ったIoTシステムがこれまで以上に多くなっているのを感じています。

これらの選択肢にはそれぞれ長所と短所があるのでそれをまずはみていきます!

慣れ親しんだLinuxベースのデバイスは始めやすいけど、、、

Linuxベースのデバイスは、一般的なプログラミング言語やアプリケーションフレームワークのほとんどが動作するため、開発を始めるのが容易です。多くの開発者のみなさんが既に持っているスキルと経験を活かしてデバイス用のコードを書き始められます。また、一般的なクラウドサービスプロバイダのSDKもそのまま動作するため、クラウド連携も難しくありません。

デバイスの管理やリモートアクセスのためのソリューションも多くの選択肢があります。デバイスがSORACOMで接続されている場合、ユーザはSORACOM Napterを使ってオンデマンドでポートを開き、SSHやRDP、管理者用Web UIなどを使ってセキュアに遠隔から管理を行うこともできます。

一方で、豊富な機能が組み込まれた完全なオペレーティングシステムを実行しなければならないことから、デバイスの消費電力や求められるスペックが高くなりがちです。特に、バッテリーで動作させる必要があるIoTのユースケースでは、Linuxベースのデバイスでバッテリー寿命の要件を満たすのは大変です。

マイコンは低コストで低消費電力だけど開発や管理のハードルが、、、

組み込み向けの開発に慣れてる方でなければ、マイクロコントローラー上での開発は専用のツールを使ったり、デバッグポートにシリアル接続したりなど、いろいろと敷居が高いかと思います。また、プログラミング言語や開発フレームワークの選択肢も限られています。PythonやJavascriptのような高度な言語を使う選択肢もないわけではないですし、それらを活用した方が生産性は高いものの、CPUやメモリのリソースが限られているマイコンでは十分な性能を引き出せないことも多くあります。組込み機器でよく使われているのはむしろC言語またはその派生言語など、よりアセンブラに近く、コンパイルされたコードが最小限のフットプリントで済む言語です。

自分も含め、モダンなプログラミング言語で提供される機能に慣れてる開発者にとってはあれもこれも自分でケアしないといけないことを改めて実感します。例えば、ガベージコレクションが自動的に行われないため、メモリーリークに注意しなければならない、などなど。

OSにしても、組み込み用OSを選択するか、OSなしでコードを書くなどの選択肢になってきます。言わずもがなですが、ファイルシステムやスレッド、IO割り込みなど、OSの機能を使わずにアプリケーションを開発するのは大変です。

更にクラウドサービスに統合する際には、その環境に合ったSDKを見つけて、それを使って開発することになります。また、OSがあればアプリをシステムから分離して、アプリがクラッシュしてもデバイス全体を落とすことなくアプリを再起動するなども可能ですが、そういうレイヤーがなければアプリのバグでデバイスが文鎮化するなんてことも起こりかねません。

あと結構忘れがちなのが、それらのデバイスのファームウェアやアプリケーションコードを書くというのは一度限りの仕事ではないという点です。ファームウェアを更新したり、リモートでバージョンを管理する仕組みが必要なのは言うまでもないですが、どうやってやりますか?Linuxベースのデバイスとは異なり、既製のフレームワークを使って解決というわけにもなかなかいかないんですよね。

では何でわざわざそんな開発者にとって苦行とも言える道を検討しないといけないんでしょう?もちろん(それが要件に書いてあったとか?)いろんな理由があると思いますが、大きな理由はマイコンの方がコストと消費電力を抑えられるからです。バッテリー駆動のIoTデバイス開発するときにはよっぽど大きなバッテリを使えるケースでなければマイコンを選択することになるのではないかと思います。そういった理由もあって、IoTシステムの開発においてマイコンを選択するケースがとても多くなっているのを感じます。

両者の良いとこどりはできないの?

ここまで一長一短って話を見てきましたけど、Linuxベースのデバイスとマイコンのいいとこ取りってできないんですかね?両方の利点を持ってて、クラウドサービスと簡単に統合できて、開発やメンテナンスも容易なソリューションってないんでしょうか?

それが今日のトピック!答えは「YES」です。いい話には裏があるものですが、そうなんです。いい話の裏を支えるプラットフォームがあるというのがこのブログでお伝えしたいポイントです!

今日の本題:Toit x SORACOM!

Toit はデンマークを拠点に元Googleの組み込み開発技術の経験者などがチームを組んで起ち上げた、マイコン向け開発の課題を解決するソリューションを提供するスタートアップです。ESP32で広く使われているリアルタイムOSであるFreeRTOSの上に、薄いハイパーバイザのようなレイヤーを実装し、ユーザーがアプリケーションをコンテナとして実行できるようにしまったのです。そうそう、まるでLinuxに対するDockerのような環境をESP32上で利用できるのです。

また、初めて彼らと話したときに驚いたんですが、↑で書いたようにIoT開発のために適した開発言語がなかったという理由で、Toitという軽量でモダンな言語も合わせて自分たちで開発しちゃったというのです。ガベージコレクションなども備えた高レベルのオブジェクト指向言語ながら、ESP32のような環境でも高効率高パフォーマンスで実行できるとのこと!C言語で書いていざデバイスでコード実行したときに謎のSeg Faultで死んで終わって絶句したり、暫く動かしていたらメモリリークで死ぬことに気づいたなんて経験ありませんか?(私はよくあります。。。)Toitを使えばそういった悩みから開放されつつ、より短時間で多く機能を実装できると思います。最近言語自体はオープンソース化されて話題になっていたので、ぜひこの機会に見てみてください。

で、Toitは言語の名前でもあるのですが、それを開発した会社及び、同社が提供するクラウドプラットフォームの名前でもあります。なので、Toit言語でコードを書いたら、ToitプラットフォームのWebコンソールやAPIを使って、ネットワーク越しにESP32マイコンにコードをデプロイできちゃうんです!つまり、↑で書いたマイコン上での開発における課題の多くを解決できちゃうんですよ!

というわけで、実際に使ってみましょう。

セットアップ

まず、ESP32のボードを用意しましょう。僕はPycom GPyボードを選びました(注:当方アメリカ在住。日本では技適を通った同様のボードを見つける必要がありそうです)。このボードはWiFi、Bluetooth、Cellular(LTE-MとNB-IoT)など、重要な無線インターフェースをすべてサポートしています。大体末端価格で50 USDくらいなので、シングルボードコンピュータ (SBC) と追加のセルラーモデムに比べて、かなりの節約になります。同じような価格のSBCを見つけることができるかもしれませんが、大体セルラーモデムを別途購入する必要があるんじゃないかと思います。

このボードのSIMスロットにSORACOMのSIMカードを挿入し、LTE-Mネットワークを介してどこからでもToitのクラウドに接続できるようにしました。

次のステップは、Toitのファームウェアの書き込みです。ウェブサイトからToit CLIをダウンロードして、手元のMacにセットアップします。

Pycom GPyとMacをUSBケーブルで接続しました。Pycom GPyボードのファームウェアをフラッシュするには、ファームウェアフラッシュモードを設定する必要があるので、P2端子とGroundをジャンパーケーブルで接続して、再起動ボタンを押します。

あとは以下のコマンドを実行して、Pycom GPyにToitファームウェアをフラッシュします。ちなみに、SORACOM SIMでLTE-Mネットワークに接続するために、APNを「soracom.io」と指定しています。

% toit serial reinstall \
  --firmware v1.4.2 \
  -p model.cellular.enabled=1 \
  -p model.cellular.tx=5 \
  -p model.cellular.rx=23 \
  -p model.cellular.rts=19 \
  -p model.cellular.cts=18 \
  -p model.cellular.pwr=27 \
  -p model.cellular.monarch=1 \
  -p cellular.apn=soracom.io

これで準備は整ったので、Toitのウェブコンソールにアクセスして、デバイスをクレームしてみます。デバイスIDをコピー&ペーストして、クレームボタンを押します。

すると、ブーン!デバイスが現れ、Toitクラウドに接続されたのが確認できます!

それでは、「CODE」タブでコードを実行してみましょう。Toit のドキュメントに次のようなコードサンプルがありました。

import net
import http

main:
  network_interface := net.open

  host := "www.google.com"
  socket := network_interface.tcp_connect host 80

  connection := http.Connection socket host
  request := connection.new_request "GET" "/"
  response := request.send

  bytes := 0
  while data := response.read:
    bytes += data.size

  print "Read $bytes bytes from http://$host/"

これは、www.google.com のポート80への接続を開き、HTTPリクエストを送信し、何バイト受信したかを表示するシンプルなコードサンプルです。このコードをコピーしてコードタブに貼り付け、「実行」ボタンを押します。

そして...動いた!

とっても簡単じゃないですか?ですよね?今回は自分の机の上で行いましたが、SORACOM IoT SIMで接続されているので、LTE-Mネットワークがあれば、何千キロも離れた場所にあるボードでも同様に実行できちゃうんです。簡単だけどなんてパワフル!

実際に何か役に立つことをやってみよう:センサーを接続して温湿度測定

さて、せっかくなので何かIoTっぽい、役に立つことをしてみましょう。BoschのBME280という温度・湿度・圧力センサーがあったので、これを接続して、温度と湿度を測定できるはずです。写真のようにセンサーを接続しました。

注意点としては、Pycom GPyがピンとGPIOの内部リマッピングを行うため、P12とP11をそれぞれGPIOピン21と22に使用する必要がありました(GPy P12はGPIOピン21に、GPy P11はGPIOピン22にマッピングされています)。詳しくは、Pycomのスペックシート をご覧ください。(ToitのAnders Johnsenさんが迅速かつ適切なサポートをしてくれました!)

そして、Toit Weatherstationチュートリアルにある以下のコードをコピー&ペーストして、実行ボタンを押します。

import gpio
import i2c
import bme280

main:
  bus := i2c.Bus
    --sda=gpio.Pin 21
    --scl=gpio.Pin 22

  device := bus.device bme280.I2C_ADDRESS_ALT

  driver := bme280.Driver device

  print "Temperature: $driver.read_temperature C"
  print "Humidity: $driver.read_humidity %"
  print "Pressure: $driver.read_pressure Pa"

順調ですね!この部屋の温度、湿度、気圧を測定できました。

次はクラウドに接続!

このデータをクラウドに送れるようになれば、同じデバイスをたくさん用意して、多地点からあつまるデータを収集して分析なんてこともできて、もっと面白いのでぜひやってみましょう!でも、マイコンに適したSDKを見つけて、それを使ってコードを書かなければならないと言いませんでしたっけ?

大丈夫だ。心配ない。なぜ?このボードは、単なるインターネット接続ではなく、クラウドへのスマート接続を提供するSORACOM IoT SIMを装備しているから!

SORACOMプラットフォームには、データを受信した際、SORACOMクラウドに保存したり、AWS IoT、Azure IoT、Google IoT Coreなど、お好みのクラウドサービスに転送する機能があります。また、AWS Lambda、Azure Functions、Google FunctionなどのFunction as a Service上のファンクションを呼び出して、デバイスにレスポンスを送り返すこともできます。つまり、SDKを見つけて専用のコーディングをしたり、認証用のクレデンシャルをデバイスにプロビジョニングしたりしなくても、マイコンをクラウド・サービスに統合することができるのです。

実際にやってみましょう。SORACOMのウェブコンソールにいって、SORACOM SIMを使って送られたデータをデータストレージサービスであるSORACOM Harvestに保存するように設定します。

まず、SORACOM コンソールに行き、自分のSIMを選択します。

そして、"Actions "メニューをクリックし、"Change Group "を選択して、Soracom Harvestを有効にした新しいグループを作成します。

とりあえず「Toit demo」という名前にして、SIMを作成し、グループに割り当てます。

これで、手元のSIMは新しく作成されたグループに属することになりました。それをクリックして、グループの設定をしてみましょう。

”SORACOM Harvest Data"までスクロールしてタブを開き、サービスを有効にして "Save "をクリックします。

これで完了です!これで、このSIMでSORACOM Harvestが有効になりました。SIMからデータが受信されるたびに、SORACOM Harvestに保存され、データを照会したり視覚化したりすることができます。

それでは、ボードからデータを送信してみましょう。データをJSON形式に変換してSORACOMエンドポイント(http://unified.soracom.io)に送信するように、先程のコードを少し変更しました。変更は以下の通り:

  • BME280からデータを読み込んでJSON形式で返す関数 "read_sensor_data "を定義。この関数は、上記のセンサー読み取りコードをベースにしています。
  • “send_data_to_soracom "という関数を定義しました。この関数は、contentとcontent typeを引数にとり、HTTP POSTでSoracomエンドポイントにデータを送信します。これは主に、先ほどのHTTPサンプルコードに基づいています。
  • ”read_sensor_data "と "send_data_to_soracom "を順番に呼び出すように修正。
import gpio
import i2c
import bme280

import http
import net

main:
  data := read_sensor_data
  send_to_soracom data "application/json"

read_sensor_data:
  bus := i2c.Bus
    --sda=gpio.Pin 21
    --scl=gpio.Pin 22

  device := bus.device bme280.I2C_ADDRESS_ALT

  driver := bme280.Driver device

  temperature := driver.read_temperature
  humidity := driver.read_humidity
  pressure := driver.read_pressure
  
  print "Temperature: $temperature C"
  print "Humidity: $humidity %"
  print "Pressure: $pressure Pa"


  json := "{\"temperature\":$(%.1f temperature),\"humidity\":$(%.0f humidity),\"atmosphericPressure\":$(%.1f pressure)}"
  return json

send_to_soracom content contentType:
  network_interface := net.open

  host := "unified.soracom.io"
  socket := network_interface.tcp_connect host 80

  connection := http.Connection socket host
  request := connection.new_request "POST" "/"
  request.headers.set "Content-Type" contentType
  request.body = content.to_byte_array
  response := request.send
  
  print "Response was $response.status_code $response.status_message"

先ほどと同じように実行してみましょう。

動いた! SORACOMのエンドポイントから正常応答を受け取ったようです。さて、SORACOMコンソールに戻って、収穫されたデータを見てみましょう。

期待通りウェブコンソールにデバイスからのデータが表示されています!

このコードを定期的に実行すれば、温湿度や気圧などのデータをSORACOM Harvestのデータストレージに記録し、Web UIやAPIで参照することができます。

さらに、このあとの発展形としては、データをAWS IoTやAmazon Kinesisに転送したり、AWS Lambda関数を呼び出したりするようにSoracom SIMを設定しさえすれば、デバイス側のロジックを変更することなく、クラウドにデータを保存したり、機械学習を使ったデータ分析を行うなど、思い通りにシステムを組むことができます。


また、すでにご存じのように、デバイス側のコードに変更を加えたい場合は、Toitクラウドを使って更新されたファームウェアを送信することができます!

Toit×Soracomでマイコンを使ったIoTをより簡単に!

ToitとSORACOM、2つのプラットフォームを組み合わせることで、マイコンを使ったIoTデバイスの開発がいかに簡単になるかを感じていただけたかとおもみます。ご興味のある方は、ぜひ両方のサービスに登録して試してみてください。ご質問やフィードバックなどはTwitterなどのソーシャルはもちろん、https://chat.toit.io にジョインしていただいて #cellular チャンネルがあって、そちらでToitとSoracomの両チームがお待ちしてます。 みなさんがIoTプロジェクトの共通の難関部分をプラットフォームに任せて、一番楽しい部分の開発に集中できるように、両チームとも願ってますので、よかったらお試しください!

Discussion