United Statesからアクセスのようです。言語設定をEnglishに切り替えますか?
Switch to English site
Skip to main content

Raspberry piでアナログ信号をキャプチャしてみよう

以前のRaspberry Piで病院のベッドを監視するシステムへの挑戦では、結局のところデジタルセンサーであったため、湿度センサーをつなげるだけで十分だった。しかし、圧縮セル(コンプレッションセル)では、そんな簡単ではない。圧縮セルは、単純に「濡れている」や「乾いている」といった0もしくは1といった状態を観測するだけではない。その他にもRaspberry Piが定量できない様々な値を測定しているのだ。それではまず初めに、異なる信号の違いと、それらをどのように結合しているのかについて考えてみよう。

アナログ信号 vs.デジタル信号

入力信号はアナログもしくはデジタルである。アナログ信号は「連続した信号」であり、それらの値は常に変化するものだ。それと対称的に、デジタルデータは「連続していない信号」であり、その値は個々のステップで変化し、「高い」または「低い」で表現される。簡単に表現すると、それはライトのスイッチのON/OFFのようなものだと考えれば良いだろう。バルブを上下に操作することで明るさを調節できる調光スイッチはまさにアナログスイッチである。多くの標準的なON/OFFライトスイッチはデジタルだ。実はそこまで単純なわけではないが、基本的には上/下といった2種類で表現されるだろう。違いを簡単に理解するため、以下のグラフを見てほしい。

青がアナログ信号、赤がデジタル信号だ。アナログ信号からは、0.1, 0.11, 0.12, 0.12を読み取ることができる。アナログ信号からは、さらに細かい0.01,0.02,0.03,0.04の値も読み取ることができる。これを2進数の値として読み取ると、100(2)と表現されるのが分かるだろう。同じように、100(2)を超えているだろう0.1, 0.11, 0.12, 0.13の値はアナログ信号として読むことが可能だ。しかし、上の図におけるデジタル信号の場合、0(000), 1(001), ..., 7(111)といった8種類でしか表現することができない。これはアナログ信号の方がより正確なデータを得ることが可能であることを示している。しかし、同時にデジタル信号の方がより小さいデータサイズで多くの結果を保存することができるのだ。

私達は今デジタルの世界に生きており、私のPiはデジタルの女の子だ。そう、だから私のアナログな体重をPiが理解できるためのデジタル信号に変換する必要がある。ここで登場するのが救世主のアナログ – デジタル変換器(ADC; Analogue-to-Digital converter)だ!

コンバータ

ADCはアナログ信号をデジタル信号に変換する役割をもつ。先ほどアナログ信号が8種類の2進数で表現される例で説明したのを思い出してほしい。このように信号の差を簡単に表すようなデジタルの値を得るために、コンバータは内部で「魔法」を実行している。ここではその「骨」となる部分を紹介しよう。ADCをより深く見てみると、連続で観測しているわけではなく、周期的にサンプリングを行っている事がわかる。もう少し具体的に言うと、連続して入力されるアナログの値を定量し、デジタルの連続した値として出力しているのだ。ADCは、その帯域幅と信号対雑音比(SNR; Signal to noise ratio)が特徴だ。計測される値に最も大きな影響を与える要因の一つがADCのダイナミックレンジだ。これは識別可能な信号の最小値と最大値の比率を指しており、サンプリングの正確さや、分解可能な精度に大きな影響がある。分解可能な精度(分解能)とは、この場合分けることのできる種類の多さを示している。先の例では0(000)~7(111)の8種類だが、これをさらに細かい精度の0(000)~15(1111)のように15種類で表現することも可能ということだ。私達はこの種類の多さを『ビット』として表現することとする。ではビットが2であった場合はどうだろう。2ビットの場合00, 01, 10, 11の4種類で表現できる。簡単に0/1の2パターンが2つなので、2×2 (2^2) = 4パターンであることがわかる。このとき、入力される電圧のアナログ信号が0V ~ 20Vで変化する際には以下のように表現される。

2ビットでは4種類でしか表現できないため、1ビットで20を4で割った5Vずつしか表現することができない。ではさらにビットを増やして12ビットを考えてみよう。12ビットだと4096種類表現できるため、20を4096で割った4.8828152×10^(-3) = 0.0048828125V=4.88 mVずつ表現することができるのだ。メーカーの情報を確認すると、デジタル信号として12ビット、16ビット、64ビットで返すものが多く、これはワード長として知られている。一般的にワード長/ビット数が大きいほど良いが、これは必ずしもそうとは限らない。これらの数はビットの品質にはほとんど影響が無いと言われている。ともかく、明らかににビット数が大きくなるほど、キャプチャできる分解能が高くなり、より正確に元のアナログの値をデジタルで表現できることを理解していただけただろうか。私のアプリケーションで計測が十分正確に行われることを確認するため、今回は10ビットのシリアルADCを採用することにした。

MCP3008マイコン

このマイコンは8チャネル、10ビット分解能のチップであるため、2^10 = 1024種類の値で表現できる。今回の圧縮ロードセルの理想的な計測範囲は5~45kgだ。この範囲を10ビットで表現するため、(45 – 5)kg / 2014 = 0.039kg/bitの精度で表現できるようにすれば良い。他の素晴らしい特徴として、2.7~5.5Vの単電源動作電圧と1秒あたりのサンプリング率と互換性があることだ。2.7Vでは、一秒間に75回サンプリングできる。5.5Vだと一秒間に200回もサンプリングできるのだ。これらはADCの世界では多少低い値であるものの、私の中ではこれまでのものより生産的なものであり、今回私が必要とするものとしては十分だ。また、私はADCが動作するのに理想的な温度環境である-40~80度の環境にいる。-40~80度の間で使用できるということは、私はこのADCをロシアやオーストラリアで売ることができるのだ。これで儲けて20代で引退だって夢ではないかもしれない!

MCP3008マイコン/Raspberry Pi 回路

上の図は私がFritzingで作成したブレッドボードレイアウトの回路図である。アンプからの出力を利用し、圧縮セルの信号でLDRの変換を加速させる。LDR(Light Dependent Resistor)は光で変化する抵抗だ。そうして、Raspberry Piによって読まれた値がMCP3008によってアナログ信号がデジタル値へと変換、処理される。素晴らしい点の一つとして、このPiからの電力のみで問題がないことだ。3.3Vピン1だけで回路へ電力を供給できる。以前ある記事にてGeneral Purpose input/outputピン(GPIOピン)について見たことがあったため、私は複数の情報を必要なピンを使ってPiに送信できることを知っていた。特にこのチップはSPI(Serial Peripheral Interface bus)を利用いるため、私もSPIピンを利用しなければならない。このため、SPIピンであるPiのピン9-11を使って、情報が正しく受信・処理されることを確認した。以下が最終的に作成した回路の写真だ。

.

Piとチップ

さて、ここまででPiと回路はうまく接続することができた。次に、取得したセンサの値から、実際に何が起こっているのかを判断するための処理をコーディングする必要がある。今回使用している特定のチップは、SPIを使用している。つまり、4本のピンのみで、なおかつPythonのライブラリspidevを利用して簡単に通信できるのだ。今回のデモでは1秒に1回サンプルを取得することにした(そのためにはtimeライブラリも必要になることに注意してほしい)。コーディングした例は次の図を参照してほしい。もちろん、Python以外のプログラミング言語を利用も可能だ。その場合はSPI通信のためのライブラリを調べて利用が可能なはずである。

それでは詳しくソースコードについて解説しよう。

まず初めに変数を定義する必要がある。今回は1秒に1回データを取得するため、各測定の間に遅延を設ける必要がある。しかし、実際には長時間計測することもあるため、必要ないだろうが、今回はテストのために設けている。

また、入力がどのADCチャネルかを指定する。ここではチャネル0を指定している。 

次に、SPIオブジェクトを作成する。必要なweightの値をPiからSPIバスを介してチップから取得する。 spidevライブラリを利用することで、Piが全てのピンの割り当て情報を自動で処理してくれることだ。これによって、私達はピンの割り当てなどを知らずに値を取り出すことができるのだ。

さらに、ADCコンバータを読み取る関数を定義する必要がある(上の図ではreadadc関数として定義している)。まず、チャネルは0から7のいずれかになるはずだ。コード中では、それ以外の異常なチャネル数に場合は-1を返すようにしている。使用しているチャネル番号が正しければ、トランザクションのSPIから値を読み取り、値を返す。メインのwhileループでは、ADCを読み取って、遅延後に再度計測する。

最後のコード中のprint文中の%dは、10進数の値を返すことを意味している。その後、回路を接続して、アナログ信号をADCに送信し、デジタル値がPiに戻り、コマンドラインへと出力される。

プログラムを実行し、手を振ってLDRに入る光の量を変化させると、それに伴い出力されるグラフが変化するはずだ。これでアナログをデジタルに変換し、様々な計測に適用可能になった。

次に何をしよう?

私の究極的な目的は、床ずれ予防を通じてNHS(国民保険サービス)にかかる費用を減らすための装置を作ることだ。これにより、患者の病院生活を快適にし、看護師の仕事を軽減させるのだ。この次のステップは、圧縮セルからの信号を増幅し、ADCの入力とすることで患者の体重の読み取りだ。以前投稿した水分センサーと組み合わせ、最終的に患者の失禁状態を検知し、その不快感の改善や看護婦の仕事の軽減などにつなげることだ。今、私がすべきことは『全てを組み合わせること』だ。私はこれをまさに今、始めたいと思っている!

I Graduated from the University of Bradford with a degree in Chemistry and Forensic Science and currently I am studying towards a HND in Electronic and Electrical Engineering while interning at AB Open.