SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

.NET nanoFrameworkとESP32でIoTプログラミング

C#でLED電光掲示板を作ろう! .NET nanoFrameworkとESP32でIoTプログラミング!

.NET nanoFrameworkとESP32でIoTプログラミング 第5回


  • X ポスト
  • このエントリーをはてなブックマークに追加

センサーと組み合わせ、リアルタイムで距離を計測して表示する

 距離を測定するセンサーには、レーザー光や電磁波、超音波を利用するものがあります。今回は、赤外線レーザー光を利用したTOF(Time of Flight)センサーを使います。TOFとは、センサーから発信した光が対象物に反射して往復するまでの時間を計測し、距離を定める方法です。

VL53L0X

 VL53L0Xという距離センサーモジュールを利用します。測定範囲は、約30mmから最大2mで、I2C接続でデータを取得できます。ESP32はI2Cにも対応していますので、センサーモジュールをそのまま直結して使うことができます。

VL53L0X
VL53L0X

I2C

 I2C(Inter-Integrated Circuit)とは、SPI通信と同様のシリアル通信規格です。主な特徴は、次のとおりです。

  • 2本の信号線(クロック、データ)
  • マスター/スレーブ方式
  • アドレス指定により複数のスレーブデバイスに対応
  • SPIに比べて低速

 I2Cでは、コントローラとなるマスターと、センサーなどのスレーブの間で通信を行います。スレーブデバイスは、それぞれ固有のアドレスを持っており、マスターがこのアドレスを指定して通信を行います。つまりI2Cのアドレスは、デバイスを識別するためのもので、I2C通信を行う上で非常に重要な要素となります。

 またI2Cでは、電源と信号線2つの合計4つの接続だけで通信可能です。そのため、信号線だけで4つ使うSPIよりもシンプルな配線となります。

配線とソース

 ESP32では、I2C接続でも任意のGPIO端子で利用可能です。ここでは、GPIO18、19を利用しました。また、.NET nanoFrameworkには、VL53L0X用のクラスが用意されています。VL53L0Xの制御は、けっこう複雑なコードが必要なのですが、そのあたりはクラス内に実装されていますので、とても短いコードで距離を測定できます。

 最初にNuGetパッケージマネージャで、次のパッケージをインストールしておきます。

  • nanoFramework.Hardware.Esp32
  • nanoFramework.Iot.Device.Vl53L0X

 距離センサーの値を取得して、デバッグ表示するコードは、次のようになります。

[リスト3]Program.csの一部

public static void Main()
{
    // I2C接続に用いるGPIOの設定(1)
    Configuration.SetPinFunction(18, DeviceFunction.I2C1_DATA);
    Configuration.SetPinFunction(19, DeviceFunction.I2C1_CLOCK);

    // I2C通信のアドレス設定(2)
    var connectionSettings =
        new I2cConnectionSettings(1, Vl53L0X.DefaultI2cAddress);

    // I2C通信オブジェクトの生成(3)
    using var i2c = I2cDevice.Create(connectionSettings);

    // Vl53L0Xオブジェクトの生成(4)
    var vL53L0X = new Vl53L0X(i2c);

    // 測定モードを連続モードにする(5)
    vL53L0X.MeasurementMode = MeasurementMode.Continuous;

    while (true)
    {
        try
        {
            var dist = vL53L0X.Distance;

            // 値がOperationRange.OutOfRangeは測定異常(6)
            if (dist != (ushort)OperationRange.OutOfRange)
            {
                // 計測距離(mm)の表示(7)
                Debug.WriteLine($"Distance: {dist}");
            }
            else
            {
                Debug.WriteLine("Invalid data");
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Exception: {ex.Message}");
        }
        Thread.Sleep(500);
    }
}

 I2C接続の設定手順は、SPIと同様です。I2C接続に用いるGPIOの設定後(1)、設定オブジェクトを生成して(2)、通信オブジェクトを生成します(3)。設定オブジェクトといっても、SPIと異なり、I2Cのアドレスを設定する程度です。

 Vl53L0Xクラスのコンストラクタで、通信オブジェクトを指定して初期化します(4)。そして、測定モードを、連続取得モードに設定します(5)。この測定モードでは、一定周期で計測が行われますので、適宜Distanceプロパティを参照すれば、随時距離が参照できるはずです(7)。測定値が、固定のOperationRange.OutOfRange(8190)となった場合は、正しく測定できなかったという意味となります(6)。

計測距離デバッグ表示
計測距離デバッグ表示

 なお、Vl53L0Xのアドレスは、標準で0x29(Vl53L0X.DefaultI2cAddress)となります。Vl53L0Xでは、アドレスをハードウェア的に変更することはできないので、もし同じアドレスのデバイスを使いたい場合は、初期化時にアドレスを変更する必要があります。いったんデフォルトのアドレスでVl53L0Xオブジェクトを生成後、Vl53L0XクラスのChangeI2cAddressメソッドで、アドレス変更のコマンドを発行します。それからあらためて、新しいアドレスでI2C通信オブジェクトを作り、Vl53L0Xオブジェクトを生成しなおす必要があります。

マトリックスLEDでレベルメーター

 先ほどのマトリックスLEDを使って、距離をレベル表示するようにしてみます。

[リスト4]Program.csの一部

public static void Main()
{
    // MAX7219、Vl53L0Xの準備
    ~中略~

    m7219.Rotation = RotationType.Right;

    // レベルメーターのバイト列データ(1)
    var levelmeter = new byte[] {
            0b10000000,
            0b11000000,
            0b11100000,
            0b11110000,
            0b11111000,
            0b11111100,
            0b11111110,
            0b11111111,
    };

    while (true)
    {
        try
        {
            // 距離をレベル(0~8)に変換(2)
            var level = Math.Min(400, vL53L0X.Distance) / 50;

            // バッファクリア(3)
            m7219.Clear(0, 1, false);

            // 距離レベルより小さい表示データを内部バッファに書き込む(4)
            for (var i = 0; i < level; i++)
            {
                m7219[new DeviceIdDigit(deviceId: 0, digit: i)] = levelmeter[i];
            }
            m7219.Flush();
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Exception: {ex.Message}");
        }
        Thread.Sleep(100);
    }
}

 MAX7219、Vl53L0Xのオブジェクトを作成した後、レベルメーターのバイト列データ(1)を定義しています。スマホの電波強度のアンテナ表示みたいなイメージです。

 測定した距離は、0から8(400ミリ以上は8)になるように変換します(2)。あらかじめ内部バッファをクリアしてから(3)、内部バッファにレベルメータのイメージのデータを書き込みます。定義したバイト列の配列から、距離レベルより小さいインデックスのものを指定します(4)。

 このコードを実行して、センサーに手をかざすと、リアルタイムにレベルメーターが変化します。

レベルメーター
レベルメーター

マトリックスLEDでリアルタイム距離表示

 次に、距離をそのまま数値で表示してみましょう。カスケード接続したマトリックスLEDを用います。

[リスト5]Program.csの一部

~中略~
var dist = vL53L0X.Distance;
if (dist != (ushort)OperationRange.OutOfRange)
{
    writer.ShowMessage(dist.ToString(), alwaysScroll: false); // スクロールなし
}

 値をそのまま表示するには、さきほどの電光掲示板のプログラムと同様に、MatrixGraphicsクラスのShowMessageメソッドを利用します。今回はスクロール表示は不要なので、ShowMessageメソッドのalwaysScrollパラメータは、falseにします。

 実行すると、リアルタイムで距離が表示されます。

アスキー文字
距離が表示される様子

最後に

 今回は、ドットマトリックスLEDを使って、電光掲示板表示や、センサーの値を表示するプログラムを作成しました。次回は、Bluetooth通信を利用したプログラムを作成する予定です。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
.NET nanoFrameworkとESP32でIoTプログラミング連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20049 2024/10/03 12:28

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング