こんにちは。CTOの新井です。前回ご紹介したOprange Pi Zeroに続き、組み込み系の話を今回もご紹介しようと思います。
組み込みシステムのベースとなるマイコンやLinuxボードではメーカーが提供しているSDKやライブラリの中身を見てみるとレジスタの書き込みレベルまで見れるものも多く、ソフトウェアで実行した内容がハードウェアをどう動かしているかまで見えるものも珍しくありません。その反面、SDKの抽象度が低い事が多く、細かい例外処理等は基本的にSDKを使用する開発者が行うことが求められます。
それと同時に、組込みシステムでは高い信頼性が要求されます。現実世界に何らかの作用を及ぼすものなので基本的に代替品はありませんし、車などでは人命に関わることもあります。mornin’も指定した時間に動かなかったり、全然関係ない時間に動くようでは商品としての価値はありません。
そこで、今回は組み込みシステムを開発する上で信頼性のあるモジュールを設計するための方法の一つをご紹介致します。
ステートマシン図
プログラムを勉強したことがあれば一度は聞いたことがあるかと思いますが、ステートマシンとは、プログラムが入力等のイベントを受けたときにどういう状態に遷移するかを表現するための手法の一つです。詳しい説明はWikipediaに譲るとして、ここではmornin’のようにモータを時計回りまたは反時計回りに台形速度制御で動かすステートマシン図を例に考えてみましょう。
台形速度制御とは、一定の加速度である速度まで加速し、その速度まで到達してからは定速状態になり、停止する際に一定の加速度で減速する、という速度制御方法です。速度をグラフ化すると台形になるのでこのように呼ばれています。
早速この制御のステートマシン図を書いてみましょう。UML系の描画ソフトを使うのもいいのですが、個人的にはguiflowというツールが気に入っています。もともとはその名の通り画面遷移図を作成するためのものですが、後述するステートフルなシステムの表現に便利なのと、マルチプラットフォームなので重宝しています。
モータ制御モジュールのステートマシン図
前述のモータを台形速度制御する場合、モータの状態を表すものとしてはどんなものがあるか考えてみます。一般的なモータでは下記のような状態になると考えられます。
- モータが回っていない状態
- モータが時計回りに加速中
- モータが時計回りに定速回転中
- モータが時計回りに減速中
- モータが反時計回りに加速中
- モータが反時計回りに定速回転中
- モータが反時計回りに減速中
まずは時計周りにモータを動かし停止する、というところをUML風のステートマシン図のように表現してみます。
guiflowでの記述は下記のようになります。
UML用のツールではないのでやや違和感のある見た目ですが、モータが動き始めてから止まるまで、何となく可視化出来ました。
しかしながら、組み込みシステムへのリクエストは一般的なWebシステムへのリクエストとは異なり、
リクエストはいつ何時でも飛んでくるにもかかわらず、前回のリクエストの処理の状態によって処理を変えなければいけないステートフルなシステムであり、かつ長時間その状態が保持される可能性が高いという特徴があります。
こういったシステムをUMLのステートマシン図で表現するとステートマシン図を状態の数だけ分割したり、状態遷移の矢印にすごい量の文字情報を詰め込むこんだりと、あまり見やすくありません。そこでguiflowの表現を利用して、全ての情報を一つの図にまとめてみます。
組み込みシステム流のステートマシン図風の何か
早速ですが、完成した図を見てみましょう。
guiflowでの表記はこちら
一般的なステートマシン図とは異なり、起点にはモータを指定した方向へ回す2つのリクエストがあり、次にそれらのリクエストに応じて分岐した先で、すべての状態が羅列してあります。そしてここでそれぞれの状態においてどういった遷移をするかを矢印で表現し、その後は通常のステートマシン図と同様に、ステートが処理に応じてどのように遷移していくかが表現されています。
この表現のいいところは、このモータを制御するモジュールがどんな状態の遷移をするかと、状態遷移表のようにどの状態にどういったリクエストが来るとどう遷移するかの両方が見えるところです。
状態遷移表からステートマシン図を生成してくれるツールもありますが、矢印に文字情報をくっつける形になるとインデントがずれて見づらかったり、矢印が密になるとどの矢印に対して文字が付いているのか見づらかったりするのでイマイチでした。
それに対し、この方法だと表のように状態を表しそこから矢印を伸ばすので、個人的には遷移が直感的でわかりやすいと思っています。
また、モータの状態としては前述の7通りになりますが、正しい台形速度制御をする場合にはモジュールの状態としては減速が完了してから反転する、という状態を入れる必要があることが図から読み取れます。
このように、可視化することによってハードウェアの動きだけでなく、ソフトウェアとしてはどういう状態が必要なのか気づきやすくなります。
また、この図に表されている各状態における実際の処理、ある状態において処理が完了した際の状態の遷移、そして何らかのイベントが発生した際に各状態において状態の遷移が正しく行われるかをユニットテストとして実装すると、このモジュールが仕様どおり動いていることが保証できるようになるため、開発の見通しも非常に良くなります。
まとめ
信頼性の高いシステムを作るには設計が非常に重要になってきます。今回例に上げたモータ制御では例外は発生しませんが、各ステート時にリクエストが来た際にどういう応答を行うかを視覚的に網羅できるようになるため、例外処理などの漏れも起こりにくくなりますので、製品の信頼性を高めることができるようになります。
もちろん、動けばいい程度のプロトタイプを最速で作る段階からこういったものを用意する必要は基本的にはありませんが、ある程度製品としてどう動くかが決まった時点でこういった資料があるとアプリ側や機構設計側との動作フローの意識合わせも楽になりますので、ぜひお試しあれ。