« 秋月の3DセンサーをRS-232Cで使いたい | トップページ | 2点の緯度・経度から距離を求める(PocketPC対応) »

2008/06/02

3Dセンサーのプログラム

ぷろぐらむとか」のTDControl2(C++)を参考に,C#でTDS01Vのデータを取得するプログラムを作っていましたが,とりあえず,ボタンを押すたびにデータを取得するプログラムができました。エラー処理とか,タイミングとか細かいところは全く見ていませんので,自己責任で試してみてください。フォームに必要なのは

  • シリアルポート選択用のコンボボックス(cboPort)
  • シリアルポート接続用ボタン(btnConnect)
  • 計測開始用ボタン(btnStart)
  • 計測表示用ボタン(btnMeasure)
  • 表示用テキストボックス(txtDisplay)

の五つです。ボタンを押す代わりにタイマー起動させるようにすれば,定期的にデータを取得できます。

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace TDS01V
{
    public partial class frmMain : Form
    {
        private TDControl tds;
        private AllData meas = new AllData();

        private const int INTERVAL = 0;       // 1 time
        private const int BAROMETER = 10133;  // 1013.3 hPa
        private const int VARIATION = 3540;   // W6 deg

        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            tds = new TDControl ();
            btnConnect.Text = "Connect";
            btnStart.Text = "Start";
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (btnConnect.Text == "Connect") {
                tds.Open(cboPort.Text);
                btnConnect.Text = "Disconnect";
            } else {
                tds.Close();
                btnConnect.Text = "Connect";
            }
        }

        private void cboPort_Click(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();
            Array.Sort(ports);
            cboPort.Items.Clear();
            foreach (string s in ports)
                cboPort.Items.Add(s);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (btnStart.Text == "Start") {
                if (tds.Init(INTERVAL, BAROMETER, VARIATION)) {
                    btnStart.Text = "Stop";
                }
            } else {
                tds.Stop();
                btnStart.Text = "Start";
            }
        }

        private void btnMeasure_Click(object sender, EventArgs e)
        {
            meas = tds.Measure();
            txtDisplay.Text = meas.DirDeg.ToString() + " " + meas.Altitude.ToString();
        }
    }
}

3Dセンサーは改行コードがCR+LFになっています。SerialPort.WriteLine()は行末にNewLineを出力するので文字列にCRだけを付加しています。コマンドは文字列で与えてもいいのですが,整数値を16進数に変換するようにしました。受け取ったデータも整数値ですので,値によっては10.0で割る必要があります。コマンドを送って,データを受け取るまでに,待つ必要があるはずですが,とりあえず動作しているので,放置しています。もしかしたら,1回分遅れたデータを取得しているのかもしれません。ステータスを見て変換終了を確認するべきだと思います。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;

namespace TDS01V
{
    public struct AllData
    {
        public int MagVX, MagVY, MagVZ;
        public int DirDeg;
        public int AccVX, AccVY, AccVZ;
        public int RollDeg, PitchDeg;
        public int Barometer, Altitude;
        public int Temp, Volt;
    }

    class TDControl
    {
        private const int CMD_SET_CONDITION  = 0x05;
        private const int CMD_SET_SENSORTYPE = 0x0D;
        private const int CMD_RESET          = 0x0F;
        private const int CMD_START          = 0x21;
        private const int CMD_STOP           = 0x23;
        private const int CMD_MAGINIT        = 0x27;
        private const int CMD_READ           = 0x29;
        private const int CMD_CHECK          = 0x2B;
        private const int CMD_ROMVER         = 0x5F;
        private const string CRLF = "\r";

        public SerialPort port = new SerialPort();
        private bool opened;

        public TDControl()
        {
            opened = false;
            port.WriteTimeout = 2000;   // timeout 2000ms
            port.ReadTimeout = 2000;    // timeout 2000ms
        }

        public bool Open(string com)
        {
            port.PortName = com;
            port.BaudRate = 9600;
            port.Parity = Parity.None;
            port.DataBits = 8;
            port.StopBits = StopBits.One;
            try {
                port.Open();
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble opening the SerialPort! " + ex.ToString());
                return false;
            }
            opened = true;
            return true;
        }

        public bool Close()
        {
            try {
                port.Close();
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble closing the SerialPort! " + ex.ToString());
                return false;
            }
            opened = false;
            return true;
        }

        public bool Init(int interval, int hpa, int variation)
        {
            if (opened) {
                for (int i = 0; i < 3; i++) {
                    if (GetCommand(CMD_CHECK) != "") break;
                    if (i == 2) return false;
                }
                if (!Command(CMD_RESET))
                    return false;
                GetCommand(CMD_CHECK);
                GetCommand(CMD_CHECK);
                GetCommand(CMD_ROMVER);
                if (!SetCommand(CMD_SET_CONDITION, interval.ToString("X2") + hpa.ToString("X4") + variation.ToString("X4")))
                    return false;
                if (!SetCommand(CMD_SET_SENSORTYPE, "F7"))
                    return false;
                if (!Command(CMD_MAGINIT))
                    return false;
            } else {
                return false;
            }
            return true;
        }

        public bool Stop()
        {
            if (opened) {
                if (!Command(CMD_STOP))
                    return false;
            } else {
                return false;
            }
            return true;
        }

        public AllData Measure()
        {
            AllData meas = new AllData();
            if (opened) {
                Command(CMD_START);
                string data = GetCommand(CMD_READ);
                meas.MagVX = Convert.ToInt16(data.Substring(0, 4), 16);
                meas.MagVY = Convert.ToInt16(data.Substring(4, 4), 16);
                meas.MagVZ = Convert.ToInt16(data.Substring(8, 4), 16);
                meas.DirDeg = Convert.ToInt16(data.Substring(12, 4), 16);
                meas.AccVX = Convert.ToInt16(data.Substring(16, 4), 16);
                meas.AccVY = Convert.ToInt16(data.Substring(20, 4), 16);
                meas.AccVZ = Convert.ToInt16(data.Substring(24, 4), 16);
                meas.RollDeg = Convert.ToInt16(data.Substring(28, 4), 16);
                meas.PitchDeg = Convert.ToInt16(data.Substring(32, 4), 16);
                meas.Barometer = Convert.ToInt16(data.Substring(36, 4), 16);
                meas.Altitude = Convert.ToInt16(data.Substring(40, 4), 16);
                meas.Temp = Convert.ToInt16(data.Substring(44, 4), 16);
                meas.Volt = Convert.ToInt16(data.Substring(48, 4), 16);
            }
            return meas;
        }

            
        private bool Command(int cmd)
        {
            string _cmd = cmd.ToString("X2") + CRLF;
            try {
                port.WriteLine(_cmd);
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble writing the SerialPort! " + ex.ToString());
                return false;
            }
            string status;

            try {
                status = port.ReadLine();
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble reading the SerialPort! " + ex.ToString());
                return false;
            }
            if (cmd + Convert.ToInt16(status.Substring(0, 2), 16) != 255)
                return false;
            return true;
        }

        private bool SetCommand(int cmd, string data)
        {
            string _cmd = cmd.ToString("X2") + data + CRLF;
            try {
                port.WriteLine(_cmd);
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble writing the SerialPort! " + ex.ToString());
                return false;
            }
            string status;

            try {
                status = port.ReadLine();
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble reading the SerialPort! " + ex.ToString());
                return false;
            }
            if (cmd + Convert.ToInt16(status.Substring(0, 2), 16) != 255)
                return false;
            return true;
        }

        private string GetCommand(int cmd)
        {
            string _cmd = cmd.ToString("X2") + CRLF;
            try {
                port.WriteLine(_cmd);
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble writing the SerialPort! " + ex.ToString());
                return "";
            }
            string data;

            try {
                data = port.ReadLine();
            }
            catch (Exception ex) {
                System.Diagnostics.Trace.WriteLine("Trouble reading the SerialPort! " + ex.ToString());
                return "";
            }
            return data;
        }
    }
}

|

« 秋月の3DセンサーをRS-232Cで使いたい | トップページ | 2点の緯度・経度から距離を求める(PocketPC対応) »

「プログラミング」カテゴリの記事

「電子工作」カテゴリの記事

コメント

こんにちは、今僕もTDS01VをJAVAを使って制御するプログラムを書いています!
まだ全然エラーばっかりですが。。。

投稿: mori | 2008/10/30 16:11

JAVAはさっぱり分かりません。苦労話も含め、WEBでぜひ公開してください。

投稿: Nori-chan | 2008/10/30 16:54

自分も今四苦八苦中です。。。
完成したら是非公開させてもらいたいと思います☆

投稿: mori | 2008/10/30 17:37

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/7916/41409572

この記事へのトラックバック一覧です: 3Dセンサーのプログラム:

« 秋月の3DセンサーをRS-232Cで使いたい | トップページ | 2点の緯度・経度から距離を求める(PocketPC対応) »