.NET対応組み込みデバイス「Netduino」入門(3)
Netduinoアナログ入力の基本(温度センサー活用)
Lチカができたら、アナログ入力を使ってみよう。温度センサーの値をNetduinoで取得するサンプルを作成し、アナログ入力の基礎を説明する。
環境センサーはアナログ入力を使え
前回で、基本的な回路の組み方とアプリの組み方を解説した。
今回は、Netduinoの入出力機能の中からアナログ入力について取り上げる。例えば気温センサー(=温度センサー)などから値を取得するときには必須の入力方法だ。
Netduinoのアナログ入力
Netduinoのボード右下にある6ピンがアナログ入力だ(図1)。このアナログ入力には、0~3.3vの電圧を入力できる。
今回のサンプルでは、このアナログ入力の0番ピンに温度センサーの値を入力する。
温度センサーについて
温度センサーにはいろいろあるが、今回は入手のしやすさ、測定できる温度範囲の広さ、必要な回路が単純なことから、LM61CIZ(図2)を使う。
LM61CIZは、ナショナル セミコンダクター社(現在はテキサス・インスツルメンツ社の一部門として吸収合併されている)の温度センサーだ。そのためか、製品データシートなどを見ると表紙こそテキサス・インスツルメンツ社だが、中のページのヘッダーには「ナショナル セミコンダクター」と記載されている。
LM61CIZの性能としては、測定レンジは-30~100℃、測定誤差の最大値は±4℃(25℃では±3℃)の精度がある。また、待機時消費電力は最大125μA(25℃時)であり自己発熱は0.2℃以下に抑えられているので、自己発熱で回りを温めてしまうことによる測定誤差が生じたりはしない。
より高い測定精度が必要なときには、LM35DZなどを使うとよいだろう。LM35DZであれば測定レンジ-55~150℃、測定誤差の最大値は±0.75℃(25℃では±0.5℃)、待機時消費電力は最大60μA(25℃時)で自己発熱は0.1℃以下が可能だ。しかし、氷点下を測りたいときはマイナス電源が必要になるなど回路が複雑になるので、今回は採用を見送った。
ただし、「回路が複雑になる」といっても、今回取り上げるLM61CIZを使った回路でLM35DZに差し替えるだけでも、2~150℃の範囲であれば測定できる。アプリ側のコードも多少相違はあるが、基本は一緒なので、LM35DZを購入してサンプルコードを試すことも可能だ。相違点についてはコード解説時に説明する。
Netduino+LM61CIZのハード構成
LM61CIZの物理仕様
LM61CIZ(LM60BIZも同様)は3本の端子(これを「足」と呼ぶ)がある。それぞれの役目は、LM61CIZのデータシートに記載がある(図3)。
図3は、下からLM61CIZを見たときの図だ。よって平らな面を正面にして足を下にしたときに向かって左から電源(+2.7~+10V)、測定値出力(300~1600mV)、GND(0V)となる。
よって、LM61CIZとNetduinoを接続するときには、左足をNetduinoの5Vピン、真ん中の足をアナログ入力の0番ピン、右足をGNDに接続すればよい。もちろん5Vピンではなく3.3Vピンでもよいが、LM35DZの電源電圧が+4~+30V
であるため、回路の共通化という意味もあり5Vピンに接続する。
LM61CIZ接続回路図
図4のLM61CIZ接続回路図を見ると、今までの説明にはない「0.1μF(100nF)のコンデンサー」が登場する。これは電源用パスコン(=バイパスコンデンサー)だ。
IC(集積回路)は、動作するときに電流が微量ではあるが変化する。この変化を緩和しないと、供給される電圧が一時的に変化してしまう。そこで、電圧が追いつくまでのタイムラグを埋めるためにパスコンを配置する。パスコンは、通常は充電を行い(電気をためておき)、消費電流が増えたときに放電して電圧の低下を防止する。このようにICごとにパスコンを入れることで、回路全体の動作が安定する。また同様に微弱な変化である電源ノイズのフィルターにもなる。
今回の実装で使用したパスコンの詳細仕様は、50V0.1μFのセラミックコンデンサー(同様のものを購入するならこちら)である。
ブレッドボード実装
回路図を基にしてブレッドボードに部品を配置する。
ブレッドボードのそれぞれの穴には、「アルファベットと数字」(以下、穴番号)が割り振られており、この図では薄く小さい文字で左側に「A」「B」「C」……、上側に「1」「5」「10」……と記載されている。例えばこの図の「A」行「8」列目の穴(本連載ではA8
と表記)には赤いピンが刺さっている。
Netduinoからの5Vラインは、赤いラインを通ってブレッドボードの一番下に接続する。ここは内部的には横の穴が全て接続されているブレッドボードのプラス電源ラインだ。GNDからの線も同様に青いラインを通って下から二番目に接続する。ここも内部的に横の穴がつながれているブレッドボードのGNDラインだ。
ブレッドボードのプラス電源ラインからは、A8
に接続されている。A8
-B8
-C8
-D8
-E8
(=各列の「A」~「E」行)は内部的に接続されているので、そこのどこかにパスコンの片足とLM61CIZの+Vs
(=向かって一番左足)を刺す。なお、図では見やすさの都合上、パスコンをLM61CIZとは別列に配置してその間をジャンパー線で接続している。実用上はこの両者の間は短い方がいいので、LM61CIZの+Vs
はC8
に刺してしまえばよい。
次に、ブレッドボードのGNDラインからをA10
に接続し、E10
にパスコンのもう片足、C10
にLM61CIZのGND
を差し込む。
最後にLM61CIZのVout
とNetduinoのアナログ0番ピン
を黄色い線で接続すれば完成だ。
実際に接続すると次のようになる。
なお、ブレッドボード上の配線にはジャンパーワイヤー、ブレッドボードとNetduinoの間はジャンパーコードを使用した。ブレッドボード上にきれいな配線を行うのに便利なものなので参考にしてほしい。
Netduino+LM61CIZのプログラミング
回路が完成したら、アプリのプログラミングを始める。
最初に行う手順は、Visual Studioの[新しいプロジェクト]ダイアログで[Micro Framework]カテゴリの[Netduino Plus 2 Application]テンプレートを選択して、新規にプロジェクトを作成することだ(本稿の例では、プロジェクト名はVB.NET用は「LM61TemperatureVB」、C#用は「LM61TemperatureCS」とした)。
アナログ入力用クラスライブラリの参照設定の追加
アナログ入力を行う場合、テンプレートにより追加済みのクラスライブラリに加えて、AnalogInputのクラスライブラリへの参照設定も追加する。
ソリューションエクスプローラーでプロジェクトを右クリックして、(表示されるメニューから)[追加]-[参照]を選択してダイアログを表示し、そこで図7のように「SecretLabs.NETMF.Hardware.AnalogInput」クラスライブラリを選択して[OK]ボタンをクリックする。
センサー値の理解
LM61CIZが、測定した温度をどのようなアナログ値で出力するかもデータシートに記載がある(図8)。
600mVを0℃として、300~1600mVの値がアナログ出力される。また測定値が1℃変わるとセンサー値は10mV変化することもデータシートに記載がある。よって次の式で測定温度が求まる。
アプリ作成
Netduinoのアナログ入力を使ったアプリを作るときに覚えておきたいことがある。それは、アナログ入力ピンは0~3300mVの入力が可能だが、コードで取得するときの値は規定値では「0~1023」の1024段階だという点だ。温度、センサー値、アナログ入力値を比較すると次の表になる。
温度 | センサー値 | アナログ入力値 |
---|---|---|
100℃ | 1600mV | 496 |
25℃ | 850mV | 263 |
1℃ | 610mV | 189 |
0℃ | 600mV | 186 |
-25℃ | 350mV | 108 |
0~3300mvのセンサー値がそのままアナログ入力値として取り出せると、アプリのコードは格段に読みやすくなる。それを可能にするのがSetRange(0, 3300)
だ。詳しくは次のコードを見ていただきたい。
Imports Microsoft.SPOT
Imports SecretLabs.NETMF.Hardware.Netduino
Imports System.Threading
Module Module1
Sub Main()
Dim lm61 = New SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A0) '1
lm61.SetRange(0, 3300) '2Netduinoアナログ出力は(0~3.3V)
While (True)
Dim value = (lm61.Read() - 600) / 10.0F '3600mV = 0℃ , 1℃=10mV
Debug.Print(value.ToString)
Thread.Sleep(500) '4
End While
End Sub
End Module
|
using Microsoft.SPOT;
using SecretLabs.NETMF.Hardware.Netduino;
using System.Threading;
namespace LM61TemperatureCS
{
public class Program
{
public static void Main()
{
var lm61 = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A0); //1
lm61.SetRange(0, 3300); //2Netduinoアナログ出力は(0~3.3V)
while(true)
{
var value = (lm61.Read() - 600) / 10.0F; //3600mV = 0℃ , 1℃=10mV
Debug.Print(value.ToString());
Thread.Sleep(500); //4
}
}
}
}
|
- 1アナログ入力0番ピン用の変数
lm61
を宣言。 - 2
SetRange
メソッドにより、アナログ入力ピンからの取得値は0
~3300
とする。 - 3アナログ入力値から温度へ変換。
- 40.5秒の測定待ち。
3で10.0F
としているのは、lm61.Read()
での戻り値が整数型なので、演算結果が浮動小数点型になるように明示的に定数の型を指定している。
LM35DZを使う場合の変更点
もし、LM61CIZではなくLM35DZを使った場合は、3の計算式が変わる。LM35DZのデータシートから3の式は次のようになるので、LM35DZで使う場合は参考にしてほしい。
Dim value = lm61.Read() / 10.0F '3 0mV = 0℃ , 1℃=10mV
|
var value = lm61.Read() / 10.0F; //30mV = 0℃ , 1℃=10mV
|
アプリ実行
以上でサンプルアプリは完成だ。実際に動かしてみると、[出力]ウィンドウに気温が表示される。
Netduino+LM61CIZのノイズ対策強化版ハード構成
LM61CIZのデータシートを読んでみると、「ノイズが激しい環境ではパスコンに加えて(どちらかというとパスコンより先に)Vout
とGND
の間に、1μFのコンデンサーを入れてローパスフィルター(低域通過回路)を設置するように」という旨が書かれている。ローパスフィルターというのは、特定の周波数以上の信号をカットするフィルターのことであり、高周波ノイズを除去することで、ノイズが多い環境でも出力にノイズが乗って測定値が暴れるのを防ぐという効果がある。
実際にローパスフィルターを設定した場合の回路図は図9のようになる。
Netduino+LM61CIZの出力電圧増幅版ハード構成
入力された電圧をアプリで扱うときは、SetRange
メソッドで指定したとしても、内部的には0
~1023
の整数値として取り出している。つまり、「1℃」の変化でセンサー値は3
変化するので、センサー値1
の変化は「約0.3℃」に相当することになる。どんなに温度センサーの精度を上げたとしても、0.3℃より小さな変化は捉えられないということになる。
また、LM61CIZのセンサー値の範囲は350~1600mVであり、0~3300mVというアナログ入力のレンジを活用していない。そこで登場するのが、センサー値の出力電圧を増幅してアナログ入力のレンジをフル活用することで精度を向上させるという方法だ。
具体的には出力電圧を2倍にすると次のような形になる。
温度 | センサー値 | アナログ入力値 |
---|---|---|
100℃ | 3200mV | 992 |
25℃ | 1700mV | 527 |
1℃ | 1220mV | 378 |
0℃ | 1200mV | 372 |
-25℃ | 700mV | 217 |
これにより「1℃」の変化でセンサー値は6
変化する。つまり、センサー値1
の変化は「約0.16℃」に相当する。
出力電圧を増幅する方法
出力電圧を増幅するには、オペアンプというICを使う。今回はプラス電圧をそのまま2倍にしたいので非反転増幅回路を組む(図10)。
増幅率は2つの抵抗値の比率で調整する。
抵抗は100Ω前後を用いるときが多いので、2倍にしたいのであれば、100Ωの抵抗を両方に付ければよい。
出力電圧増幅回路図
オペアンプとしてOPA277PAを使って非反転増幅回路を作成してLM61CIZと組み合わせたときの回路図は次のようになる。
出力電圧増幅ブレッドボード実装
回路図が出来上がったのでブレッドボードに実装する。OPA277PAは2列4ピン合計8ピンのICなのでブレッドボードに刺すときにはEとFをまたがるように刺す。
ブレッドボードは、E
とF
の間は同じ列でも内部結線されていないので、OPA277PAのようなICはここに刺して上下に配線を伸ばす。なお、端の下2列と上2列は電源ラインとGNDラインなので、横に内部結線されている。
部品点数も多くなり回路も複雑になってきたのでブレッドボード上も混み合ってきたが、Fritzing上で納得いくまで配置を決めてから実装すると思い通りの配線で実装できる。きれいな配線(図13)は配線ミス防止にも役立つので画面上で試行錯誤してほしい。
出力電圧増幅対応アプリ作成
LM61CIZをこの回路に組み込んだときも、SetRange
メソッドを使えばセンサー値をそのままアナログ入力値として使うことができる。2倍になるので、温度「0℃」=センサー値「1200mV」=アナログ入力値1200
だ。また、温度「1℃」の変化もアナログ入力値20
となる。よって、計算するコードは次のようになる。
Dim value = (lm61.Read() - 1200) / 20.0F '3 1200mV = 0℃ , 1℃=20mV
|
var value = (lm61.Read() - 1200) / 20.0F; //31200mV = 0℃ , 1℃=20mV
|
もしくはLM35DZをこの回路に組み込んだときは上限が100℃で1000mVになるので、3倍増幅しても100℃で3000mVとなりセンサー値930
とオーバーフローせずに済む。センサー自体の精度もいいので氷点下を無視してLM35DZを3倍増幅で使うというのも手だろう。このときの温度変換コードは次のようになる。
Dim value = lm61.Read() / 30.0F '3 0mV = 0℃ , 1℃=30mV
|
var value = lm61.Read() / 30.0F; //30mV = 0℃ , 1℃=30mV
|
以上でアプリは完成なので、実行すると、より精度の高い値が出力される。
まとめ
等倍回路と2倍増幅回路での温度測定の結果をグラフにしてみた。
同時測定できるように回路を組んでオペアンプにも0.1μFのパスコンを挟み込んでみたのですが、2倍増幅時の方が増減が激しいように見て取れる。
これはLM61CIZの測定精度自体が等倍回路の精度で十分測定できる範囲であり、増幅によりセンサーの測定精度付近での揺らぎを拾ってしまっているのではないかと考える。LM35DZであればカタログ上は0.5℃の測定精度があるはずなので、2倍増幅や3倍増幅することでアナログ入力の1024段階に丸められたときに消えてしまう変化も検出できるだろう。
このようにアナログ入力を使う場合は、センサーの精度や回路上のノイズの考慮などさまざまな要因を検討しなければならない。例えば1回の測定で測定値とするのではなく、5回の平均で測定値にするなどの工夫も必要だ。このあたりは実際に試して実感していくことでノウハウがたまるので、ぜひサンプルを使って試してほしい。
次回はI2C接続を使ったセンサー入力を取り上げる予定だ。使用する部品としては、ADT7410温度センサーモジュールを予定している(※この部品は、はんだ付けが必要なので、はんだごてが手元にない場合は、「goot 電子工作用はんだこてセット X-2000E」などを購入しておいてほしい)。また、次々回ではAQM0802A-RN-GBW液晶+ブレッドボード用ピッチ変換基盤を使用予定なので、こちらもまとめて購入しておくのがお勧めだ。
※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
2. Netduino、まずは基本のLチカ
初めてのNetduinoアプリ開発。まずは基本の基本であるオンボードのLチカから。次にブレッドボード上の外部LEDのLチカも行う。また、ファームウェアの更新方法も説明する。