アプリ版:「スタンプのみでお礼する」機能のリリースについて

VISCAプロトコル(RS232C通信)で、やはり長いコマンドを正しく送れない

次のサイトのソースをもとに、SONY EVI-HD1カメラをPCからVC++プログラムで制御しようとしています:
http://onishi-lab.jp/programming/rs232c_win.html

ただし、以前あった以下の質問を参考に、ソースをいくつか修正しています:
http://okwave.jp/qa/q4296092.html

具体的には、下記の変更を加えました:
(1)"sprintf"ではなく"memcpy"関数を使うようにする
(2)"dcb.fOutxDsrFlow = bSet;"の部分は"bSet = dcb.fOutxDsrFlow;" の誤りと思われるので修正

以前の質問では(1)の修正により解決されたようでしたが、実際に試してみると問題がありました。
これは、前の方が質問の中で報告されている通り、

「短いコマンド(例:カメラを右にパンする、81 01 06 01 10 10 02 03 FF)は動くが、長いコマンド(例:カメラのパンチルト上限を設定、81 01 06 07 00 01 0F 0A 05 00 0F 0E 09 08 FF)になるとコマンド中に00が入ると動かない。また、コマンド中に0がなくても思うような動きをしない」

というものです。
私が試したところ(1)の修正に関係なく、上の問題が発生するようです。

・なぜ長いコマンドになると問題があるのか?
・なぜ00が入るとコマンド書き込みが上手くいかないのか?

など見当がつかず、混乱しております。
もし何か心当たりがありましたら教えていただければ大変助かります。

A 回答 (4件)

No.1です。


原因がわかられて何よりです。

ちょっとだけ追加でアドバイスです。
質問文と
>memcpyを使っていても,結局データの一部がNULL文字扱いになっていたことが原因だったようです.
からだと「通信データフォーマットを理解していなかった」と理解することができてしまいます。
誤解がないようにしていただきたいのですが、「RS-232c」は「通信のI/F(H/W)の規格」であって「通信データの規格ではない」ということです。
(さらに厳密にいえば、「RS-232」のRev.cなので「RS-232c」となるのですが)
従って、「通信データ」として「0x00」を送ることは可能です。

No.1では「『プログラム内での』送信データは正しいもの」としてプロトコルアナライザー(ラインモニタ)での確認を勧めましたが、
今回の問題はその手前だったようなので通信系の確認すべき個所を再度纏めておきます。

・(プログラムとして)送信するデータが正しいかどうか
 →H/Wになるべく近いレイヤ(今回ならWriteFile直前)で内容を確認
・ライン上の送信データが正しいかどうか
 →プロトコルアナライザー(ラインモニタ)で確認
・受信されたデータが正しいかどうか
 →受信側デバイスで確認できなくても、
  大抵は受信側デバイスから正常に受信できたかどうかの返答があるのでそれで確認
・根本的に送受信の設定があっているか
 →ラインにクロック信号が無い場合や、データにクロックを埋め込んでいない場合は特に重要。

上記を確認する際に必要となる情報が「通信データフォーマット」ということになります。
    • good
    • 0

ちょっと参考までにコメント


 コマンド送ったあとにACKとか何か返ってきてますよね?
それはどんな内容なんでしょうか?コマンド成功、失敗とも確認した方がいいと思います。
 また、bSet=0とかにしてXフローはOFFなんですか?場合によっては誤動作する可能性があるのでチェックが必要かも。
    • good
    • 0

短いコマンドではデータ中に0があっても無くても動くのでしょうか?


※ 短いコマンドでそのようなデータが作れなかっら確認できませんが

0のデータが入っているときにうまく動かないってのは御自身の
提示URLに書かれてる中に回答が書かれてると思います
(元のサンプルコード自体がテストしてるとは思えないレベルのソースってのがかなりきつい)

>コマンド中に0がなくても思うような動きをしない
ということから何らかの通信トラブルが発生しているのではないかと
思いますが単純に考えられるのは送信オーバランなどですが
結局エラーコードなどを調べた上で何処に問題あるのか
特定する必要があります

#1さんも書かれてるようにプロトコルアナライザお持ちであれば
使うのが確実ですがそんなに安いものでもないので
個人ベースではなかなか手も出せないでしょう
やっぱりシェアウエアになってしまいますが
似たようなことも出来るツールの紹介として
http://www.fukufukudenshi.com/

以前はプロトコルアナライザ使ってましたが此方のソフト
使い出してからはPCだけで事足りる方が多くなりました
    • good
    • 0
この回答へのお礼

ご回答どうもありがとうございます.
#1さんへのお礼の中でも報告させていただいた通り,実はコマンドを一旦stringとして格納していたことが原因でした.
そのため,たとえmemcpyを使っても,0がNULL文字として扱われてしまっていたようです.

また,それが分かった後で色々と再確認してみると「長い文字列では0がなくてもおかしい」というのはそのように見えていただけで正確ではなく,長くても短くても「0」の有無が効いていることが分かりました.

色々と確認不足があったり,また最初の質問で上記に関する情報を省略していたりと,恥ずかしい限りですが,勉強になりました.

また,今回の質問がきっかけでプロトコルアナライザについて知ることができました.
教えていただきとても感謝しております.
シェアウェアですが,今後のことを考えてプロトコルアナライザの導入も考えてみようと思います.
ご親切な回答をいただきどうもありがとうございました.

お礼日時:2010/02/18 18:33

色々と考えられることはあるのですが、とりあえず


WriteFile()の戻り値は確認してください(正確にはエラー発生時に取得したGetLastErrorの値)。
戻り値や引数でエラー値が取得できる関数を使用しているにも関わらず、これを使用して確認をしないのは原因追及にはなりません。

さて、原因推測です。
・デバイス、PCのボーレート等の設定ミス
・USB-232c変換ケーブルを使用している為必要線が動作していない
・デバイスがある一定以上のデータ長のデータを受信できない
・その他の要因

何処まで動作しているのか確認するためには別の類似質問でも回答したことがありますが、
「プロトコルアナライザー」でラインを見るのが確実なのですが……
そうしないと、通信関連は全てそうですが
・そもそもPCから送信されていない
・送信されているがデータがおかしい
・送信データは正しい→受信側の問題
というのが切り分けられません。
    • good
    • 0
この回答へのお礼

素早いご回答をいただき,心より感謝いたします.
アドバイスをもとに原因を探ってみたところ,初歩的なミスであることがわかりました.

実は,関係がないと思い質問の中に書いていなかったのですが,サンプルプログラムにほかの修正も加えていました:
memcpy()の中に直接コマンド文字列を書くのではなく,一旦stringクラス変数として格納してc_str関数で読み出していました.
そのため,memcpyを使っていても,結局データの一部がNULL文字扱いになっていたことが原因だったようです.
stringクラスの仕様を理解していなかったことによる,恥ずかしいミスでした.

また,上記のようなことを最初の質問で書かなかったことも反省しております.
これは,最初にWriteFile関数の戻り値を確認していたのですが,そのとき戻り値が1だったためWriteFile()以降に問題があると早合点してしまったことによるものでした.

その他,ボーレートやケーブル,デバイスの受信できるデータ長なども念のため確認しましたが,これらは問題ありませんでした.

プロトコルアナライザーについては,今まであまり知らなかったのですが,今後のためにも詳しく調べてみたいと思います.
丁寧に対応していただき,どうもありがとうございました.

お礼日時:2010/02/18 18:19

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!