工場長のブログ

日々思ったことを書いてます。

MyCobot280のサーボ交換 - STS3215 ID 書き換えを添えて

この記事は一見、IoTやSORACOMについての記事に見えますが、それは背景の説明であって、実際にお伝えしたいのは(残しておきたいのは)MyCobotのサーボの交換にまつわる困りごとやノウハウです。

MyCobotが骨折した(サーボが壊れた)

SORACOM DiscoveryのIoT プロトタイピングコーナーに「おっし、おれなりのPhysical AI像を出すぞ」ってことで「目(ソラカメ)と手(MyCobot280)を用意するから難しいことは全部AIに任せたピックアップチャレンジ!」的なノリで以下のようなものを作ってました。AIで駆動するEye-to-Hand的な構成ですね。Fable5がいればなんとかなるっしょ。って思ってました。

そんなに簡単じゃなかった

やってみると実際にはすごーく難しくてAIと以下のようなやりとりのスパイラルを繰り広げることとなりました。

  • AI:Intel RealSense入れようよ。
  • オレ:いやーそれ目新しさないじゃん。あと、専用機器を使うようなアプローチはしたくない。
  • AI:ティーチングやろう。
  • オレ:わかるけど、それ汎用性ないじゃん。デモでは「ほら、ここに好きなものをおいてAIに◯◯を拾ってって言ってみてください」ってやりたいんだよ。
  • オレ:外部カメラ1個だと2次元的(3次元的?)な位置特定が難しいなら画角を変えたソラカメ増やそうよ。
  • AI:いやーそれあんま意味ないと思う。

Depth Camera(Realsense)もティーチングもロボット業界ではめちゃくちゃデファクトスタンダードな手法。議論を進めていくと自然とやっぱりそれらをRevisitすることになったのはとても興味深かったです。

実装もAIに目と手を渡して行った

開発スタイルとしてはClaude CodeにラズパイへのSSH鍵を渡して、手元のPC上でコードを書いてラズパイにデプロイして動かす。それをソラカメで撮影させて(それもMCP経由で自分でやらせた)評価する、みたいな感じでAI自身で完全にループを回せるようにしてました。すごく楽しかったし、とても未来感を感じてました。「ロボットアームがどうしても真下に向かない、アームのサーボのテレメトリ的には真下を向いてるはずなのに」みたいなときはアームの先にBLEの加速度センサー付けて「これ、こんな型番のセンサー付けたから自分でラズパイにドライバインストールしてキャリブレーションに使ってね」っていったらほんとに望み通りの姿勢制御ができるようになったりしました。

ひとりでどんどん賢くなっていくロボットに「あれ?これスカイネットが生まれるんじゃね?」みたいな感想を持ったりもしました。

なお、当時はちょうどClaude CodeのAutoモードが出てきていたタイミングでした。世間に疎いわたしは「あーなんか最近のClaudeくん、なんかいちいち確認しに来なくなって便利だなー」くらいにしか感じていなかったw 

 

期日とにらめっこしながら仕事の隙間を縫いつつちまちま開発と改善、そして妥協を続けていく中でなんとか動くものができてきたので、あとはチューニング?キャリブレーション?でデモの精度とUXのよさをあげていこう。と思ってわたしはAIにこういいました。

「わたしは寝るからとりあえず朝までキャリブレーションを繰り返しておいて」

すごくウキウキしながら寝ました。デモもあとは性能を挙げていけばいい段階になったわけだし、それも(自分よりイケてる)AIがやってくれるわけだし。

 

でも朝起きてわたしが目撃したのは必死に立ち上がろうとする生まれたての子鹿のようなMyCobotくんでした。

 

そうなんです。

AIにこき使われすぎたMyCobotくん、骨折していました(サーボが故障していました)。

立ち上がろうとして崩れ落ちるのを繰り返すその姿は、まじで、生まれたての子鹿!!!!!!

ということで、MyCobotのサーボを交換することにしました。正直、サーボ以外の可能性もいろいろ考えたし調査もしてみましたが「まあ、やってみよう」ということで。

 

ということでここまではおまけです。

MyCobotのサーボはSTS3215。ネットで買って交換した。

2箇所くらい筐体を開けてみると、関節ごとにFeetechのSTS3215というサーボがマウントされていました。ベースにはM5Stackと専用のインターフェイスボードがあり、そこから6個のサーボがデイジーチェーンされている構成です。

にわかなわたしは全然肌感がありませんでしたが、流通している部品だということでAmazonで調達しました。1個3500円くらい。

ちなみに、サーボホーン(サーボと筐体をつなぐ部品。写真の円形のやつ)のネジ穴が、経緯はわかりませんがいま売っているSTS3215のサーボホーンがM3なのに対して、筐体(と、旧部材)のネジ穴がM2です。いろいろググって見ましたがSTS3215用のM2のサーボホーンは市場から調達できなさそうなので、MyCobotの筐体側のネジ穴を精密ドリルでM2からM3に拡張しました。ここはもしかしたら専用部品だったのかもしれません。

ネジ穴を拡張した筐体側の写真は撮り忘れた(そしていまから筐体を開けて取り直すの面倒)のですが、完全に1 way doorな作業なので慎重にやりました。2.5mmまで拡張して試して、2.8mmまで拡張して・・・というような具合に。筐体の強度が落ちたり、なんならその作業の結果クラックが発生したりするのを防ぎたかったので。

余談: 筐体をすこし補修した

これは余談ですが今回の作業で筐体をひととおりチェックしてみると、今回サーボの交換作業をしているJ2の関節周りのフレームに細かいクラックがちょいちょい見つかりました。構造的に、そこから先の重さをすべて支える関節であること、そしてMyCobotがいわゆるモノコックフレーム構造であることから筐体にもだいぶ負荷がかかっていたのだと思われます。どのくらい意味があるかはわかりませんが念の為パテ埋めしておきました。(ヤスリはかけてませんw

あれ?サーボが2つ同時に動く?

OKめでたし。これでいける。と思ってましたが、甘かったです。MyCobotのキャリブレーションを走らせてみると(交換したのはJ2、2番目のサーボ)、J1とJ2が同時に動くのです。

いろいろ動かしてみてはたと思い至ったのがJ1とJ2、同じ命令を受け取ってないか?

ということでした。MyCobotについての内部情報はあまり見つからなかったものの、LeRobot SO-101など同様のロボットの構成を調べてみると、サーボがデイジーチェーン構成になっていて根元側から6個の関節(サーボ)にそれぞれIDを1~6を割り振っているであろうと、想像的に判断されました。

ということでSTS3215のサーボIDを書き換えてみた

いろいろ調べてみるとサーボのデイジーチェーン構成はわりとよくあるプラクティスであって、ブロードキャストされるコマンドを受け取るのはIDベースでの判断になるということがわかりました。

ここから先はサーボIDの書き換えにはメーカーであるFeetechが提供している専用のソフトウェアを使って書き換えます。

↑は前述のプログラミング環境のスクショ。ID(サーボID)を出荷時のデフォルト値の1から任意の値(今回はJ2、第2関節なので2)に書き換えます。

 

もろもろのマニュアルや1st party情報は下記にあります。
https://akizukidenshi.com/goodsaffix/feetech_digital_servo_20220729.pdf

 

なお、インターフェイスボードのFE-URT-1は、いろんな面倒を自前で引き受けられるなら(例えば供給電力や物理インターフェイスなど)不要ですがわたしはそれに係る時間的なコストをはらいたくなかったので当該ボードを買って無事にIDを書き換え、結果としてMyCobotの復活となりました。

なお、STS3215のID書き換えと動作確認には6V 2A(定格)の電源供給が必要です。わたしの家は一般のご家庭なので安定化電源がありましたが、これがないとまた面倒です。

MyCobotのサーボ交換まとめ

と、余計なことしか書いて来ませんでしたが、TLDR的には、MyCobotのサーボを交換するには以下のようになります。

STS3215を買って、アームの関節IDにあわせてサーボのIDを書き換えて設置すればOK。ただし、ホーンのネジ径の物理調整の必要があり。

ここからまたオフトピックです

なぜサーボが壊れたのか考えてみる

「そりゃ、ひとばん動かし続ければ壊れるだろ」と言われればそうです。が、物理世界のエンジニアリングの経験がほぼゼロのわたしにはその肌感やサーボの動作原理についての知識がなくAIを使って数時間、負荷をかけ続けた結果こうなったというわけです。

ソフトウェアのループは実質タダみたいなものですが、物理世界のループやデューティサイクルという有限資源を消費していく。AIは疲れないけど部品は疲労する。

当たり前の話ではありますがそれを実感した経験談でした。

なにか続きを書こうと思ってます

SORACOM Discoveryへの出展は断念しましたが、せっかく直したのでこどもの夏休みの自由研究のテーマとして「AIでロボットを動かしてみる。プログラミングしてみる。」というハンズオンコンテンツに昇華をさせているところです。できあがったらまた書きます。

あと、AIを使ったPhysical開発みたいな話ももう少し掘り下げて書いてみたいなと。

時間は点ではなく幅 ~そのIoTデバイス、どうやって世界と「時間」を共有している?~

はじめに —— 私たちは「時間」を当然のように使っている

エンジニアをやっていると、普段から時間を扱うことが数多くあると思います。

また、みなさんのほとんどがスマホを使ってインターネット上のいろんなサービスを利用していると思います。ここでふと立ち止まって「スマホ上のアプリケーションたちはどうやって不安定な無線通信上で例えばTCP通信を実現しているのか?」と、今日は考えてみたいのです。TCPは不安定なネットワーク上でも動作するように作られたプロトコルですが、それでも不安定であれば通信効率は大きく損なわれます。また、音声通話はどうでしょうか?リアルタイムで高品質な通話を実現するために低レイヤな部分でなにが起こっているのでしょうか?

プログラマであれば、timeout=30s や TTL=60 といった数字を、わりと普通につかっていると思います。NTP はだいたい合っているし、クラウドの中では数十ミリ秒のズレは誤差のうちでしょう。 しかし無線通信の世界では、その感覚はまったく通用しなくなってしまう部分があるんです。あなたのスマホは基地局と、ミリ秒どころかもっと細かい世界で足並みを揃えています。 しかもそれを、地球規模で数十億台がやっています。 今日はその世界をちょっと覗いてみたいと思います。

分散システム(つまり、システムを構成するコンポーネントが物理的に離れた場所に位置するシステム)では「遅延」や「ズレ」は日常的に存在します。 それでもあなたのスマホは、同期的な通話を成立させ、動画を見せ、メッセージを届けてくれます。 この「当たり前」を支えているのが、時間の扱い方です。

本稿執筆時点で筆者のわたしは株式会社ソラコムに所属していますが、これを読んでも IoT アプリケーションの開発やソラコムの使い方になんら寄与することはありません。 完全な読み物です。


1. スマホで音声通話ができるのは、なぜ当たり前なのか

身近な例から始めましょう。

スマホで電話をかける。
相手が出る。
声が聞こえる。

あまりにも当たり前すぎて、「どうやって動いているのか」を意識することはほとんどないですよね。 「電話はまあそりゃ同期的に会話できるよね」くらいに思いますよね。 けれどこの裏側では、かなり複雑で、時間にうるさい仕組みが動いています。

セルラー通信をざっくり層構造で描くと、次のようになります。 なお、ここから先、例えば「UE」などのセルラーシステム用語がちょいちょい出てきますが、気付いたところのみ解説する形でご容赦ください。

図1:セルラーの層構造と「時間の厳しさ」

┌──────────────────────────────┐
│ Application (通話アプリなど) │ ← 人間の時間(100ms〜)
├──────────────────────────────┤
│ IMS / SIP / RTP (VoLTEの世界) │ ← 多少の遅延・揺らぎは吸収できる
├──────────────────────────────┤
│ NAS / Bearer (登録・セッション管理など) │ ← 論理タイマ(秒〜分)
├──────────────────────────────┤
│ RRC / MAC (制御とスケジューリング) │ ← 締切(ms)
├──────────────────────────────┤
│ PHY (OFDM / HARQ / シンボル境界) │ ← 暴力(µs〜ms)
└──────────────────────────────┘

下の層に行くほど、時間は暴力的になります。

セルラーは「時計を合わせる」のではなく、レイヤごとに別のやり方で「時間」を扱い分けている。
そしてその扱い分けがあるからこそ、巨大で壊れやすい世界が、壊れないように回っています。

VoLTE のような通話中の通信は、言ってしまえば 連続的 です。

  • UE(ざっくり言えばデバイス)は起き続ける
  • gNB(ざっくり言えば基地局)の電波を常に聞いている
  • ズレたらすぐ補正できる

この意味では、通話中のスマホはまだ「優しい世界」にいます。 同期を取り続けるための材料が、常に流れているからです。

ここで大事なのは、UE(スマホ)が話している相手は、通話相手ではないという点です。
UE は、常に 基地局(gNB)とだけ 話しています。

音声データはネットワークの中で転送されますが、 無線区間に限って言えば、UE は

  • 「いまこのフレームだよ」
  • 「次はここで送っていいよ」
  • 「ちょっとズレてるから直してね」

という会話を、ミリ秒以下の粒度で基地局と続けています。

通話中は UE が起き続け、基地局の電波を常に受信できる。 つまり、ズレてもすぐに検出でき、すぐに補正できる。ということから相対的に「優しい」のです。


2. では、IoTデバイスはどうして電池が持つのか

—— 連続的に通信しない世界は、もっとハードでは?

ここで少し視点を変えてみましょう。 スマホから離れて、バッテリーで何年も動く IoT デバイス の世界です。

IoT 向けのセルラー通信では、eDRX(extended DRX)や PSM といった省電力の仕組みが使われます。 eDRX の実際の挙動や使いどころについては、去年の Advent Calendar で詳しく書きましたのでここでは概要だけにします。

imai-factory.hatenablog.com

eDRX の本質は、とてもシンプルで

UE を、できるだけ長く眠らせる

ということになります。数十秒、もしくは数十分間にわたり UE は無線を完全にオフにし、基地局の声を一切聞かないわけです。ここで、さっきまでの話を思い出してみてみましょう。

VoLTE のように連続的に通信しているなら、
同期し続けやすそうです。

でも eDRX は、通信していない時間の方が圧倒的に長い。
こちらの方が、よほどハードモードではないでしょうか。

eDRX/PSM 中の UE は、ネットワークから見ると 「返事をしない」「見えない」時間が長い。これでどうやって“再会”するんでしょうか?ms単位での精度での同期が求められるところに対してこんなに長い時間眠っていたら、当然ズレが発生します。


3. UEは誰と、どうやって「時間」を共有しているのか

わたしも実は今回調べてみてやっと理解できたのですが、UE は基地局と時刻同期していないのです。ここで言う「時刻同期していない」とは、NTP や GNSS のように 絶対時刻(wall-clock)を合わせているわけではない、という意味です。UE は、基地局の時間に「追従」しているのです。


3.1 まず、下りで「同じ拍」を作る(通常時)

基地局は周期的に目印となる信号を送信します。 UE はそれを検出し、フレーム境界やシンボル境界、周波数ズレを推定して、自分の受信タイミングを合わせます。

これは「時計を合わせる」というより、基地局のメトロノームに、UE が合わせに行くようなイメージです。こんなかんじ↓

図3:下り同期の基本(目印に追従して境界を推定する)

時間 →
gNB: |SSB|........|SSB|........|SSB|........ (周期的に目印を出す)
UE : ↑検出 ↑再検出 ↑追従し続ける

UEは「時計を合わせる」のではなく、
基地局の拍(フレーム境界)を推定して追従する。

3.2 上りはより難しい:Timing Advance

上りでは、UE と基地局の距離によって電波の到達時間が変わります。 そのまま送ると、gNB 側では「ズレて」受信されてしまいます。

そこで、基地局は UE に対して Timing Advance(TA) を指示し、
「これだけ早く送ってね」と調整させます。

UE が 10m 動くだけでも、電波の到達時間は変わります。
だから基地局は「ちょっと早く投げて」と指示して、受け取る側で揃うようにします。


3.3 ここまでの同期は「相対時間」の世界

ここまでの話をまとめると、

  • UE は絶対時刻を知らない
  • フレームやスロットという 相対的な進捗 に追従している
  • ズレたら補正できる前提で動いている

分散システム的に見ると、
これは論理クロックに制限時間がついた世界にも見えてきます。


ここまでが「通常時」の話(連続的に追従できる世界)

ここまでは、UE が基地局の電波をある程度連続的に観測できる世界の話でした。
下りで追従し、上りで補正し、ズレを検出できる前提が成り立っています。


ここからが「省電力時」の話(連続が途切れる世界)

eDRX や PSM が入ると、前提が崩れます。UE は眠ります。しかも、長く眠ります。 眠っている間は、基地局の目印を一切観測できません。そんな条件下においても再会をしなければならないわけです。


3.4 点ではなく「幅」で合意する(DRX / eDRX / PSM)

ここで、DRX / eDRX / PSM を到達可能性とタイマーの観点でまとめて眺めてみます。

以下の図は、UE が「到達可能(UE Reachable)」な時間と、 「到達不能(Not Reachable)」になる時間が、 どのタイマーで決まっているのかを一枚にしたものです。

図2:PSM / eDRX における到達可能性と「時間方向のブロードキャスト」

図の読み方

  • Active Timer(T3324) の間、UE はまだ「呼ばれるかもしれない」状態にあります
  • eDRX が有効な間、UE は eDRX Cycle Length の周期で起床し、その中の Paging Time Window だけ paging を監視します
  • PSM Cycle Timer(Extended T3412) の間、UE は原則として到達不能になり、満了時に TAU / pTAU のために起床します

IoT 向け省電力は間欠通信(そしてその間はモジュールを眠らせる)という戦略をとっているわけです。が、ここまで何度か語られているように、UEと基地局は高い精度の同期が求められるし、眠ったあとにそれをやるのはとても難しいのです。


3.5 「時間方向のブロードキャスト」

じゃあどうするの?というところで出てくるのが、この戦略です。

時間方向のブロードキャスト

これは 3GPP の正式用語ではありません。
Paging Time Window や paging repetition の設計を、
時間の軸で捉え直した呼び方です。

ネットワークは、「この瞬間に起きていろ」ではなくて

「この時間帯のどこかで起きていればよい」

という合意をします。

点を狙うのを諦めて、帯に向かって撒く、時間方向のブロードキャストしているかんじです。

点で同期できないなら、帯で合意する。 空間に撒くのがブロードキャストなら、時間に撒くのもまたブロードキャスト——というわけです。(ドヤ

図4:時間は「点」ではなく「帯」で合意される(Paging windowの直感)

時間 →
|<-------- paging window -------->|
NW(gNB): ---|================================|---
↑ ↑ ↑ ↑
(同じ内容を複数回送る:時間方向のブロードキャスト)

UE: ~~~~~~~ wake ~~~~~~~
↑
(この帯の中で拾えればOK)

3.6 幅は「誤差」ではなく「意図的な余白」

直感的には、時刻は正確なほどよいように思えます。 しかし省電力の世界では、正確さだけでは勝てません。

  • クロックはドリフトする
  • 起床には揺らぎがある
  • 無線は不安定

だからセルラーは、

時間が不正確であることを前提に、幅を設計する

という選択をしています。つまりスマホも IoT も、別々のやり方で「同期し続ける」努力をしている。 そして省電力になるほど、その努力は“点”から“幅”へと変質していきます。


4. あれ?これって分散システムっぽくない?

—— 「比較」ではなく、思い出してみる

ここまで来ると、分散システムを触ったことのある人なら、
いくつかの単語が頭をよぎるかもしれません。

ここからは「セルラーはこれと同じだ!」と断言したいわけではなく、
むしろ逆で、

「自分たちが普段使う概念で見たら、こういう風に見えるかも」

という、連想を促すパートです。

分散システムでは「時計が信用できない」ことから出発して、
論理時計、期限付きの権利、そして“幅のある時間”へと
道具立てが増えていきました。

セルラーも、驚くほど似た順序で「時間」と格闘しているように見えます。


4.1 Vector Clock:共通の絶対時計がなくても「進捗」を揃える

分散システムでは、完全に正しい時刻を共有するのは難しい。
だから、まずは因果関係や進捗を表すために 論理時計 を使います。

Vector Clock が面白いのは、
絶対時刻ではなく「因果(happens-before)」で
世界を並べ替えるところです。

セルラーも、絶対時刻を合わせていません。
代わりに「いまどのフレーム/スロットにいるか」という進捗に追従しています。

ここで思うわけですが、

これ、制限時間付きの Vector Clock みたいなイメージがしませんか?

ただし分散システムと違うのは、セルラーには「待つ」という選択肢がほぼ無いことです。

分散システムでは「ちょっと待って順序を揃える」ことができます。
でもセルラーの無線では、時間そのものが共有資源です。

ある UE が「少し待ってから送ろう」とすると、

  • 本来そのスロットを使う別の UE と衝突する
  • 基地局側では「何も来ない」「変な信号が来た」と解釈される

フレーム境界を外す、スロットを外す。
それは単に遅れるのではなく、プロトコル違反に近い状態です。

結果としてユーザー体験では、

  • 音声が一瞬途切れる
  • 「プツッ」というノイズが入る
  • 最悪の場合、通話が切れる

という形で現れます。

だからセルラーでは、

外した側が悪い
期限切れは即座に起こる

という、非常に厳しいリアルタイム制約の世界になります。


4.2 Lease:短命すぎる「送信権」

分散システムで Lease というと、

  • 「一定時間だけ資源を占有してよい」
  • 「期限切れしたら権利は失効する」

という感覚があると思います。

セルラーのスケジューリングは、もっと強権的です。
gNB が「このタイミングで送れ」と命令し、UE はそれに従います。

でも見方を変えると、こうも言えます。

スロット割当は、「この瞬間だけ有効な Lease」を配っているようにも見える。

この Lease が失効すると、

  • そのスロットで送ったデータは、基本的に無視される
  • 再送するには、新しいスケジュール(新しい Lease)が必要になる

音声通話でこれが起きると、

  • 一瞬の無音
  • 遅れて聞こえる声
  • 会話のテンポが崩れる

といった形で UX に現れます。

期限は短すぎます。
ミリ秒どころか、もっと細かい単位で失効します。

そして eDRX / PSM は、その Lease を「長く持ちたい」という要求ではなく、
むしろ

「そもそも Lease を受け取らない時間を作りたい」

という欲望から来ているのが面白いところです。

なぜなら、受け取る=起きる=電池が減るから。
だから IoT は「権利を得ること」より「権利を無視できること」を選びます。


4.3 TrueTime:「時間は点ではなく幅」

ここまでタイムセンシティブなシステムを見ると、 (もともと Hadoop や Spark をやっていたエンジニアのわたしとしては) TrueTime が頭に浮かんできます。

TrueTime は

「今がいつか」を、一点ではなく区間(幅)で表現する

完全に正しい時刻が共有できないことを前提に、 不確実性を ε のような幅として扱います。

ここで重要なのは、ε は誤差ではなく、

「この範囲のどこかに今がある」という宣言

だということです。セルラーも、同じように「幅」を扱っています。 ただし、選んだ戦略は違います。

TrueTime は、整合性のために 待つのに対して、 セルラーは、待てないので 投げる。

TrueTime が「時間の不確実性を待つことで解決する」技術なら、 eDRX は「時間の不確実性を前提に投げ続ける」技術だと言えるかもしれません。

図5:TrueTimeは「待つ」、セルラーは「投げる」

TrueTime:
now = [ earliest -------------------- latest ]
↑
wait(不確実性が減るまで待つ)

Cellular:
paging window = [ ----------- width ----------- ]
↑↑↑↑
ばら撒く

4.4 まとめ

セルラーとか、「電話」みたいなキーワードで話してしまうと、 普段わたしたちのインフラ過ぎて「自明のもの」として扱ってしまいがちです(わたしがそうです)。

でも実は、「数十億台のデバイスとネットワークが、 ミリ秒以下の締切の中で、ズレながらも足並みを揃えている」 という、むちゃくちゃディープでテックな世界の上で成り立っています。

グローバルなネットワーク全体で完璧に同期しているわけではありません。 PHY、RRC、NAS…とレイヤを分け、 ローカルに壊れても戻れるようにして、分散性とローカルなレジリエンスを確保している。

さらに、IoTデバイスのようなスリープをするデバイスたちのUEは「点」ではなく「幅」で合意して、 時間方向に情報をばら撒いて、再会できるようにしている。

これ、めっちゃ面白くないですか?ちょっと入社してもいいかな?とおもったかたはぜひご連絡ください!!!!

iSIM, BG773, eDRX, HLCom

なんのこっちゃ?と思いますよねこのタイトル。この記事はSORACOM Advent Calendar 2024の12/23分の記事です。

 

わたしが現在働いている株式会社ソラコムでは、iSIMを搭載(?)したLPWAモジュールの開発キットとして下記のBG773A-GL-TE-B(iSIM)というキットを販売しています。

soracom.jp

今回はこのキットを使って「iSIM搭載のLPWAモジュールでeDRXとHLComを試してみた」という記事です。

 

まだ、なんのこっちゃ?ですよね。順番に説明してまいります。

iSIMとは

まずiSIMとは、Integrated SIMの略称で、SIM(厳密にはSIMが持つプロファイルデータ)がセルラーモジュール(下記の画像ではセルラーSoC)のなかに焼き込まれているものです。つまり、セルラーモジュールにIntegratedなSIMなのです。SIMのプロファイルデータはモジュール内のセキュア領域に安全に書き込まれています。これを利用するメリットとしてはSIMを物理的なフットプリントを減らすことができる、また物流をひとつ(SIMの仕入れ)を減らすことができるという点があります。

iSIMとは? - IoTプラットフォームSORACOM

画像出典: iSIMとは?技術革新とビジネスインパクト

 

BG773A-GLとは

次にBG773A-GLについてですが、これはセルラーモジュールの商品名です。Quectelが製造販売しているモジュールで、前述のように、ソラコムではこれにiSIMを搭載した評価キットであるBG773A-GL-TE-B(iSIM)という製品を販売しております。docomoでLTE-Mが利用できるplan01siSIMが載った状態で出荷されますので、手元で火をいれるだけで以下のようにIMSIが見えるのです!!!!・・・・伝わりにくいですね、この感動w

なお、BG773A-GL自体はiSIM専用のセルラーモジュールというわけではなく、カードSIMやeSIMでも利用可能です。ソラコムのお客様でもいくつかの大規模な利用実績があります。

eDRXとHLCom

eDRXとは省電力性能を保ちながらリアルタイムな双方向通信を実現するための技術です。わたしたちが普段つかっているスマホで多く利用されているようなLTEモジュールでは、(非常にいろいろ端折ってますが)1.28秒周期で無線部(厳密にはRRCと呼ばれます)をアクティブにし、自分宛ての通信がないかを確認する(厳密には電波を待ち受ける)ような仕組みになっています。

これは無線による電力消費を抑えるための仕組みでDRX(Discontinuous Reception)と呼ばれています。セルラーモジュールはこのように定期的に無線部を起こして自分宛ての通信を確認し、必要がなければまた1.28秒スリープするということをしています。私の感覚値ですが、無線部がアクティブ、かつ電波を送信するような状態だとLTEのセルラーモジュールは400mAhくらいの電力を消費します。スマホのバッテリーの容量が3000mAhとか4000mAhが標準的な数字であることを考えると、LTEがどれだけ電力食いなのかがイメージつくと思います。

eDRXはこのDRXを拡張(extended)した仕様で、前述のスリープ周期(eDRX周期と呼ぶことにします)を最大で43分まで伸ばすことができる仕様です。IoTデバイスは常に通信をし続けるようなものばかりではないこと、バッテリーで数年以上の動作を求められるようなユースケースも多いことからこういった仕様が用意されました。

なお、この周期はIoTデバイス(UE)側からのリクエストがあればいつでもリセットされ、ただちに無線はアクティブになり通信を発することができます。一方、サーバー側からの通信についてはeDRX周期の合間のスリープ中は待たされることになります。

アプリケーションレイヤで考えてみると、例えばサーバーからIoTデバイスにTCPセッションを張ろうとして43分も待たされるとどうなるでしょうか?もちろん、タイムアウトしてしまいますよね。そこで登場してくるのがHLCom(High Latency Com- munication)です。これは、モバイルキャリア(今回のソラコムのplan01sの文脈でいうと例えばdocomo)が提供しているMMEとSGWと呼ばれる設備が連携してIoTデバイス向けのIPパケットをバッファしてくれる仕組みです。サーバーからのSynパケットこの仕組みによってバッファされ、eDRX周期に合わせてIoTデバイスに配信されます。つまり、サーバー側で動作しているTCPクライアントに十分に長いタイムアウトを設定していればソケットを作成することができるということになります。

なお、どれだけの期間や容量、パケットをバッファしてくれるのかという点、またそもそもHLComが提供されるかどうかは各モバイルキャリアに依存しますのでご注意ください。また、多くの場合その仕様は公開や保証はされていないことにも注意が必要です。Just Do It!

今回やったこと

前置きが長くなりました。今回はiSIM入りのBG773A-GL(以下、BG773と略します)でeDRX/HLComの動作確認をしてみた、というお話です。

VPG Type-F2を使って以下のような構成を作り、EC2からBG773に対してPingやソケット通信を試みました。

eDRXを設定する

まずはBG773側を動作確認しながらeDRXの設定をしていきます。以下は紙芝居的にその様子を再現します。

まずは基地局にアタッチしたうえでIPアドレスが割り当てられていることを確認します。使用するコマンドはAT+CEREG?とAT+CGDCONT?です。ATコマンドの説明はここでは割愛させてもらいますが、以下のように問題ないことを確認しました。

次はいよいよeDRXの設定です。ここではAT+CEDRXSというコマンドを使います。設定自体はQuectelが提供しているApplication Noteを参考にしました。下記のコマンドの意味は「LTE-MでeDRXを有効にする。eDRX周期を163.84秒。ネットワーク側がどんな値を受け入れたのかの結果も出力する」というものです。コマンド実行成否を表すOKが表示されたあとしばらくすると"1001(163.84秒)"というeDRX設定値要求に対して"1001"を受け入れた、というような意味合いのメッセージが表示されまました(+CEDRXPから始まる行がそれです)。やった!これでeDRXが設定されました。

EC2からまずはPingしてみる

では早速実験です。EC2からタイムアウト値を100秒にしたPingをBG773に対して送信してみます。すると以下のような結果になりました。まず

注目してほしいのは各icmp echo replyのseqと、最後のstatisticsのpacket lossです。seqが欠けていないこと、またpacket lossが0であることが読み取れると思います。

一方、各icmp echo replyのtime(所要時間)を見るとどうでしょうか?最初の1発は約45秒かかっていることが確認できます。そこからだんだん所要時間が小さくなり、最終的には300ms前後に落ち着きます。

これはどういう意味でしょうか?

eDRX周期の合間に送信されたパケットはHLComによってバッファされて待たされ、BG773がAvailableな状態になったら配信され、そしてEcho replyが返ってきているということが言えます。packet lossは0であることを先に確認していますので、あくまで待たされただけで欠けていない、とも確認できます。シークエンス番号でいうと45番までがHLComによってバッファされたと言えそうです。それ以降は300ms前後で安定しているので、BG773がアクティブに動作しつづけている(連続的にEcho Replyを送信しているので無線部はそのリクエストを受けるたびにeDRX周期をリセットしている)状態になっていると言えそうです。

EC2からTCPソケットを作成してみる

つぎにEC2からncを使ってソケットを張ってみます。ひじょーーーーうに分かりづらいデモなのですが左側のターミナルがEC2、右側がBG773です。ncコマンドを発行したあと、約9秒後に右側のターミナルが反応しています。この動画は8倍速にしているので72秒ほどまたされたあとにソケットが作成されたということが言えます。めでたい!

youtu.be

まとめ

iSIM入りのBG773A-GL(以下、BG773と略します)でeDRX/HLComの動作確認をしてみた、というお話でした!

Audibleで宮部みゆきの『おそろし』を聞いた

最近のランニングのおともにこれを聞いていた。とてもよかった。

www.audible.co.jp

登場人物の感情表現や情景の描写などがとても豊かであること、そしてそれを見事に演じている波乃りんさんの朗読がとても高いレベルで(って、なんの評論家だよ。すいません)融合していて、物語はもちろんのこと、朗読?オーディオブック?ならではの楽しさが体験できた。

 

これまでにもいちど同じような体験をしたのは吉田修一の『国宝』。歌舞伎役者の尾上菊之助が朗読?演ずる?歌舞伎の劇中劇は圧巻だった。そして、ラストの恐ろしさというか美しさといったら・・・鳥肌モノでした。

 

ちなみにAudible、わたしはとても気に入っていて、ランニングのお供にしているのだけど、結構ひとを選ぶと思う。ランニングや運転など「他に何もできない」みたいな状態が長時間続くような生活習慣を持っていないとなかなかハマれないような気がする。ランニング中に話がいいところまでいったので帰ってきてお風呂に入りながら、そして昼寝しながら聞こうとしても、あんまり集中できないんだよね。

 

Theo Parrish Live @ Sonar Festival - 2008

長い距離のランニングをするときのお供にすることの多いTheo Parrish。これは初めて聞いたけど、時代的に2009のtaico clubでのセットに似ていて非常に淡々としていてよいかんじ。海風を浴びながらダラダラ踊りたい。

www.mixcloud.com

SORACOM JunctionとeBPFでパケットキャプチャしてISPのようにトラフィック分析しよう(立志編)

今日はeBPFについて書いてみようと思います。

 

いくつかのDisclaimar

  • これはSORACOM Adevent Calendar 2023の記事です
  • わたしはこの記事の執筆現在、株式会社ソラコムで働いていますが、このブログ記事は会社を代表する意見やコメントではありません。いちユーザーとしてこんな感じのことをSORACOM使ってやってみようぜという記事です。

この記事はSORACOM JunctionとeBPF使うと、まるでISPのように、自分が管理するSIMトラフィック解析ができるよ!とドヤ顔で話すための試行錯誤とその失敗(いまのところ)の軌跡です。

eBPFってなに?

さて本題に戻ります。みなさま、eBPFってご存知ですか?eBPFとはカーネルの様々なイベント(例えばSyscall、カーネル内の関数が呼び出されたとき、パケットがNICに到達したとき)にフックして、任意のバイトコードを実行できるサンドボックスです。Kernelを直接変更したり、Kernelモジュールを書いたりすることなく、安全にKernelを拡張することができることが特徴です。代表的な事例としてはトレーシングやロードバランサー、DDoS Mitigationなどがあげられます。

例えばCloudflareはエッジサーバー内において、DDoS対策のためにルーターから届く毎秒2000万のパケットから意味のある10万のパケットのみをフィルタしてアプリケーションに届ける、というパイプラインを構築しています。毎秒2000万ですよ?すごくないですか?

 

なんでこんなに速度が出るかというと、カーネル内で任意のコードを(安全に)動かせるため、ユーザーランドへのメモリコピーやコンテキストスイッチングを避けることができます。また、例えばXDPというフックポイントを利用するとOSのネットワークスタックより前に処理を差し込めたり、NIC内でその処理を実行したりすることもできてしまいます。

下の画像はXDPとOSのネットワークスタックについての関係性について説明している図で、XDPのフックポイント(XDP eBPF)が左下のパケット到着直後に存在しているのが見て取れると思います。例えばここでeBPFプログラム内でXDP_DROPという結果を返すと、このタイミングでパケットを捨てることができてしまうのです。すごくないですか?

画像出典: Express Data Path - Wikipedia

 

Cloudflareがそれをどうやって活用しているかについては下記のスライドとブログを読んでいただくとどんなことをやっているのか、またそれをどうやって実装しているのかというのがイメージ湧くと思います。とてもおもしろいのでぜひ。

blog.cloudflare.com

speakerdeck.com

 

わたしとeBPF

わたしがeBPFに興味を持ったのは、SORACOMでのトラフィック分析、より具体的に言えばゼロレーティングのためのトラフィック分析に利用できないか?というのがきっかけです。

 

ゼロレーティングとは、例えば「このSIMは月額980円でxxGB利用可能です!しかもLINEでの通信利用分は無料!」というアレです。アレを実現するためには、自分が管理するトラフィックについて、どことどのくらいの量の通信をしたのか、ということを把握できる必要があります。

 

SORACOMには、SORACOM Junctionというサービスがあり、自分のアカウント内のすべてのSIMの通信をミラーして任意の宛先に送信することができます。それを受け取って解析、一番シンプルには宛先ドメインごとに通信量集計をすればゼロレーティングが実現できそうですよね!

 

画像出典 - SORACOM Junction - SORACOM

 

ゼロレーティングとかDPI(Deep Packet Inspection)と呼ばれるような技術分野は、少なくとも私が知る限りはまだまだプロプライエタリな製品を使う以外の選択肢がなく、自分で実装したりするような事例というのは少ないのかなと思っています。そういう背景もあって、普段から「ゼロレーティング、自分で実装できたらかっこいいよな。ひとつのチャレンジテーマとして持っておこう」と思っていました。

 

そんななか、たまたまRustの勉強をしているときに下記の本を読んでいる中で出会った「Rustでパケットキャプチャ」という章において、Rustを使えばSocket APIよりも低レイヤなIPパケットが簡単に扱えることを知りました(すいません、ネットワークプロバイダのSORACOMのSAとしてそんなことも知らなかったのかよ、というツッコミは甘んじて受けます)。この本の第2章はpnetというクレートを使って、データリンク層から取り出したフレームを扱うという演習になっています。

cha-shu00.hatenablog.com

 

そして、Rustのpnetで遊んでいるうちに「よりパフォーマンスを出すパケットキャプチャプログラムを書くにはどうすればいいだろう?」としらべているなかで出会ったのがeBPFだったというわけです。当時Rustを触っていたということもあり、AYAというRust向けeBPFライブラリを使ってeBPFでパケットキャプチャをやってみたという話をSORACOM UGで発表したりしました。(ほんとうちょっと触っただけ)

speakerdeck.com

 

やってみた - SORACOM Junction + eBPF + BCCでパケットキャプチャ

今回あらためて、BCCというツールセットと、PythonとCを使って以下のようなデモプログラムを実装してみました。パケットはもちろんSORACOM Junctionでミラーリングした実際の自分のSIMの通信を利用します。全体像としてはこんなかんじ。

パケットを受け取るEC2の中はこんな感じになりました。

前回SORACOM UGで発表した時点ではAYAを使っていましたが、より情報の多いBCCのほうが書きやすかったとうこともあり、今回はこちらを使いました。

 

BCCとは、eBPFプログラムを実装、実行するためのツール群でこれを使うとPythonやluaでフロントエンド(ユーザーランドプログラム)を書けるようになります。例えば、eth0で受け取ったパケットをXDPのところですべて破棄するプログラムは以下のように書けます。これなら「おれも書けるな」という気持ちになりませんか?

現状と今後

ということで書き始めるところまではたどり着いたんですが、このブログを書いている朝まで動いていたでもプログラムが「何もしていないのに壊れてしまった」のです・・・本当はInfluxdbやAmazon Timestreamに入れたところのデモ画面くらいまでたどり着きたかったのですが・・・XDPにプログラムをアタッチするところがどうやらうまくいかなくなってしまって、いまはlibbpfやBCCそのもののコードをちょっと調べているところです。より低レイヤな部分を覗くせっかくの機会だと思って。。笑

 

ということで実際の動いているデモは冬休みの宿題としてまた新たにブログ記事にまとめられたらと思います。

 

SORACOM JunctionとeBPF使うと、まるでISPのようにトラフィック解析ができるよ!とドヤ顔で言えるようになる日までもう少しがんばります。

セルラーモデムの謎を追う その1 :導入編

みなさん、こういうデバイス使ってIoTしたことありますか?

soracom.jp

これはUSBドングルタイプのセルラーモデムで、例えばラズパイやPC、Macに接続することでそれらのコンピューターにセルラー通信上でのIP通信を実現可能にしてくれます。使ったことある方はわかると思うんですが、このデバイスはpppインターフェイスとしてOSに認識されます。が、実はSORACOMはppp方式での接続を提供していません。このことは下記のドキュメントのPDP Typeが「IP」となっていることからわかります。PDP Typeとはパケット接続の認証方式のことで、IPもしくはPPPという2つの方式があり、SORACOMはIP方式のみを採用しています。他の多くのキャリアも同様です。

参照元: SORACOM Air for セルラーの利用を始める: STEP 3: デバイスを設定する (APN 設定 / ローミング設定) | SORACOM の利用を始める | ソラコムユーザーサイト - SORACOM Users

となると、え?なんでpppインターフェイスが見えるの?となりますよね。疑問に思ったことありませんか?別に気にしなくても使えるんですが。

 

これについてはIIJの方が下記のブログ記事で解説してくださっていますが、実はppp通信しているのはOSとモデムの間だけだということがわかります。しかし、なぜこんな方式になっているのでしょうか?とか気になっちゃいますよね。

www.iij.ad.jp

 

他にも・・・ATコマンドでセルラーモデムを扱ったことあるひとはわかると思うんですが、モデムをラズパイに接続するとシリアルデバイスとして認識され、screenやcuコマンドを使ってASCIIベースの対話型インターフェイスを介してコマンドのやり取りができる状態で立ち上がってきます。ちなみにATコマンドってなに?って人はこちらのブログを読んでみてください。ざっくりいえば「モデムを制御したり情報を取得したりするためのもの」であり、IoTデバイスの入門書やキットでもよく「ATコマンドでセルラー通信をしてみましょう」というコーナーを見かけます。

bearmini.hatenablog.com

でもここで、実際のIP通信の際にはOSはどうやってモデムを扱ってるの?まさかATコマンド?みたいな疑問が湧いてきませんか?

 

これについてはLinux Documenation Projectのガイドによれば以下のような記載があります。ざっくり言えば「モデムはAT-commandモードとして起動し、ATDコマンドが発行されたタイミングからon-line dataモードと呼ばれる土管モードに入る」ということですね。

When the modem is first turned on it's in the command mode (also called terminal mode, idle state or AT-command mode). Anything sent to it from the PC is assumed to be an AT command and not data. Then if a dial command is sent to it (ATD...), it dials and connects to another modem. It's now in the on-line data mode (connected) and sends and receives data (such as Internet pages). In this mode, any AT command one trys to send it will not work but will be transmitted to the other modem instead. Except for the escape command. This is +++ with a minimum time delay both at the start and end. The time delay allows the modem to determine that it is likely a real escape and not just +++ in a file being transmitted.

 

ここまでわかってきたことを総合していくとLinuxやMacのようなOSたちは、モデムをon-line dataモードにしたうえでシリアルデバイスとして取り扱い、さらにそのうえにpppインターフェイスを作成し、自身のもつ通信スタックを用いて通信を行っているであろうことが想像できます。このブログでは「LinuxやMacでセルラーモデムを使ってIP通信が実現されている仕組み」の詳細にDive Deepしていきたいと思います。

 

ちなみにですが、ArduinoにはTinyGSMという著名なセルラー通信ライブラリがあります。

github.com

これを利用するとさまざまな通信モジュールにおいて非常に簡潔なコードでHTTP通信やMQTT通信が実現可能です。これも前述のLinuxやMacのように様々なモジュールを使って柔軟な通信を実現してくれるという意味ではとても似て見えるのですが(役割としてはとても良く似ている)、実は全く違う仕組みです。このライブラリは通信モジュールが持っている、通信用のATコマンドを利用して通信をする仕組みになっています。例えばQUECTELのモジュールはAT+QISENDというTCPでのデータ送信コマンドや、さらにはAT+QHTTPGET、AT+QHTTPPOSTといった高位の通信を行うためのコマンドも備えておりこれらを活用しています。つまり、TinyGSMの場合はモデム自身が持っている通信スタックを使っており、モデムとMCUはATコマンドでやりとりしている、ということになります。

 

次回以降は実際にいろいろ触ってみながらやっていきたいなと思います。最終的には自作のTCPスタックでモデムを使って通信、みたいなところまで行けたら最高だなと思いますが、さてどこまでいけるだろうか・・・

 

お楽しみに!