回路図を書く程でもなかったので、配線イメージ図っていう感じで
はじめはArduinoのスケッチで、起動時数回取得したAD値をアベレージして、オフセット値として、その後、毎回数回繰り返し取得したAD値の平均からオフセットを引いいて、数値をシリアルで画面に出して・・・ってやってみたんですが、数値がパラパラ変わるのは分かるんですが、早すぎて、何が起こってるんだかよくわからない・・・。
そこで、オフセットとか平均はとりあえずおいておいて、取得したAD値をシリアルに垂れ流して、パソコン側でグラフ表示して、何が起こってるか見てみようと思いました。
で、簡略化したスケッチが
#include "Arduino.h" // 端子の割当。 const int PIN_ACC_X = 0; const int PIN_ACC_Y = 1; const int PIN_ACC_Z = 2; // 変数宣言。 int adX = 0, adY = 0, adZ = 0; byte sendData[8]; void setup() { // シリアルポートの初期化。 Serial.begin(9600); } void loop() { // AD値取得。 adX = analogRead(PIN_ACC_X); adY = analogRead(PIN_ACC_Y); adZ = analogRead(PIN_ACC_Z); // 送信データ構成。 sendData[0] = 0x02; sendData[1] = (byte)((adX & 0xff00) >> 8); sendData[2] = (byte)(adX & 0x00ff); sendData[3] = (byte)((adY & 0xff00) >> 8); sendData[4] = (byte)(adY & 0x00ff); sendData[5] = (byte)((adZ & 0xff00) >> 8); sendData[6] = (byte)(adZ & 0x00ff); sendData[7] = 0x03; // 送信。 for (int i = 0; i < 8; i++) { Serial.write(sendData[i]); } delay(200); }
これで、シリアルに吐き出されたデータをPCに側で受信して、グラフ表示するプログラムを作って、表示させたら、こんな感じになりました。
赤・青・緑がそれぞれの軸のAD値で、加速度センサのブレッドボードを加速度センサの3軸方向にそれぞれ平行に振ってみたものです。3つの黄色の枠でそれぞれの方向に反応しているのがわかります。赤だけオフセットが大きいですが、赤はZ軸というか重力方向の軸です。重力加速度の影響かな?すみません、加速度センサのことをあまり勉強してないのでわかりません。でも、ためしにブレッドボード(Z軸の方向)をひっくり返したらオフセットが下側に行ったので、おそらく重力によるものでしょう。
ちなみにグラフ表示プログラムは Visual Studio 2010 のグラフ表示コントロールを使っています。
ソースはこんな感じ。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Management; using System.Windows.Forms.DataVisualization.Charting; using System.IO.Ports; namespace SerialGraph { class acceleration { private int valueX = 0; private int valueY = 0; private int valueZ = 0; public acceleration(int x, int y, int z) { this.valueX = x; this.valueY = y; this.valueZ = z; } public int getValue(int no) { if (no == 0) { return this.valueX; } else if (no == 1) { return this.valueY; } else { return this.valueZ; } } } public partial class frmMain : Form { // キーと値をセットで保存。「COM1」が「標準シリアルポート1」など。 Dictionary<string, string> ComPortTable = new Dictionary<string, string>(); // 取得データの履歴を保存。 const int MAX_DATA_COUNT = 40; Queue<acceleration> dataHistory = new Queue<acceleration>(); // グラフ構成用。 Series[] series = new Series[3]; public frmMain() { InitializeComponent(); // シリアルポートの実装状況を取得。 ManagementClass mcW32SerialPort = new ManagementClass("Win32_SerialPort"); foreach (ManagementObject aSerialPort in mcW32SerialPort.GetInstances()) { ComPortTable.Add( (string)aSerialPort.GetPropertyValue("Caption"), (string)aSerialPort.GetPropertyValue("DeviceID")); } string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { if (!ComPortTable.ContainsValue(port)) { ComPortTable.Add(port, port); } } } private void drawChart(Chart chart) { try { chart.Series.Clear(); for (int i = 0; i < 3; i++) { series[i].Points.Clear(); foreach(acceleration acc in dataHistory) { series[i].Points.Add(new DataPoint(0, acc.getValue(i))); } } for (int i = 0; i < 3; i++ ) { chart.Series.Add(series[i]); } } catch (Exception ex) { string errMsg = "@showChart(): "; errMsg += ex.Message; Console.WriteLine(errMsg); MessageBox.Show(errMsg); } } private void frmMain_Load(object sender, EventArgs e) { int i; // 画面の構成。 // シリアルポートのコンボボックス構成。 cmbPortNo.Items.Clear(); foreach (string aPortCaption in ComPortTable.Keys) { cmbPortNo.Items.Add(aPortCaption); } if (ComPortTable.Count > 0) { cmbPortNo.SelectedIndex = 0; } else { MessageBox.Show("シリアルポートが存在しません。"); } // シリアルポート「接続」「切断」ボタン。 btnConnect.Enabled = true; btnDisconnect.Enabled = false; // グラフ表示領域の構成。 chart.ChartAreas[0].AxisX.MinorGrid.Enabled = true; chart.ChartAreas[0].AxisY.Minimum = 0; chart.ChartAreas[0].AxisY.Maximum = 1023; // グラフ要素の初期化。 for (i = 0; i < 3; i++) { series[i] = new Series(); series[i].ChartType = SeriesChartType.FastLine; series[i].IsVisibleInLegend = false; } // グラフ線色設定。 series[0].Color = Color.Red; series[1].Color = Color.Green; series[2].Color = Color.Blue; // チャート表示用データのクリア。 while (dataHistory.Count <= MAX_DATA_COUNT) { dataHistory.Enqueue(new acceleration(0, 0, 0)); } // タイマーを1秒(1000ms)周期に初期化。 timer.Interval = 1000; timer.Enabled = true; } // 接続ボタンのハンドラ。 private void btnConnect_Click(object sender, EventArgs e) { try { string comPort = ComPortTable[cmbPortNo.SelectedItem.ToString()]; if (comPort != null) { // COMポート接続。 serialPort.PortName = comPort; if (serialPort.IsOpen) { MessageBox.Show("既に" + comPort +"はオープンされています。"); } else { serialPort.BaudRate = 9600; serialPort.Parity = System.IO.Ports.Parity.None; serialPort.StopBits = System.IO.Ports.StopBits.One; serialPort.DataBits = 8; serialPort.Open(); btnConnect.Enabled = false; btnDisconnect.Enabled = true; } } } catch (Exception ex) { if (serialPort.IsOpen) serialPort.Close(); string errMsg = "@btnConnect_Click(): "; errMsg += ex.Message; Console.WriteLine(errMsg); MessageBox.Show(errMsg); btnConnect.Enabled = true; btnDisconnect.Enabled = false; } } // 切断ボタンのハンドラ。 private void btnDisconnect_Click(object sender, EventArgs e) { try { if (serialPort.IsOpen) { serialPort.Close(); btnConnect.Enabled = true; btnDisconnect.Enabled = false; } } catch (Exception ex) { string errMsg = ex.Message; Console.WriteLine(errMsg); MessageBox.Show(errMsg); } } // シリアルポート受信ハンドラ。 private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { byte[] rcvData = new byte[8]; ushort adX, adY, adZ; //int readCount; try { //serialPort.Read(rcvData, 0, 1); rcvData[0] = (byte)serialPort.ReadByte(); if (rcvData[0] == 0x02) { //readCount = serialPort.Read(rcvData, 1, 7); // ↑ 7byte取得に設定しても5~6byteのみ取得する。受信が間に合っていない? // ↓ 1byteずつ同期受信に変更。 for (int i = 1; i < 8; i++) { rcvData[i] = (byte)serialPort.ReadByte(); } if (rcvData[7] == 0x03) { // コマンド解析。 adX = (ushort)((((ushort)rcvData[1]) << 8) + (ushort)rcvData[2]); adY = (ushort)((((ushort)rcvData[3]) << 8) + (ushort)rcvData[4]); adZ = (ushort)((((ushort)rcvData[5]) << 8) + (ushort)rcvData[6]); // キューに登録。 dataHistory.Enqueue(new acceleration((int)adX, (int)adY, (int)adZ)); } } } catch (Exception ex) { string errMsg = ex.Message; Console.WriteLine(errMsg); MessageBox.Show(errMsg); } } // タイマのハンドラ。 private void timer_Tick(object sender, EventArgs e) { // キューの最大値を超えたら、古いものから削除。 while (dataHistory.Count > MAX_DATA_COUNT) { dataHistory.Dequeue(); } // グラフの再描画。 drawChart(chart); } } }
0 件のコメント:
コメントを投稿