バージョン情報
Arduino Uno , Arduino IDE 1.0.5 , Visual C# 2013 , Visual Studio Express 2013 for Windows Desktop , windows 8.1
Arduinoを使ってシリアル通信を試してみた。その2。
今回の実験内容
アナログセンサ : フォトリフレクタ
↓
Arduino
↓
PC : Visual C#でグラフ化
Arsuino側は前回と同じ。
【Arduinoのスケッチ】
時間とデータをカンマでつないだ文字列として送信。
int analog_in = 0; int val = 0; String str_send_data; unsigned long sTime = 0; //プログラム開始時間 unsigned long cTime = 0; //sTimeからの経過時間 unsigned long rTime = 0; //サンプリングレート調整用 void setup() { Serial.begin(38400); sTime = millis(); } void loop() { cTime = millis() - sTime; rTime = millis(); val = analogRead(analog_in); str_send_data = String(cTime) + "," + String(val); Serial.println(str_send_data); while(millis() - rTime < 100){ delay(1); } }
ここから今回のチャレンジ内容。はじめてのVisual Studioに戸惑いながらもなんとか動くところまでやってみた。
プロジェクトの作成
新しいプロジェクトがから、Visual C# Windows フォームアプリケーションを選択してプロジェクトを作成すると、以下のようなファイルが自動で生成される。
【Program.csの中身】
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication3 { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
Main関数の中でForm1が生成されているのかな。
【Form1.csの中身】
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication3 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } } }
フォームの作成
ツールボックスを使ってフォームをつくっていく。流石の”Visual”、お手軽。
続いてプロパティウィンドウでプロパティを設定していく。
特に大事な部分はserialPortの設定でArduinoの設定合わせて以下のように設定する。
コード作成
次にSerialPortの受信詩時のイベントを実装する。
プロパティウィンドウでイベントを表示させてDataReceivedの部分をダブルクリックするとForm1.csの中にコードが生成される。
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { }
この中に受信時の動作をつくればよいみたいだ。今回は以下の二つを実行。
1.受信した文字列をテキストボックスに追加
2.受信した文字列を時間とアナログ値で散布図に表示(時間の経過と共に左に流れていく)。
その他に接続ボタンで通信開始、切断ボタンで通信終了するコードを書くと、Form1.csはこのようになる。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace _20140604_serial_test01 { public partial class Form1 : Form { string RxString; public Form1() { InitializeComponent(); } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { RxString = serialPort1.ReadLine(); this.Invoke(new EventHandler(DisplayText)); this.Invoke(new EventHandler(showChart)); } private void button1_Click(object sender, EventArgs e) { serialPort1.Open(); } private void button3_Click(object sender, EventArgs e) { serialPort1.Close(); } private void DisplayText(object sender, EventArgs e) { textBox1.AppendText(RxString + Environment.NewLine); } private void showChart(object sender, EventArgs e) { string[] strArrayData = RxString.Split(','); int x = int.Parse(strArrayData[0]); int y = int.Parse(strArrayData[1]); chart1.Series["Series1"].Points.AddXY(x, y); chart1.ChartAreas[0].AxisX.Maximum = x; chart1.ChartAreas[0].AxisX.Minimum = x - 10000; } } }
processingよりシンプルにできたような気がする。
visual studioの使い方に慣れるまで大変な気もするがなんとかなるかな。
【今回のはまりポイント】
・シリアル通信の設定をどこですれば良いか、Google先生に聞きまくった。
・chartオブジェクトのプロパティ探し。
・イベント実行時のFormの更新が理解できていない。
この部分 ↓ 、おいおい勉強しよう。
this.Invoke(new EventHandler(DisplayText)); this.Invoke(new EventHandler(showChart));
大変参考になりました。ありがとうございました。
C#おもしろいですね。はじめてでしたが、今の印象はJavaより作りやすい気がしてます。
ArduinoのプログラムでSerial通信のbpsが38400になっていますが、9600ではないでしょうか
当方まったくの素人ですので・・・。もしくは38400で問題ないようでしたらご教授願います。
コメントありがとうございます。
通信速度について、38400で問題なく動作しました。9600でも動作すると思います。(試してません。)
ポイントは以下の二つです。
・通信相手の通信速度と合わせる: 今回はC#側のSerialPort の BaudRate。
・通信の量とタイミング : 今回は100ミリ秒に一回の送信。
参考になれば幸いです。