PR

C#でArduino用の表示画面をつくる

電子工作など

ArduinoからのデータをPCの画面に表示する簡易的なアプリの作り方を、紹介します。
センサーを使って計測する際などに、PCの大きな画面で確認できれば便利だと思います。  

今回、C#に慣れていない状態で恐る恐る着手しましたが、高機能の開発環境のおかげで思ったより快適に作業できました。

最後に文法の勉強のために読んだ本の紹介もしているので、「C#?やったことない……。抵抗がある」という初めての方の参考になれば幸いです。

スポンサーリンク

はじめに

Arduinoでセンサーを使った計測をする際、測定値を確認する方法は2つあります。

  1. LCDモジュールを回路に組み込んで、その画面に値を表示する
  2. PCに接続し、シリアル通信でデータを受け取る

上記一つ目だと、独立したシステムになるので、PCが無くても値を確認できます。ただしLCDモジュールを購入したり配線したりする必要があります。

二つ目は一番手軽な方法で、配線はUSBケーブルでPCに接続するだけです。データの送受信は、無料の開発環境であるArduino IDEの「シリアルモニタ」で実行できます。

Arduino IDEのシリアルモニタ動作の様子
Arduino IDEのシリアルモニタが動作している様子

ただし、上図のシリアルモニタだと基本的には文字の羅列なので、細かくデータの見た目を整えることができません。
個人的には細かい文字だと見るのがしんどいので、簡単な表示画面をWindowsで作ってみようと思った次第です。

この記事で作るもの

Arduinoからシリアル通信でデータを受信し、PCの画面上に表示する簡単なWindowsアプリを、C#で作ります。開発環境は、Visual studio 2022を使います。

動作デモ

▼動作している様子は、こんな感じです。(gifアニメ)

起動したら接続可能なポートをコンボボックスに表示し、接続ボタン押下で通信を開始します。
左側に大きい文字で距離と電圧を表示し、右側はログとして一行ずつデータを追記していきます。

動作デモ。作ったアプリで、Arduinoからのデータを表示している様子
作ったアプリで、Arduinoからのデータを表示している様子

▼ 測定の様子です。段ボールに貼った白い紙を、測距センサにかざしています。

Arduinoに繋いだ測距センサに、紙をかざしている様子
測定の様子

システム構成

この記事のシステム構成は、下図の通りです。

  • Arduino側の動作…… センサーを接続し、1秒ごとにAD変換された値をPCへ向けて出力する
  • PC側の動作…… シリアル通信でArduinoからのデータを受信し、距離や電圧に換算して画面に表示する
今回のシステム構成。測距センサを繋いだArduinoを、PCに接続している
今回の実験系。測距センサを繋いだArduinoを、PCに接続している

開発環境と、使う部材

開発環境と、使う部材は以下の通りです。

Visual studio 2022(コミュニティ版)

マイクロソフトが開発している、ソフト開発のための総合開発環境です。  

▼ ダウンロードはこちらからできます。

Visual Studio Tools のダウンロード - Windows、Mac、Linux 用の無料インストール
Visual Studio IDE または VS Code を無料でダウンロードします。 Windows、Mac で Visual Studio Professional または Enterprise エディションをお試しください。

Windows PC

Windows 10 64bitのPCで実行しました。

Arduino

電子工作、各種測定、何にでも大活躍。手軽に使える便利なマイコンボードです。

Arduino単体

▼ 初めて購入される方は、キットを買うと一気に部材が揃います。Arduino本体と、USBケーブル、抵抗やブレッドボードなどがそろっています。同梱されているブレッドボードやジャンプワイヤーは電子工作で日常的に使う物なので、入門後もずっと役立ちます。

The Arduino Starter Kit(日本語版)
Arduino (アルドゥイーノ)
Arduinoをはじめる方にぴったりのスターターキットです

▼ 単品で集めることもできます。(この記事の実験では、ブレッドボードやジャンプワイヤは使いませんが、電子工作では必需品です。)

Arduino Uno Rev3 A000066
Arduino (アルドゥイーノ)
名称 Uno
サンハヤト SAD-101 ニューブレッドボード & ジャンプワイヤキット SKS-100 単線タイプでよく使用する短めジャンプワイヤのセット品【セット買い】
サンハヤト
こちらの商品で付与されるAmazonポイントは、個別商品のポイントが合算されて付与されます。正確なポイント数については注文確認画面にてご確認ください。

▼ 秋月電子だとArduinoを始め、USBケーブルやブレッドボード、基板など豊富な選択肢からまとめ買いできます。

Arduino Uno Rev3: 開発ツール・ボード 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作Arduino Uno Rev3秋月電子通商 電子部品通信販売

測距センサ

シャープ測距モジュール GP2Y0A21YK0Fを使いました。タミヤの工作ボードの端材に六角スペーサーを付けた台を作って、固定しています。

シャープ測距モジュール GP2Y0A21YK: 計測器・センサー・ロガー 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作シャープ測距モジュール GP2Y0A21YK秋月電子通商 電子部品通信販売
GP2Y0A21YK0Fを端材の台に取りつけた様子
測距センサGP2Y0A21YK0Fを端材の台に取りつけた様子

先端は、スズメッキ線を半田付けして、Arduinoのポートに直接挿しています。折れそうで不安定なので本来はコネクタを付けるべきなのですが、むかし半田付けしたものが手元にあったので今回使いました。

では、これから具体的な手順を説明します。

Arduino側の準備

配線する

Arduinoとセンサーを下図のように接続します。

使う測距センサには三本の線があり、それぞれ電源供給の5V、GND、信号線です。

コードを書く

測距センサのデータを、シリアル通信でPCへ出力するコードを書きました。
1秒ごとに送信するだけです。

送信データは、AD変換された値です。距離や電圧への換算は、PC側で行います。

301 Moved Permanently

データを出力できているか、確認

Windowsアプリを作る前に、そもそも測距センサのデータが正常にPCへ送信されているかを確認しておきます。Arduino IDEというArduino専用の開発環境を使います。

▼ Arduino IDE

Software
Open-source electronic prototyping platform enabling users to create interactive electronic objects.

PCにUSBケーブルでArduinoを接続し、Arduino IDEを立ち上げます。上部メニューのツールシリアルモニタという機能を使えば、すぐに確認できます。

▼ 無事、データがPCへ送信されていました。

Arduino IDEのシリアルモニタでデータ確認している様子
Arduino IDEのシリアルモニタを立ち上げて、データ確認している様子(gifアニメ)

さて、ここからはWindowsアプリを作っていく作業に移ります。

Visual Studioを導入する

Visual Studioのコミュニティ版(個人使用が無料)をインストールし、立ち上げます。

▼ ダウンロードは、こちらからできます。

Visual Studio Tools のダウンロード - Windows、Mac、Linux 用の無料インストール
Visual Studio IDE または VS Code を無料でダウンロードします。 Windows、Mac で Visual Studio Professional または Enterprise エディションをお試しください。

Windowsフォームアプリ を立ち上げる

▼ 立ち上げたらまずはこんな画面がでるので、「新しいプロジェクトの作成」を選択。

▼ C# 用の「Windows フォームアプリケーション(.NET Framework)」を選択し、次へ をクリックします。

プロジェクト名 や 保存場所 を適宜入力して、「作成」をクリックします。

Windowsアプリを作る環境が立ち上がります。

visual studioを立ち上げた様子

NuGet でsystem.IO.Portsをインストールしておく

Visual studioでシリアル通信を使うために、NuGet というシステムから、別途必要な機能のパッケージをインストールしておきます。

ちなみに、NuGetの発音は”New Get”(ニューゲッツ)です。.NETの動画でそう発音されていました。(調べるまでは、ずっとナゲット🍟かと思っていました)

ツール → NuGet パッケージマネージャソリューションのNuGetパッケージの管理 を選択し……

▼ 参照 をクリックして、検索欄に system.IO.Ports と入力します。

候補が出てきたらsystem.IO.Portsを選択し、右に表示されている自分のプロジェクト名にチェックを入れて、インストールボタンをクリックすれば完了です。

ソフトの外観を作る

まずは、ソフトの外観を作ります。

ドラッグアンドドロップで、ぽんぽんとコントロール(ボタンなどの部品)を配置していきます。

visual studioで部品を配置する様子
visual studioで部品を配置する様子

見た目は、右下のプロパティパネルで適宜変えられます。

▼ こんな感じで配置してみました。

Visual studioのFormツールで、コントロールを配置した様子

距離に換算する式を作っておく

次にプログラムのコードを書き進める前に、Arduinoから受信した値を距離に変換する式を作っておきます。

  • 距離は、データシートのグラフから近似式を求めて、その式に電圧を代入します。
  • 電圧は、ArduinoでAD変換された値から換算します。
    (ArduinoのAD変換についてのドキュメントはこちら

元にするデータシートのグラフは、以下のPDFの p5. Fig. 2 Exsample of distance measuring characteristics(output) に掲載されています。

近似式は、エクセルの機能を使って求めました。

まず、データシートp5.下段の Inverse number of distance(1/cm) の値を読み取り、距離の逆数(x軸)と電圧(y軸)をエクセルにプロットします。
そして、xy軸を入れ替えて線形近似とみなし、エクセルの機能で式を求めます。
(グラフのデータ要素上で右クリック → 近似曲線の追加 を選択する)

y=0.0479x-0.0085 という式が出来上がりました。

▼ これを、プログラムでこんな感じで使用します。

//受信した値を電圧に換算
voltage = float.Parse(AdcVal) * 5 / 1024; 
//Excelで出した近似式を使用し、電圧から距離を出す
distance = (float)(1/(0.0479 * voltage - 0.0085));  

データシートのグラフからの値の読み取りは、目分量です。

▼ ちなみに、下図は今回の距離の測定結果です。5cmごとに測ってみました。  

全体的にばらつきが大きいですが、特に40cmを超えるとデータが乱れてしまいました。今回はアプリを作るのが主目的なので、特に対策などはしませんでした。

コードを書いてく

さて、準備が整ったので、先ほど配置したコントロールにイベント、イベントハンドラーを追加して、実行するコードを書いていきます。

イベントを追加する

イベント、イベントハンドラーはざっくりと言うと下記のような意味です。

  • イベント…… ボタンのクリックなど、アプリ上で起きた何らかの事象
  • イベントハンドラー…… イベントの発生を受取り実行される処理

詳しくは、マイクロソフトのドキュメントや、最後に紹介しているC#おすすめ本をご覧ください。

追加方法

▼イベントは、ボタンなど対象のコントロールを選択後、右下のプロパティパネルの稲妻マークをクリックして、設定します。

例えば、「クリックされた」というイベントなら、アクションのClick欄にイベント名を記入してエンターキーで確定します。

すると、こんなコードが生成されます。(イベント名は、ConnectButtonClickedとした場合)

private void ConnectButtonClicked(object sender, EventArgs e)
  {
    //この中に処理を書く
  }

今回のイベント

今回のイベントとその後の処理は下記の通りです。

接続ボタンをクリック時
接続を開始する
切断ボタンクリック時
シリアル通信を終了する
シリアルデータ受信時
  • 受信した値を距離や電圧に換算する
  • 換算した値を表示する(直接ではなくInvokeの引数として呼び出す)

表示値の処理には、Invokeメソッドを使った

受取ったデータをテキストやログとして表示する部分は、別途メソッドを用意し、デリゲートを使ってInvokeメソッドの引数として呼び出しています。以下のコードの7行目です。

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{
    string AdcVal = sp.ReadLine();
    //中略(受け取ったデータを電圧へ換算する処理など)
    //メインスレッドで実行するための命令
    Invoke(new AddLabelDelegate(AddLabel)); 
}

private delegate void AddLabelDelegate(); //デリゲート型を宣言
void AddLabel() //表示値の処理
{
    distanceLabel.Text = distance.ToString("F2") + " cm" + "\r";
    //以下略(テキストボックスやラベルの表示値を変える処理)
}

最初は、シリアルデータ受信時のイベントのイベントハンドラーに全部書いてしまっていました。

しかしドキュメントの「注釈」の項に、以下のような説明があったので修正しました。
(日本語版は読みづらい機械翻訳だったので、英語を引用します。)

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object.(中略) If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.

https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.datareceived?view=dotnet-plat-ext-6.0

概要は、「シリアルデータ受信イベントの DataReceived event はセカンダリスレッドで発生するため、UI要素の変更などを行うのは適切ではない。その場合は、Invokeを使用しなさい」とのことです。

参考ドキュメント

💡 ちなみに、どっちのスレッドで実行されてるのか確認してみました。

確認には、Visual studioの機能を使いました。まず確認したい行の左端をクリックして、ブレークポイントを設けます。
そして、デバッグを開始(緑色の三角形の再生ボタンを押下)して、上部メニューのデバッグウインドウスレッド をクリックし表示パネルを出します。
そしてアプリを実行すると、ブレークポイント部分で処理が止まり、結果が表示されます。

▼ DataReceivedイベントのイベントハンドラー内を見ると、メインではなくワーカースレッドと表示されています。

▼ Invokeで呼び出すようにしたメソッドの中で確認すると、メインスレッドと表示されていました。正しく動いているようです。

Visual studioのデバッグ機能で、動作しているスレッドを確認している様子

書いたコード

最終的なコードは以下の通りです。

Arduino側

Windowsアプリ側

Arduinoから受け取った値を、距離や電圧に換算して、画面に表示します。

▼ コントロール(部品)に付けた名前は、下図の通りです。

参考文献

C#のドキュメント

Arduinoのドキュメント

C#が初めての方へ、おすすめ本

C#を始めから学べる書籍を紹介します。

▲ 第一歩のとっかかりとして最適な本です。ネットのチュートリアルだけではなかなか理解が進まなかった私は、この本に助けられました。

優しい語り口と随所のイラストがとてもかわいく、ほっこりと勉強を進められます。

最初はコンソールでプログラムの結果を確認しながら学習を進め、後半はWindowsアプリを作っていきます。イベントやイベントハンドラーも、本書の課題でボタンを設置したりしてるうちに、なんとなく馴染んできました。
作るアプリはシンプルな機能なので、プログラムの流れやコードの書き方を把握しやすく、とにかくC#に慣れることに専念できます。

デリゲートなど省かれている項目もありますが、読み終わる頃には、次の本やドキュメントを読むのが、だいぶ楽になっているはずです。

▲ 分厚い本です。先に紹介した「確かな力が身につく~」では扱われていなかった項目が網羅されていて、文法上で何かわからないことがあったら、すぐ参照しています。頼りになる本です。
プログラミング自体が初めての方は、まず先に紹介した入門書を一通り読んでおくと、理解がスムーズだと思います。

個人的には、今回Windows formを使う上で、最後の章に載っていた「11.4.1 イベントの基本」がとても勉強になりました。
イベントの発生側と受け取り側の処理の流れが、サンプルコードを用いて解説されています。
イベントはあまり馴染みのない概念だったので、コードを動かしながら読んでいると、少しずつ理解が進んできました。(まだ途上ですが)

内容は言語の仕様が中心でサンプルコードも全てコンソールアプリですが、「Windows formでGUIアプリを作りたい」という方にも基礎固めに役立つと思います。

動画もあります

この記事の内容を、6分半ほどの動画にしました。(注意:音声ありです)

Youtubeでご覧になる場合はこちら
タイトルとURLをコピーしました