• ベストアンサー

VISCAプロトコル(RS232C通信)のプログラム

VISCAプロトコル(RS232C通信)のプログラムがうまく動きません。 大学の研究にてSONYのEVI-D100というカメラをパソコンから制御する必要が出てきました。 このカメラはVISCAプロトコル(RS232C通信)で制御するらしく、シリアル通信でコマンドを送る以下のようなプログラムをウェブで見つけて参考にしています。 http://onishi-lab.jp/programming/rs232c_win.html しかし、短いコマンド(例:カメラを右にパンする、81 01 06 01 10 10 02 03 FF)は動くのですが、長いコマンド(例:カメラのパンチルト上限を設定、81 01 06 07 00 01 0F 0A 05 00 0F 0E 09 08 FF)になるとコマンド中に0が入ると動いてくれません。また、コマンド中に0がなくても思うような動きをしてくれません。 一応自分で通信タイムアウトは書き加えたのですが、それでもうまく動きません GetCommTimeouts( hCom, &cto ); // タイムアウトの設定状態を取得 cto.ReadIntervalTimeout = 0; cto.ReadTotalTimeoutMultiplier = 0; cto.ReadTotalTimeoutConstant = 1000; cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant =1000; SetCommTimeouts( hCom, &cto ); // タイムアウトの状態を設定 RS232Cについては初心者なのでよくわからないことも多いのですが、どこをどう書き換えれば動くかなどを教えていただけると幸いです。よろしくお願いします。 EVI-D100のマニュアルページへのリンクを貼っておきます。 http://www.totsu.co.jp/isp/ispproducts/pdf/D100_tec.pdf

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

sprintf(send,"\x88\x01\x00\x01\xff"); send_length=5; などと記載されている一連のコマンド設定コードを memcpy(send,"\x88\x01\x00\x01\xff", 5); send_length=5; で解決だと思いますけど。

ario316
質問者

お礼

ありがとうございます。無事正常に動かすことができました。 RS232Cの問題というよりC言語の関数の問題だったんですね。失礼しました。

その他の回答 (2)

noname#144013
noname#144013
回答No.3

ario316さん、はじめまして。 後述した内容をカキコミしようと思っていたところ、既に解決されたようで良かったですね。(^_^) 以下は投稿しようと用意していたものですが、参考までにカキコミしてみます。 ※ario316さんが返答される前のものなので、KY(^^;)な部分は予めご了承ください。 ======================================= まず、【回答:ANo.1】のJaritenCatさんも言われているように、EVI-D100のテクニカルマニュアル をよく読んで、送信するコマンド、データ等の形式(コマンド値、データ範囲、データ長など)が合っ ているかどうかの確認、およびラインモニタなどを使用し、送信したデータ、EVI-D100からの応答 メッセージ等の確認をされた方が良いと思います。 あと、デバッグ用にバイナリデータが送信できる市販またはフリーの「RS-232C通信ソフト」を使用 して、手入力またはマクロ機能(簡易プログラム機能)などを使い、EVI-D100へテストコマンド及び データを送信して正常に送受信できるか確認されるのも良いかと思います。 それと、【回答:ANo.2】のpenguin999さんも指摘されているように、そもそも参考にされている サンプルプログラム自体が間違っています。 (このサンプルを作成&公開された方は、ちゃんとテストされたのでしょうか?) sprintfに限らず、C言語の文字列を扱う標準関数では、文字列の途中にNULLコード ('\x00'、16進値=0x00)を含んだものは扱うことはできません。 なぜなら、NULLコードは文字列の終端コードとして扱われているからです。 関数が文字列を処理している時にNULLコードに達するとそこで処理を終了します。 参考にされているサンプルの例で言うと、   sprintf(send,"\x88\x01\x00\x01\xff"); の部分の実際の処理は、   バッファ"send"には、'\xff'までコピーされずに、"\x88\x01"までしかコピーされない。   ※'\x00'は文字列の終端コードなため。 だと思います。 この関数を実行した後のバッファ"send"の中身は、   0x88、0x01、0x00、・・・・・・・・・  (・・・の部分はsprintfを実行する前の値) となってしまうと思います。(0x00は終端コードとしてsprintfが付加します) 解決策として、ここはpenguin999さんが書かれているとおり、文字列用の関数を使うのではなく、 バッファ転送用の関数(memcpyなど)を使ってデータコピーするのが得策だと思います。 ※memcpy関数は単純に指定したバイト数分のバッファコピーを行います。 C/C++言語の標準関数(ランタイムライブラリ等)の詳細仕様については、お使いの開発環境 付属のマニュアルおよび、C/C++言語関連の書籍等をご覧になってください。 =======================================

ario316
質問者

お礼

詳しい説明どうもありがとうございます。 C言語の方もまだまだ勉強が必要なようです・・・。 精進したいと思います

回答No.1

コマンドを送ったら機器からレスポンスが送信されてくると思うのですが正常が返ってくるのでしょうか? ちらっとマニュアルを見る限りでは、 81 01 06 07 00 01 0F 0A 05 00 0F 0E 09 08 FF は、YYYY=FA50を設定していますが範囲外だと思います。 FA60(-1440)~05A0(1440)に指定しないとだめではないでしょうか。 このコマンドを送ったときエラーは返ってきますか? 通信プログラムが期待通りのデータを送信しているかどうかは、RS-232Cラインモニタなどを使うと分かります。 もし変なデータを送っているのであれば、ソフトの問題でしょう。

ario316
質問者

お礼

ご指摘のとおり、設定パラメータがおかしかったことも一要因だったようです。ご指摘ありがとうございます。符号付16進数のことがよくわかっていませんでした。 コマンドを送ったときにエラーすら帰ってこない状態だったのですが、そちらについてはpenguin999さんからの回答で解決しました。ありがとうございました。