.NET対応組み込みデバイス「Netduino」入門(6)
Netduinoシリアル通信(I2C)で複数機器接続
シリアル通信(I2C)で2つ以上の機器を同時に使用するサンプルを作成する。温度センサーから室温を取得して液晶ディスプレイ(LCD)にリアルタイム表示してみよう。
前回の予告通り、温度センサーの値をLCDに表示する。
使用部品について
I2C対応機器として、これまでの連載の中で使用した次のものを同時使用する。
接続回路図
複数のI2C対応機器を接続する場合、4本のラインをそれぞれ分岐して各機器に接続する。SCLとSDAに設置する10kΩのプルアップ抵抗は機器ごとではなく1組だけ設置すればよい。
ブレッドボード実装
回路図(図1)を基にしてブレッドボードに部品を配置する(図2)。
Netduinoからの5Vラインは赤いラインを通ってブレッドボードの一番下のプラス電源ラインを通ってLCDのVDDとRESETそして温度センサーのVDD、1組のプルアップ抵抗へと5Vを供給する。NetduinoのGNDからの線も同様に青いラインを通って下から二番目のGNDラインに接続し、LCDと温度センサーのGNDに接続する。
SCLとSDAの2つの信号線は、SCLがA23、SDAがA22でNetduinoに接続し、ここからB13とC14に分岐してLCD側に接続する。また、プルアップ用の10KΩ抵抗でA13とA14からプラス電源ラインの間を接続する。
実際に接続すると、ブレッドボード上の実装は次のようになる。
今回使用したLCDと温度センサーは端子の向きが左右逆転している。もし、端子の左右を揃えて左から順にVDD、SDA、SCL、GNDと揃えたいのであれば、温度センサーを裏表逆に差し込んで回路を組み直すといいだろう。
Netduinoでの複数I2C機器のプログラミング
回路が完成したら、Visual Studioの[新しいプロジェクト]ダイアログで[Netduino Plus 2 Application]テンプレートを選択して、新規にプロジェクトを作成して(本稿の例では、プロジェクト名はVB.NET用は「TemperatureVB」、C#用は「TemperatureCS」とした)、アプリのプログラミングを始める。
クラス構成
今回のサンプルコードのクラス構成をVisual Studioのコードマップ機能で確認する。なお、前回まではVBならばModule.vbファイル、C#ならProgram.csファイルの中にあったLCDや温度センサー用のクラスも、今回からは別クラスファイルにしている(※そのため、Private/privateとして実装していたクラスはFriend/internalに変更しなければならないので注意してほしい。その他、名前空間名の違いにも注意されたい)。
I2C用クラスであるI2CLibクラスを基本クラスとして、LCD用AQM0802Libクラス、温度センサー用ADT7410Libクラスに派生させてから呼び出している。これらのクラスは、前回および前々回に作成したものと同じなので、本稿では説明を割愛する。
複数I2C機器を同時に使うときの注意点としては、プログラムで接続する際のI2Cアドレスが複数あるということだ。I2CLibクラスの中で使っているI2CDeviceクラスは1度に1つのアドレスしか指定できず、オブジェクトを生成したまま、I2Cアドレスを切り替えることができない。そこで機器ごとに、つまり、LCDを使うときはAQM0802Libクラスからオブジェクトを生成して表示データを送信したら速やかに解放(Dispose)し、温度センサーから温度を読み出すときはADT7410Libクラスからオブジェクトを生成してデータを読み取ったら速やかに解放(Dispose)するようにしなければならない。つまりリスト1のように、I2CLibクラスのDisposeメソッド内に、I2CDeviceオブジェクトをDisposeするコードを追加する。
|
……省略……
Friend Class I2CLib
Implements IDisposable
……省略……
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
Me.I2c.Dispose()
End If
End If
Me.disposedValue = True
End Sub
……省略……
End Class
|
|
……省略……
namespace ADT7410TemperatureCS
{
internal class I2CLib : IDisposable
{
……省略……
public void Dispose()
{
this.I2c.Dispose();
GC.SuppressFinalize(this);
}
……省略……
}
}
|
このようなことができるのは、LCDも温度センサーもNetduinoからの接続が切れても電源さえ切れなければ状態を維持して動作し続けるからだ。
AQM0802用クラスの改良
前回作成したAQM0802Libクラスでは、クラスからオブジェクトが生成されるときに初期化も行っていた。今回のように生成と解放を繰り返す使い方をしたいときには、最初の1回だけ初期化すれば状態が維持されるので毎回初期化するのは非効率だ。そこで初期化部分をInitメソッドとして切り出しておこう。具体的には次のようなコードになる。
|
Public Sub New()
MyBase.New(&H3E, 100, 500)
Thread.Sleep(40) ' 40ms待つ
End Sub
Public Sub Init()
' 画面サイズ指定
Me.WriteCommand(LCD_FUNCTIONSET Or LCD_8BITMODE Or LCD_2LINE)
' 拡張コマンド設定開始
Me.WriteCommand(LCD_FUNCTIONSET Or LCD_8BITMODE Or LCD_2LINE Or ISBit)
' AQM0802用固定設定
Me.WriteCommand(&H14) ' Internal OSC Frequency
Me.WriteCommand(&H70) ' Contrast set
Me.WriteCommand(&H52) ' Power/ICON/Contrast control(5V用)
Me.WriteCommand(&H6C) ' Follower control
' 拡張コマンド設定終了
Thread.Sleep(200)
Me.WriteCommand(LCD_FUNCTIONSET Or LCD_8BITMODE Or LCD_2LINE)
'
Me.WriteCommand(LCD_DISPLAYCONTROL Or LCD_DISPLAYON) ' DISPLAY ON
Me.WriteCommand(&H6) ' Entry mode set
Me.ClearDisplay()
End Sub
|
|
public AQM0802Lib()
: base(0x3e, 100, 500)
{
Thread.Sleep(40); // 40ms待つ
}
public void Init()
{
// 画面サイズ指定
this.WriteCommand(LCD_FUNCTIONSET | LCD_8BITMODE | LCD_2LINE);
// 拡張コマンド設定開始
this.WriteCommand(LCD_FUNCTIONSET | LCD_8BITMODE | LCD_2LINE | ISBit);
// AQM0802用固定設定
this.WriteCommand(0x14); // Internal OSC Frequency
this.WriteCommand(0x70); // Contrast set
this.WriteCommand(0x52); // Power/ICON/Contrast control(5V用)
this.WriteCommand(0x6C); // Follower control
// 拡張コマンド設定終了
Thread.Sleep(200);
this.WriteCommand(LCD_FUNCTIONSET | LCD_8BITMODE | LCD_2LINE);
//
this.WriteCommand(LCD_DISPLAYCONTROL | LCD_DISPLAYON); // DISPLAY ON
this.WriteCommand(0x6); // Entry mode set
this.ClearDisplay();
}
|
メインプログラムの作成
クラスの用意ができたら、MainメソッドからADT7410LibクラスとAQM0802Libクラスの呼び出しを作成する。
|
Module Module1
Sub Main()
Using lcd As New AQM0802Lib
lcd.Init() ' ……1
End Using
While (True)
Dim value As Single
Using adt7410 As New ADT7410Lib
value = adt7410.ReadTemperatre ' ……2
End Using
Using lcd As New AQM0802Lib
lcd.Locate(0, 0)
lcd.WriteMessage(value.ToString()) ' ……3
End Using
Thread.Sleep(1000) ' ……4
End While
End Sub
End Module
|
|
public class Program
{
public static void Main()
{
using (AQM0802Lib lcd = new AQM0802Lib())
{
lcd.Init(); // ……1
}
while (true)
{
Single value;
using (ADT7410Lib adt7410 = new ADT7410Lib())
{
value = adt7410.ReadTemperature(); // ……2
}
using (AQM0802Lib lcd = new AQM0802Lib())
{
lcd.Locate(0, 0);
lcd.WriteMessage(value.ToString()); // ……3
}
Thread.Sleep(1000); // ……4
}
}
}
|
- 1LCD初期化(
usingブロックの間だけ接続)。 - 2温度センサーからの値取得(
usingブロックの間だけ接続)。 - 3LCDに温度表示(
usingブロックの間だけ接続)。 - 41000ms=1秒の待ち合わせ。
アプリ実行
アプリを実行すると、1秒ごとに気温を更新表示する。
【動画】Netduino plus 2+LCD
まとめ
測定結果をブレッドボード上のLCDで確認できるようになった。プログラムの動作が確認できたらPCからUSBを外して別電源から7.5V~9.0Vを供給すると自動的にブートされてプログラムが起動し気温をLCDに表示し続けてくれる。
次回は、今回作成した回路とプログラムを使ってMicrosoft AzureのEventHubにデータを送信してクラウド側でデータ表示する方法を取り上げる。いわゆるIoTの世界だ。
※以下では、本稿の前後を合わせて5回分(第4回~第8回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
6. 【現在、表示中】≫ Netduinoシリアル通信(I2C)で複数機器接続
シリアル通信(I2C)で2つ以上の機器を同時に使用するサンプルを作成する。温度センサーから室温を取得して液晶ディスプレイ(LCD)にリアルタイム表示してみよう。
8. GR-PEACHボードとAzure Event Hubでクラウド集計
ついに発売開始されたGR-PEACHを利用。Microsoft Azure Event Hubを使って室温データをクラウドに送信してWebから見えるようにしてみよう。