Alternative Architecture DOJO

オルターブースのクラウドネイティブ特化型ブログです。

.NET nanoFrameworkを使ってC#でマイコンのプログラムを書いてみた

こんにちは、11月になったときに「今年も残すところあと2ヶ月か~」と言ったら娘に「え、年長組はまだ5ヶ月あるよ?」と言われ、色々なことが分かってきたなと感心しつつ年度の概念を説明した木村です。

本記事はオルターブースAdvent Calendar 2023の4日目の記事です(毎年カレンダーの綴りを一瞬迷います)。

adventar.org

IoT番長ということで毎年アドベントカレンダーではIoT関連の記事を書いているのですが(だいたいはSORACOMの事ばかりですが)、今年はマイコンのプログラムをC#で書いたという話題にしてみました。

.NET nanoFrameworkとは

みなさんESP32などのマイコンのプログラムはCやC++で書くというイメージをお持ちかもしれませんが、最近ですとmicro pythonやElixirなど多様な言語で開発できるようになってきています。そして、弊社の主力言語であるC#にも.NET nanoFrameworkというものがあります。

.NET nanoFrameworkは公式ページの説明を要約すると以下のような特徴を持っています。

  • 使い慣れたツールやデバッグ機能(Visual Studio)を使ってC#でマイコンのプログラムを書ける
  • 多くのマイコンに対応
  • イーサネット、WiFi、モデム等を介してAzure IoTやAWS IoTのライブラリを利用できる

これはなかなか面白そうですね、早速試してみました。

ターゲットとなるマイコンは、昨年の記事でも利用した、M5Stack Coreを使いました。

開発環境の準備

公式ページのgetting startに従って開発環境を準備します。今回私はVisual Studio 2022(17.8.1)を使いました。
Visual Studioの拡張機能から「.NET nanoFramework」をインストールします。

.NET nanoFrameworkエクステンション

インストールにはVisual Studioの再起動が必要なので、一旦再起動します。

次に、M5Stackにファームウェアを書き込みます。以下は公式ページのアーキテクチャ図を引用していますが、対象となるマイコンにnanoCLRという実行環境をインストールし、その上でC#のプログラムを実行するという仕組みになっています。そのため、このnanoCLRが入っているファームウェアを書き込む必要があります。

https://docs.nanoframework.net/images/architecture.png

ファームウェアの書き込みはnanoFirmwareFlasherというツールを使うので、まずこれをインストールします。公式ページでは.NET 6.0のランタイムが必要と書いてありますが、2023/11/30時点で最新の.NET 8.0のランタイムでも問題なく動作しました。

$ dotnet --version
8.0.100
$ dotnet tool install -g nanoff

次に、M5StackをPCに接続して、nanoFirmwareFlasherを実行します。M5Stackがシリアルとして認識されるようにセットアップする手順はここでは割愛します。
以下のコマンドを実行すると、利用できるシリアルポートの一覧が表示されますので、M5Stackが接続されているポートがあることを確認してください。

$ nanoff --listports
.NET nanoFramework Firmware Flasher v2.5.46+527e3d0ff4
Copyright (C) 2019 .NET Foundation and nanoFramework project contributors


Available COM ports:
  COM1
  COM4

私の環境ですとCOM4になります。
次に、以下のコマンドで利用可能なファームウェアの一覧を確認します。

$ nanoff --listtargets
.NET nanoFramework Firmware Flasher v2.5.46+527e3d0ff4
Copyright (C) 2019 .NET Foundation and nanoFramework project contributors


Available targets:
  ST_B_L475E_IOT01A
    1.9.0.110
    1.9.0.91
    1.9.0.42
  ....
  M5Core
    1.9.0.888
    1.9.0.868
    1.9.0.860
  ....

大量に表示されますが、今回はM5Stack Coreを使うのでM5Core/1.9.0.888を使うことにします。以下のコマンドでインストールします。--serialportには先ほど確認したシリアルポートを指定します。

> nanoff --target M5Core --serialport COM4 --update
.NET nanoFramework Firmware Flasher v2.5.46+527e3d0ff4
Copyright (C) 2019 .NET Foundation and nanoFramework project contributors


Reading details from chip...OK

Connected to:
ESP32 (ESP32-D0WDQ6 (revision v1.0))
Features WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Flash size 4MB unknown from ST (manufacturer 0x32 device 0x16406)
PSRAM: undetermined
Crystal 40MHz
MAC 80:7D:3A:B6:E4:FC

Downloading firmware package...OK
Extracting M5Core-1.9.0.888.zip...OK

Updating to 1.9.0.888

Erasing flash...OK
Flashing firmware...OK

上記のように「Flashing firmware...OK」と表示されればファームウェアの書き込みは完了です。

プロジェクトの作成とHello Workd

では、早速プロジェクトを作成してみましょう。Visual Studioを起動して、新しいプロジェクトを作成します。
プロジェクトの種類は「Blank Application (.NET nanoFramework)」を選択します。

新規プロジェクト作成

プロジェクト作成段階で準備されているProgram.csは、以下になります(コメントは省略しています)。見慣れたC#のコードですね。そして、いつものマイコンのコードのように最後は無限ループで終わっています。

using System;
using System.Diagnostics;
using System.Threading;

namespace NFApp1
{
    public class Program
    {
        public static void Main()
        {
            Debug.WriteLine("Hello from nanoFramework!");

            Thread.Sleep(Timeout.Infinite);
        }
    }
}

このままではデバイス側に特に何も出ることなく終わってしまいますので、M5Stack Coreのディスプレイに文字を出力してみましょう。
M5Stack Core特有の機能を使うために、nugetパッケージでnanoFramework.M5Coreをインストールします。
そして、ソースコードを以下のように修正します。

using nanoFramework.M5Stack;
using System.Threading;
using Console = nanoFramework.M5Stack.Console;

namespace NFApp1
{
    public class Program
    {
        public static void Main()
        {
            M5Core.InitializeScreen();
            Console.WriteLine("Hello from nanoFramework!");

            Thread.Sleep(Timeout.Infinite);
        }
    }
}

using Console = nanoFramework.M5Stack.Console;とすることでConsole.WriteLine()の出力先がM5Stack Coreのディスプレイになります。導入したパッケージはM5Coreですが、名前空間はM5Stackなのでご注意ください。
そして、Console.WriteLine()の前にまずM5Core.InitializeScreen()を呼び出して、M5Stack Coreのディスプレイを初期化しています。

では早速このプログラムをビルドして、M5Stack Coreにデプロイしてみましょう。Visual Studioの「ビルド」メニューから「(プロジェクト名)の配置」を選択します。
もしここでデプロイが失敗する場合は、M5Stack Coreのファームウェアとパッケージのバージョンが合っていない可能性があります。nugetパッケージのバージョンを変更して再度試してみてください。

デプロイが成功すると、以下の写真のようにM5Stack Coreのディスプレイに「Hello from nanoFramework!」と表示されます。

M5Stack Coreに表示された様子

次に、デバッグ実行をやってみましょう。Visual Studioの「表示」メニューから「Device Explorer」を選んで、Device Explorerを表示しておきます。「表示」メニューでDevice Exploreが出てこない場合は、「表示」→「その他のウィンドウ」を選択してみてください。

Device Explorerを表示する

一度このDevice Explorerを表示しておかないと、デバッグ実行時にエラーになってしまいました。

そして、Console.WriteLine()の行の所にブレイクポイントを置いて、いつものように「デバッグ」メニューからデバッグを開始します。ちゃんとブレイクポイントで止まり、M5Stack Coreのディスプレイには何も表示されません。そして再開したら「Hello from nanoFramework!」と表示されます。

まとめ

今回は、.NET nanoFrameworkを使ってC#でマイコンのプログラムを書いてみました。 豊富なC#のライブラリを利用でき、Visual Studioのデバッグ機能も使えるとなると開発が大変捗りそうです。ただし、ファームウェア(nanoCLR)のサイズがそれなりにあるので、メモリの制約からあまり大規模なプログラムや大きなライブラリを含んだプログラムを書くのは難しいかもしれません。

今回は最初の一歩ということでディスプレイに文字を表示するという簡単なプログラムを書いてみましたが、次回はAzureに接続するような、もう少し複雑なプログラムを書いてみたいと思います。

皆様のお役に立てば幸いです。

サービス一覧 www.alterbooth.com cloudpointer.tech www.alterbooth.com