dsPIC33Eでのインプットキャプチャの問題点と解決方法

このQ&Aのポイント
  • dsPIC33Eでのインプットキャプチャを用いてラインカメラの出力の幅を計測する際に、問題が発生しています。
  • 現在のプログラムでは、カメラ出力が無い場合でもキャプチャが行われてしまい、正しい計測ができません。
  • 解決策として、インプットキャプチャを特定の条件下でのみ行うように改良する必要があります。
回答を見る
  • ベストアンサー

dsPIC33E でのインプットキャプチャについて

問題点 概要: インプットキャプチャを用いて、ラインカメラの出力の幅を計測しようと考えています。 しかし、カメラ出力が無い場合でも、キャプチャをしてしまいます。 SHOEISHAの「組込みマルチタスクプログラミング」等の書籍でも勉強していますが 分かりません。 何かアルゴリズムのお勧めの書籍等も教えて頂けると幸いです。 添付画像のような信号図になります。 仕様: ラインカメラ:投光器を用いて、物体を検知すると信号が「L」になる。 そのエッジをキャプチャし、パルス幅を計測する。 ※但し、現状はエッジを検出すると、あるピンを反転させてキャプチャしたかの点検をしています。(オシロにて確認) 動作詳細: ・動作は120MHzです。 ・カメラはPICからクロックパルスを送り、それに応じて出力を返す。 1MHzのクロック(T=1[us])で129発。 その後は出力はOFFになり、リセットパルスが入力させるまで、信号を出力しない。 ・タイマ2にて上記クロックパルスをカウントし、130回目で、割込み。 (後にデータ送信等を行う) ・タイマ3にて500[us]毎にリセットパルスを送信を、割込みにて行う。 これでカメラがリセットされる。 上記のタイマ2での割込み後です。 ・メインループ内では、インプットキャプチャフラグを見ており、フラグONで RB13ピンを反転させる。 (後に、タイマ1を用いたキャプチャ値の計算を実装予定) 問題点 詳細: カメラの前に物体が無いと、信号は「H」です。 しかし、129回クロックパルスを与えると、カメラ出力は「L」になります。 この部分も検知してしまい、冒頭に述べたように、「カメラ出力が無い場合でもキャプチャをする」事態になっています。 (1)物体を検知していない状態のカメラ出力   ここでは、本来であればキャプチャは行わない ____________|¯¯¯¯¯¯¯¯¯|_________________ (2)物体を検知した状態 ____________|¯¯¯|___|¯¯¯¯ |_________________ 現状のプログラムでは、(1)の場合のエッジを検知してしまいます。 目的は(2)の状態の中央部のエッジ2つのみをキャプチしたいのです。 考察 調査した点: (1)main内のwhile(1)内で、無限にキャプチャのフラグを見ていますので タイマ2の値でのifを付けた。 TMR2が、1<TMR2<129の間のみキャプチャフラグを見る ! (1-1)上記の改良で、キャプチャフラグ検知後に、TRM2の条件分岐 (2)キャプチャを行うタイミングでのみ、インプットキャプチャをONにする。 リセットパルス後、インプットキャプチャON、クロックパルス130回目でインプットキャプチャOFF いずれも、うまくいきませんでした。(カメラが物体を検知していないのに、キャプチャをすると出力反転するピンが反転している) 要約は、 mainの無限ループ内でインプットキャプチャを行っており、それを条件に合わせてON/OFFしたいのですが、上手く行きません。 長文になりましたが宜しくお願い致します。 参考文献等の案内でも大歓迎ですのでお願いします。

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

  • ベストアンサー
  • koujikuu
  • ベストアンサー率43% (428/992)
回答No.2

No.1 補足 これはPICの場合で、dsPICでは違うかも知れません <IFS0bits.IC1IF> のチェックのみでLEDを点滅させていますが、IC1IFフラグはIC1IE (IC1割り込み許可フラグ) の状態にかかわらずセットされます IC1割り込み禁止中にLED点滅を止める場合は、IC1IEを考慮する必要があります TSL1401CLのデータシートでは、SCKに5K~8MHzの幅があり、ソフトウェアでSCKを出力しSCK立下りのタイミングでデータを読み取っても問題ないと考えます 又はSPI通信(ダミーデータを出力しシリアルデータを受け取る) SI周期でシャッタースピードが規定されるので、タイマ割り込みで同期を取る パルス幅をキャプチャする方法では、SIの立ち上がりを基点として、次のSCK立下りでスタート、SCK128回目の立下りまでHIGH / LOW データパルス幅をすべて記録する必要があります (幅の狭いパルスはノイズ、ゴミとして除外する) 参考になれば幸いです。

Snoodam
質問者

お礼

TAOS社のイメージセンサの仕様書までご確認頂きありがとうございます。 頂いたアドバイスを基に試してみます。 今度もお時間があれば宜しくお願い致します。

その他の回答 (1)

  • koujikuu
  • ベストアンサー率43% (428/992)
回答No.1

dsPICは未経験なのでプログラムのアドバイスは出来ませんが ラインカメラ=ラインスキャンカメラの事だと思われ、シフトクロックで順次データが出力されるタイプです シフトクロックに連動して128画素データを読み込み比較した方が良いと思われます。 (出力されるデータはアナログ値なので、A/D変換するか、コンパレータでしきい値を設定する必要があります) 参考先 http://blog.digit-parts.com/archives/51911667.html http://blog.digit-parts.com/pdf/SEN917_LE_N_SU13.pdf ラインカメラの種類が違う場合は、本回答は無視して下さい

Snoodam
質問者

お礼

koujikuu様: アドバイスありがとうございます。 添付して頂きました、ラインスキャンカメラのそのものズバリを使用しています。 但し、OPアンプ内蔵型を使用しており。今回の1MHzにOPAMPが対応しないので、OPAMPは変更していますが。 現状、コンパレータを使用しております。(AD変換では、500usの周期に間に合いそうもないので) もしお時間がおかりであれば再度の相談に乗って頂けないでしょうか。 1.プログラムの構成についてです。 (1)コンパレータ出力ピン→どこかのデジタル入力ピンに入力(RB13と仮定) (2)char comp_out[127]に値の取り込み  ※このイメージが出来ません。もしRB13ピンにコンパレータ出力を入力するとして    comp_out[i]=ROPRBbits.RB13; としてfor を回すして、コンパレータの実時間との整合性はどう取ればいいのでしょうか。 現在PWMモジュールで1us毎にパルスを与えていますので、カメラの出力も1usでOUTされます。 1us毎に comp_out[i]=ROPRBbits.RB13; が働くプログラムのイメージが出来ません。 ニュアンスだけでも結構ですので、ご助言頂けると幸いです。 2.ラインスキャンカメラの扱いについて 私が言うのは不遜なのですが、koujikuu様が今まで回答されてきました履歴を拝見させて頂き 素晴らしい経験と幅広い知識をお持ちということが分かりました。 (以前の私の質問にも回答を頂き、無事解決しました。ありがとうございます。) 下名は、マイコンのプログラミングを聞ける人が周りにおらず、また経験も浅いので まだまだ「不文律」のようなものが分かっておりません。 前置きが長くなりましたが、ラインスキャンカメラと言うのは >シフトクロックに連動して128画素データを読み込み比較した方が良いと思われます。 との使い方が普通なのでしょうか。 (すみません。文章で書くとkoujikuu様を疑っている様にも見えますが、決してその意図はございません) 「自分でアルゴリズムを考える」ことの大切さも重々承知しておりますが、先人が考えてきたものは有用だからこそ残っているとも考えております。 その観点からも、「通常のラインスキャンカメラの使い方」を知りたく思います。 トラ技やインターフェース等でも、勉強しておりますが、やはり「生の言葉」は重みが違います。 もし、お時間が許すのであればkoujikuu様のお言葉を頂けると幸いございます。 長々と厚顔無恥なお願いで申し訳ございません。   

関連するQ&A

  • AVRのインプットキャプチャについて

    AVRのインプットキャプチャを利用してパルス立ち上がりエッジ間の時間を計測したいのですが、どうも計算が合いません。知恵を貸してください・・・ 1MHzの駆動でカウンタの分周が64分周なら単純に1カウント64μSecですよね? 実際に計測しますと130Hzのパルス立ち上がりエッジ間に60カウントしました。ですので・・・ 60パルス*64μSec=3840μSec となると思うのですが、 130Hzならパルス立ち上がりエッジ間は・・・ 1Sec/130Hz=0.007692Sec すなわち7692μSecですよね? もし計算間違ってたら教えてください。 計測対象のパルスですが、これはPCファンの回転信号を計測しました。 DSOnanoで計測したら130Hzでした。 AVRのタイマ/カウンタの値はUARTで確認しました。 AVRのタイマーの設定を間違ってたらいけないので記載していきます。以下の通りです。 TIMSK = (1<<ICF1); TCCR1B = (1<<ICES1)|(3<<CS10);//上りエッジの64分周

  • 16ビットPICのインプットキャプチャについて

    dsPICやPIC24の16ビットPICのインプットキャプチャについて お世話になります。16ビットPICのインプットキャプチャは、8ビットのPIC(特に16F1ファミリ)のCCPモジュールと使用方法がどこか違うのでしょうか。 16ビットPICはバッファを4つ持っており、値を4つまで保持できるはずですが、パルス幅計測がうまくできません。 現在dsPIC33Eを使っています。 皆様のアドバイスを頂けると幸いです。 問題点: 以下のパルスを計測すると、値がおかしくなる。 ㅤAㅤㅤ Bㅤㅤ CㅤㅤD ___|¯¯¯¯|_________|¯¯¯¯¯|______ ・B-Aでは正常 ・D-Cでも正常 ・しかし、C-Bをすると値が狂う。 値の確認方法: LCDにて表示。 タイマ1をキャプチャ用タイマとしている。(分解能は0.1336us) オシロでの計測値が120usの時、LCDの表示は「896」なので 896*0.1336=119.705us なので、正常と判断しています。(B-AやD-Cでパルス幅を計算時) プログラム仕様: メインループ内で、キャプチャを行う。 IC1で立下りエッジを検出 Captime_down[0]=IC1BUF;ㅤㅤ上図のDエッジ Captime_down[1]=IC1BUF;ㅤㅤ上図のBエッジ IC2で立ち上がりエッジ検出 Captime_rise[0]=IC2BUF;ㅤㅤ上図のCエッジ Captime_rise[1]=IC2BUF;ㅤㅤ上図のAエッジ 2msでタイマ3割込みが入り、値を計算し、表示 Captime[0]=Captime_down[0]-Captime_rise[0];ㅤㅤD-C Captime[1]=Captime_down[1]-Captime_rise[1];ㅤㅤB-A この時にC-B Captime_rise[0]-Captime_down[1] を行うと値が理論値をはるかに超えた19000等の値になります。 考察: インプットキャプチャに使用のタイマ1のオーバーフローも疑いましたが オーバフローしている形跡はありません。以下を試しました。 (1)タイマ1は0.1336usでカウントUP。 FFFFまで8755us=8.7ms必要。今回は2msで回し、値もクリアしている。 (TMR1=0) (2)タイマ1がオーバーフローすると、別ピンがON →ONしていないのでオーバーフローしない バッファの使い方?がおかしいのか? Captime_rise[0]-Captime_down[1] と配列の要素が違う計算(バッファの位置とでも言うのでしょうか、 キャプチャしたタイミングの違う値→[0]でのエッジ検出と[1]で タイマ1の値が変わる?) リファレンスマニュアルや書籍も読んだのですがわかりません。 アドバイスを頂けると幸いです。

  • IC16F1829でのCCPモジュールについて

    PIC16F1829でのCCPモジュールを使用した、パルス幅のキャプチャについて 割込み関数を用いたら、mainループ内でCCP*IFを検知しません。状況: CCPモジュールを用いて、パルスの幅を計測しようとしています。CCP単独での動作では、パルス幅を計測できました。 ここでの「単独」とは、割り込み関数を用いないmainループ内での処理です。 //「単独」での仕様 // (1)CCP2モジュールでPWMパルスを発生する (2)上記パルスをCCP1で立下がり、CCP4で立上がり検出する (3)上記の値の差を計算 (4)I2C通信でLCDに表示 これで、タイマ1の分解能を1usに設定し、パルスのOFF時間を計測できました。 問題: PICにラインカメラを接続し、カメラの出力パルスOFF幅を計測したいのですが できません。 原因: mainループ内 if(CCP1IF){ } に処理が入らない。 質問: なせCCP1IFを検知できないのでしょうか。 割込み関数を入れると、検知できないようになってしましいます。 何か競合するのでしょうか。 PICでは割込み関数の処理が終わるまでは、ほかの割込み禁止なはずなので 下に書いてある、フローチャート通りにプログラムが動くはずなのですが・・ 私の力不足で、うまく動作しません。 後閑さんの本やPIC16F1829のデータシートも見ましたが原因がわかりません。 よろしくお願いします。 仕様(フローチャート): 概要 割込み関数は ・タイマ0 (CCP2のパルスカウント) キャプチャした値の計算とシリアル送信を行う ・タイマ4 (20ms周期でリセットパルスを生成) メイン関数は ・CCP1で立下りエッジ検出 ・CCP4で立上がりエッジ検出 ****** タイマ0の割込みは約13msです。 タイマ4は20msです。 時系列で言うと (1)プログラムスタート~タイマ0割込みまで(0~13ms) main関数が走り、パルスのエッジをキャプチャする (はずですが、現状CCP1IFを検知できません) (2)タイマ0割込み中(13~19.9ms) キャプチャの値の計算とシリアル送信 (3)タイマ4割込み発生(20ms) リセット信号と全ての値のクリア

  • H8/3048F インプットキャプチャについて

    CPU:H8/3048F 開発環境:GCC Developer 以上の環境で制御プログラムを作成しています. タイマ1のインプットキャプチャを用いて 入力パルス数を計測するプログラムを作成しました. 割り込み要因はパルスの立ち上がり/立下りの両方です. デバッグ方法として 1.パルスを入力するポートにボタンを接続し, ON:5V OFF:GND となるようにした. 2.7セグメントLEDに割り込み毎にインクリメントしていくように 表示させる(1から9までカウントする). 以上の方法で,ボタンをON OFF する度にカウントがインクリメントされるのを確認しました. 次にボタンを取り外し,入力ポートに何も接続されていない状態で, 電源を入れると,カウンタが凄い勢いでインクリメントを繰り返す現象が発生します. デバッグでは意図どおりに動作していたのでプログラムは問題ないと 思うのですが,ハードに問題があるのでしょうか? ハードの知識はあまりないので全くわからない状況です.

  • 立上がりと立下がり、両方のエッジでパルスを出したい

    デジタル回路についての質問です。 今、デジタルオーディオのDAI-DACを自作しようとしていて、DAIを切り替える回路を考えているところです。 DAI-DAC間の信号線を切り替えるのは、マルチプレクサなどを使用すればできる作例を見つけましたが、DACにもリセット信号が必要なことに気づきました。 リセット信号を入れるために、単安定マルチバイブレータを入れればよいと思うのですが、 私の理解の範囲では、結局のところ、立上がりエッジか立下がりエッジかどちらかの入力でしかパルスが出ないらしいので、マルチプレクサの選択端子と同じ電圧を入れるだけでは、片方の向き(A→Bなど)だけしかリセット信号が取り出せないことになってしまいます。 両方のエッジで単安定なパルスを出力できる簡単な回路がありましたら教えてください。

  • H8/2052Fインプットキャプチャ機能実装について

    現在、上記のマイコンを使い0.5ms程度のパルス波の入力と波長判断を行いたいと考えています。 そこで、インプットキャプチャ機能を使用したいと考えているのですが、うまくいきません。 外部入力を得て割り込み関数を呼び出すことすらできない段階です。 何かアドバイスをいただけないでしょうか? よろしくお願いいたします。 タイマ関数初期化の手順としては、 1.TCRレジスタの設定(TIU0.TCR.BYTE = 0x03;//φ/8分周) 2.TIORレジスタの設定(TIU0.TIOR.BYTE = 0xDC;//GRB立下り、GRA立ち上がり) 3.TIERレジスタの設定(TIU0.TIER.BYTE = 0xFB;//IMFB、IMFA割り込み許可 ) 4.TNCT、GRA、GRBレジスタの初期化 5.タイマスタート となっております。よろしくお願いいたします。

  • 16ビットPICのインプットキャプチャについて(2

    以前に http://oshiete1.watch.impress.co.jp/qa9005302.html で質問をさせて頂いた者です。 質問していました問題は、解決いたしました。 koujikuu 様から頂いたアドバイスの 「ICxCON2 / ICTRIG=0 同期モード キャプチャの度にタイマがクリアされる」 という言葉で、もう一度マニュアルを読んでみたところ。ここが問題でした。 トリガモードにして(ICTRIG=1) トリガ源も、ICクロック源と同じTimer1に変更しました。 (FIFO機能は用いずに、一回のエッジ検出毎にカウンタを++しました) 今回の問題は ICTRIG=0; だと、キャプチャごとにタイマ値がリセットされるので 同じタイミング→    例) Rise[0]-Down[0]  →  だと値が正常で タイミングがずれると 例) Rise[1]-Down[0]  →  だと値が異常でした。 前置きが長くなりましたが、質問をさせて頂きます。 「組込システム」のセンスを磨くにはどうすればいいでしょうか。 周りに質問できる人がいない状態です。 父と二人で計測器を作っていますが、父はアナログ屋で、昔にZ80を少し触った程度。 下名は4年目で、以前は3年間工作機械メーカー勤務(学生時代にロボットアームの制御でC言語は触っていました) 翔泳社のCodezinというサイトにも無料登録しましたが、マイコンや組込系とは少し違う気がします。 具体的な質問として 1.(関西の)サークルや勉強会の情報を持っているかたはおられませんか?   情報の「クレクレ」では無く、上記の通りアナログの知識は(主に父経由ですが)   40年の蓄積があるので、情報の取引的なことができるかとは思います。   (情報を共有できる方と知り合える場、もちろん関西以外でも結構です。)    2.皆様は何で勉強されましたか?   「これだけは読め!」等の書籍等を教えて頂けると幸いです。

  • C言語でのif文分岐について(PICで使用)

    お世話になります。 現在PICマイコンでC言語を用いて、プログラムを組んでいますが、煮詰まったので皆様のアドバイスを頂戴したく、質問させて頂きます。 問題点概要: if文の分岐がうまく行かない。 パルス幅を計測し、その幅に応じて個数を判別し、累積カウントをするプログラムです。 しかし、パルス幅での個数の判別がうまく行きません。 例)パルス幅100以上で「2つ」とカウントしたいところが、「1つ」とカウントする。 プログラム仕様: 1.パルスの幅を計測するプログラム 2.計測したパルス幅に応じて、個数を判別する。 3.個数を累積する。 4.表示する 1から3を2[ms]周期で実行しています。 ※カメラの前を物体が横切ると、カメラ出力がLになるので、そのエッジを見ています。 したがって、 カメラの前にずっと物体があると、出力がLのままなので、累積カウントがアップし続けます。 その時は、累積カウントをしないプログラムにしています。  → 一回目の検知時のみ累積カウントをアップさせる。 そのために、「PP」という変数を定義しています。 添付資料に、詳しく書いています。 見て頂けると幸いです。 カメラ出力の取り込みについて: 立ち上りエッジをCaptime_rise[Rise]; Riseは検知するたびに、インクリメントされます。(1から++) Downも同様です。 カメラは、物体を検知しないときは ______|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|________________ なので、Rise==Down==1です。 物体を検知すると ______|‾‾‾‾‾‾|_____|‾‾‾‾‾‾|______________ となります。 上述の通り、「カメラの前に物体がずっとある場合の、累積カウントアップ防止」の為に PP==1  // PPは前のRiseの値 の時のみ、累積を加算するようにしています。 PP==1の状態とは、物体を検知していない場合なので、この考えで大丈夫ではないかと思っています。 //プログラム抜粋 // 個数の計算 /* Captime[i] → 計測パルス Captime_rise[i] → 立上パルス Captime_down[i] → 立下パルス KOSU → 個数 KOSU_SUM → 累積個数 PP → 1つ前のサイクルのRiseの値 STD_width → 個数判別の基準値 */ if(Rise==1){ KOSU=0; Captime[1]=0; } else if(Rise==2){ // パルス幅の計算 Captime[0]=Captime_down[1]-Captime_rise[1]; // Captime[1]=Captime_rise[2]-Captime_down[1]; // 1つ目の検知 if(PP==1){ if(Captime[1]>STD_width) { KOSU=2; KOSU_SUM=KOSU_SUM+2; } else { KOSU=1; KOSU_SUM++; } } } else{ KOSU=9; } PP=Rise; アルゴリズムの考え方等が我流なので、皆様のアドバイスを頂けると幸いです。

  • フリップフロップ(D-FF)回路について

    D-FF回路でT-FF回路を作成した場合、Qバーの出力をDに入力させます。 このとき、Qバーの出力ピンに丸印(小さい○)をつけると、クロック(CLOCK)の立ち上がりエッジから遅延して、Qバーからの出力が反転されます。 ここで、なぜ、Qバーの出力ピンに丸印(小さい○)をつけると、クロック(CLOCK)の立ち上がりエッジから遅延して、Qバーからの出力が反転されるのかが、分かりません。 ご教授をよろしくお願いします。

  • RSフリップフロップ(?)

    下図のように、信号Aの立ち上がりエッジより 信号Bの立下りエッジまでのパルスを作れる回 路を教えてください。もちろん信号AおよびB のチャタリングは無視できるようにします。 RSフリップフロップに近い動作なのですが… よろしくお願いします。 信号A_| ̄|__| ̄|__ 信号B__| ̄|__| ̄|_ 出力 _| ̄ ̄|_| ̄ ̄|_

専門家に質問してみよう