mengineer's blog

ニッチなネタばかりですが。

JAIのCameraLinkでコマンド送受信 C#編

前回の続き、実際のソフトの説明ですね、環境は例によってVisualStudio2005です。

C#でシリアルポート通信するには、SerialPortクラスを使用します、
下記のようにusing System.IO.Ports; を追加しておきます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;                //SerialPortクラス

シリアル通信の設定の詳細は、”C# シリアル通信”等で検索すると、
判りやすいサイトが沢山出てきますので、そちらを参照して下さい。

ということで、COMポートの初期設定の部分から見てみましょう。

COMポートの初期設定

いきなりソースコードですが、CameraPortOpenはCOMポートをOpenする処理、
CameraComに”COM3”等を文字列で指定し、Open成功するとtrueが戻ります。

    public partial class Form1 : Form
    {
        public SerialPort CamPort;               //カメラ通信用COMポート

        public Form1()
        {
            InitializeComponent();
        }
        private bool CameraPortOpen(string CameraCom)
        {
            bool result = false;                        //戻り値

            CamPort = new SerialPort(CameraCom);        //CameraComはCOMポート名(COM3等)
            CamPort.BaudRate = 9600;                    //ボーレート 9600bps
            CamPort.DataBits = 8;                       //データビット 8bit
            CamPort.StopBits = StopBits.One;            //ストップビット 1bit
            CamPort.Parity = Parity.None;               //パリティ無し
            CamPort.NewLine = "\r\n";                   //改行コード <CR><LF>

            //PortOpen処理
            if (CamPort != null)               
            {
                if (CamPort.IsOpen) CamPort.Close();    //既にOpenされている場合、一旦閉じる

                try
                {
                    CamPort.Open();                     //Open処理
                    result = true;                      //Open出来れば、戻り値をtrueに変更
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);        //Open出来なかった場合、エラー表示
                }
                finally
                {
                    if (!CamPort.IsOpen) CamPort.Dispose();
                }
            }
            return result;
        }
    }

ボーレート等の通信設定は、カメラのマニュアルに記載された内容に従います、
また改行コードは<CR><LF>なので、CamPort.NewLineで設定しています。

通信ポートを閉じるのは下記の処理、SerialPortクラスにCloseの処理も有るので、
それを呼ぶだけです、シンプルですね。

        private void CameraPortClose()
        {
            if (CamPort != null)
            {
                if (CamPort.IsOpen) CamPort.Close();
            }
        }

カメラとの送受信処理

簡単なサンプルです、textboxに文字列を入れて”コマンド送信”ボタンを押すと、
そのコマンドを送り、カメラからの応答文字列をlabel1に表示するもの。

f:id:mengineer:20160829135716p:plain

ソースコードは下記、SendCommandが実際の送受信の処理部分です。

        private void button1_Click(object sender, EventArgs e)
        {
            //COM3をOpen出来ない場合には、エラー終了
            if (!CameraPortOpen("COM3"))
            {
                MessageBox.Show("CAMERA通信ポートOpenエラー");
                return;
            }
            //コマンド送信、カメラ応答をlabel1に表示
            if (textBox1.Text != "")
            {
                label1.Text = SendCommand(textBox1.Text);
            }
            //COM3を閉じる
            CameraPortClose();
        }
        private string SendCommand(string Command)
        {
            string reply = "";                          //カメラ応答文字列用

            CamPort.DiscardInBuffer();              //受信バッファクリア
            CamPort.DiscardOutBuffer();             //送信バッファクリア

            CamPort.Write(Command + "\r\n");        //コマンド送信

            //以下はカメラ応答待ちループ
            for (int i = 0; i < 100; i++)
            {
                System.Threading.Thread.Sleep(20);
                if (CamPort.BytesToRead > 0)        //応答データが入ったら
                {
                    try
                    {
                        reply = CamPort.ReadLine(); //データを改行コードまで読む
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    break;
                }
            }
            return reply;
        }

コマンドの種類によりカメラからの応答時間が異なっているところがミソです。

応答待ちのループを廻し、データが戻って来たら(CamPort.BytesToRead > 0)、 CamPort.ReadLineでデータを読むようにしています、Sleepが20mS×100回で、
このサンプルでは、最長約2秒まで応答を待てることになります。

カメラによっては、処理を実行するのに2秒以上掛かるコマンドも有り得るため、
ループ回数を100固定では無くて変数で渡す等、工夫が必要かもしれません。

シリアルポートでデータ受信割込が発生するので、それを使う方法も有りそう?
なのですが、処理がややこしそうで、今回はそこまで研究出来ませんでした。

実行時の画面例です、GAコマンドはカメラのゲインを設定するコマンドです。

設定を問合わせした場合 → 現状の設定 "GA=0" が戻ってくる

f:id:mengineer:20160829144332p:plain

GA=100に設定した場合 → GA=100に設定後、"COMPLETE"が戻ってくる

f:id:mengineer:20160829144351p:plain

存在しないコマンドを送った場合 → "01 Unknown Command!!" が戻ってくる

f:id:mengineer:20160829144406p:plain

範囲外のパラメータを送った場合 → "02 Bad Parameter!!" が戻ってくる

f:id:mengineer:20160829144422p:plain