今回のテーマは「Raspberry Piで作る温度計」です。
Raspberry Piと温度センサ(BME280)、OLEDディスプレイ(SSD1306)を使って温度、湿度、気圧の表示をしてみます。
本シリーズでは、UMLを用いて設計をしていきます。
実際のUMLの使い方を知りたいという方はぜひ見ていただけたらと思います。
本編はシステム設計、ソフトウェア設計、実装編の3つのステップで構成されています。
とにかくまずはモノを作りたいという方には第3回から見ていただくでも問題ありません。
温度計のシステム設計をします。
Raspberry Pi、温度センサ、ディスプレイといった部品間でどういったデータをやりとりするか、制御の順序どうすかといったシステムレベルの設計を行います。
Raspberry Piのソフトウェア設計を行います。第1回のシステム設計の結果を元に、具体的にどういったソフトウェアモジュールを作成するかという詳細設計のフェーズになります。
Raspberry Piのセットアップを行い、C言語でプログラムを実装して部品を動かしていきます。
それではシステム設計編、いってみましょう。
温度計システムの構成
今回は、Raspberry Piを使って温度・湿度・気圧を表示してくれるシステムを作りたいと思います。
一般的に、組み込みシステムの基本構成はシステムの頭脳となるCPUと、センサ、HMI(Human Machine Interface)、アクチュエーター(駆動部品)といった部品で構成することが多いです。
今回のテーマでは、頭脳に当たるマイコンはRaspberry Pi、温度センサはBME280、ディスプレイはSSD1306というOLEDディスプレイを使用したいと思います。
部品 | 部品名 | 役割 |
---|---|---|
マイコン | Raspberry Pi 3 Model B ※他のモデルでも問題ありません | システムの頭脳。部品の制御を行う部品 |
温度センサ | BME280 | 温度・湿度・気圧を計測する部品 |
ディスプレイ | SSD1306 | 取得した情報をユーザーに表示する部品 |
HW構成は以下のとおりです。
BME280とSSD1306は、I2Cという通信バスでマイコンと通信を行います。
マイコンはBME280とSSD1306のアドレスを指定することで通信を行います。
配線図にすると以下の通りです。
BME280とSSD1306がI2Cバスを共有しているところがミソです。
温度計システムのデータの流れ(データフロー)
今回のシステムの登場人物はRaspberry Piと、温度センサ(BME280)、ディスプレイ(SSD1306)です。
これらの部品の間で、どういうデータをやりとりするか整理していきましょう。
このシステムはかなりシンプルなので、既に頭の中で思い描けている方もいると思いますが、明示的に表現してみましょう。
ここでは、UMLのアクティビティ図を使ってデータフローを表現してみます。
部品ごとにレーンを作成し、部品から部品へ何のデータが流れるか、部品はどういう機能を実行するかを表現しています。
まず、温度センサで温度計測を行い、取得した温度がRaspberry Piに渡されます。Raspberry Piは取得した温度を元に、画面に表示する描画データを作成します。最後に、描画データがディスプレイに送られ、画面が更新されます。
具体的には制御用のコマンドなど様々なデータのやりとりが発生しますが、ここでは表現していません。
まずは大枠で各部品の責務を捉えることで、開発ボリュームが見えてきます。
設計のコツとして、まずは大枠を捉えるために抽象的なレベルで検討することがポイントです。
いきなり細かいところから始めてしまうと、大事なポイントを見落とす可能性があります。
まずは俯瞰して大きな目線で捉えることが必要であり、丁度いい抽象度で検討できるか、が設計者の腕の見せどころでもあります。
データフローから、大きく分けて2つのポイントに着目して設計すると良さそうです。
1つは温度センサの制御、2つ目はディスプレイの制御です。
次の章では、この2つのアイテムをベースに振る舞いを検討していきます。
温度計システムの振る舞い(制御フロー)
温度センサ(BME280)の制御
温度センサのBME280は、コマンドを送ることで温度の計測や、計測したデータの読み出しを行います。
BME280には周期的に計測を行うモードも存在しますが、今回は計測実施コマンドを送ったタイミングで1回計測を行うイベントドリブンのモードで動作させます(Forced Mode)
上図はUMLのシーケンス図ですが、登場人物達のやりとりを時系列に表現した図になります。
上から下方向に時間の経過を表しており、各線をライフラインと呼びます。
横方向に伸びる矢印をメッセージと言いますが、
メッセージは「相手が提供している機能を呼び出す」ことを表現しています。
つまり上の図の最初のメッセージでは、「Raspberry PiはBME280が提供する”温度計測実施”という機能を呼び出す」ということを表現しています。
プログラミングでいえば、相手が提供している関数を呼び出す、ということです。
よくある勘違いとして、メッセージという名前から、送るデータが書かれていると思いがちですが間違いです。
「データを送る」のではなく、「相手の機能を呼び出す」が正解です。
下に間違い例を書いてみました。これでは「Raspberry Piが温度計測実施コマンドを送る」 ように見えてしまいますがNGです。
シーケンス図はあくまで制御フロー(誰がどの機能を呼び出すか)であって、データフロー(誰が何のデータを送るか)ではないのです。
ディスプレイ(SSD1306)の制御
OLEDディスプレイのSSD1306は、128x64pixの画素数を持ったディスプレイです。
内部に128x64pix分のメモリを持っており、ディスプレイにはメモリから読み出されたデータが描画されます。
メモリを書き換えてあげることで好きな画面を描くことができます。
Raspberry Piが画面メモリの更新を行うと、ディスプレイの表示が更新されます。
SSD1306は周期的に画面メモリを読み出して描画を行うので、書き換えたところから反映されていきます。
シーケンス図で表現すると下記の通りです。
ここで、「par」と「loop」という箱が出てきましたが、それぞれ並列処理(パラレル)、繰り返し(ループ)を表しています。
この箱は複合フラグメントと呼ばれ、ループや条件分岐を表現することができます。
上のシーケンス図では、SSD1306は画面描画と画面メモリ更新(描画データを受信してメモリを書き換える)を並列で行っており、画面描画は繰り返し実施されています。
Raspberry Piから画面メモリ更新がされると、並列で行っている画面描画で画面が更新されることがイメージできると思います。
システムとしての振る舞い
温度センサ(BME280)、ディスプレイ(SSD1306)の振る舞いを押さえた上で、システムとしての振る舞いを見ていきましょう。
基本的には①温度の計測、②画面更新、この2つを繰り返すことで温度をリアルタイムで表示するシステムが作れるはずです。
シーケンス図で表現すると下記のとおりです。
Raspberry Piは、温度計測実施をコールし、計測した温度を読み出し、読みだした温度を元に描画データを生成してディスプレイの画面メモリ更新を行います。
最後に
いかがでしたでしょうか。
システムレベルの動作イメージができましたでしょうか。
今回作成したシーケンスを元に、次回、Raspberry Piのソフトウェア設計をしていきましょう。
コメント