.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から見えるようにしてみよう。