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

このQ&Aのポイント
  • C言語でのif文分岐についての質問記事です。アルゴリズムの改善に関するアドバイスをもとに、パルス幅の最大値の保持に関するプログラムを追加しました。しかし、意図した通りに動作しないため、困っています。
  • 現在のパルス幅と最大値をLCDに表示するため、1ループ目では現在のパルス幅と最大値が同じになり、2ループ目以降も最大値が前回の値のままになってしまう現象が発生しています。
  • アルゴリズムの動作を確認するために、アルゴリズム図を参考にしてソースコードを見直しても上手くいかず、困っています。パルス幅の最大値の保持がうまく行われず、次の処理に進めない状況です。
回答を見る
  • ベストアンサー

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

http://oshiete1.watch.impress.co.jp/qa9017378.html で質問をさせて頂き、アドバイスを基に以下のアルゴリズムを追加しました。 (以前の質問では、間違って質問を締め切ってしまいました。 アドバイスを頂いた方に大変失礼なことをしてしまいました。申し訳ございません。) 1.パルス幅の最大値を保持する。 2.物体の通過後に累積個数を加算する。この時に、保持した最大値を用いる 従来はRise==2,PP==1の時に、累積加算+パルス幅の判別を行っていました。 このタイミングは、「物体の先端を検知した時」になります。 それを変更し、Rise==1,PP==2の時に、判別するようにしました。 このタイミングは「物体の通過後」になります。 質問: 「1」の「最大値の保持」のプログラムが意図した通りに動きません。 1ループ前のパルス幅を P_Captime[1]=Captime[1]; として保持し、 現在のループの計測値を比較を行い、現在の値の方が大きければ Max_Captime[1]=Captime[1]; とし、最大値を保持しています。 私の意図している動き: LCDに ・現在のパルス幅(Captime[1]) ・最大値 (Max_Captime[1]) を表示しています。 この時、LCDの表示が ・1ループ目 現在のパルス幅が50 →最大値も50 ・2ループ目 現在のパルス幅が20 →最大値は50のまま としたいのですが、 ずっと現在のパルス幅=最大値となり、 最後のパルス幅(物体が通過した最後のループ)がLCDに保持されたままになります。 例)上記の後、最後のループのパルス幅が30の場合、最大値は50でなく、30と表示される。 以下ソース抜粋 /* パルス有無の検知 Rise による識別*/ if(Rise==1){ KOSU=0; Captime[1]=0; } else if(Rise==2){ // パルス幅の計算 Captime[1]=Captime_rise[2]-Captime_down[1]; if(Captime[1]>P_Captime[1]){ // 最大パルスの取得・保持 Max_Captime[1]=Captime[1]; } } P_Captime[1]=Captime[1]; PP=Rise; /*抜粋終わり*/ ドツボに嵌っています。 あえて昨日は何も考えずに、もう一度ソースコードでなく、アルゴリズム図から見直してみましたが、うまくいきません。 /*****************************/ 冗長な文章でしたので、要約すると 1.パルス幅の最大値を保持する。 2.物体の通過後に累積個数を加算する。この時に、保持した最大値を用いる の「1.パルス幅の最大値を保持する」がうまくいかないので、「2」に進めずに 困っています。 となります。 アドバイスを頂けたら幸いです。 (もちろん自分自身でも、並行して考え直しています)

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

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

実際に確認したわけでは無いので参考程度に、 Sel初期値0:現在の処理モード if (Rise==1 && Sel==0){ KOSU=0;Captime[1]=0;Sel=1; } if (Rise==2 && Sel==1){ Max_Captime[1]=0;Sel=2; } if (Rise==2 && Sel==2){ Captime[1]=Captime_rise[2]-Captime_down[1]; if (Captime[1]>Max_Captime[1}){ Max_Captime[1]=Captime[1]; } } // Max_Captime[1] 最大値計測中 if (Rise==1 && Sel==2){ Sel=0; // Max_Captime[1]によるKOSU加算処理 } if (Rise>2){ KOSU=9;Sel=0; } // Error

Snoodam
質問者

お礼

koujikuu様: 私の低レベルの質問にいつも付き合って頂き、本当にありがとうございます。 本当に失礼なのですが、質問しておきながら、本日はPICを触れる状態にありません。 明日試します。 /****/ if (Captime[1]>Max_Captime[1}){ Max_Captime[1]=Captime[1]; } の部分でハッとしました。 今までのif分岐だと、値がうま行かない理由を、サイクルタイム毎に表に値を書いて みました。10-40-20-30と値が変化すると、MAX値が最終的に40でなく30になりますね。 思い込みで、一応添付画像の通り、サイクルタイム毎の値を書いたつもりでしたが、走り書き でなく、しっかりと表に書くべきでした。 /****/ Sel初期値0:現在の処理モード の使い方も教示して頂きありがとうございます。 switch文のcaseの様な使い方をその様にしたらできるのですね。 目からうろこでした。 /*****/ 本当にありがとうございます。

Snoodam
質問者

補足

koujikuu様: 解決いたしました。 本当にありがとうございます。 今後は同じ様な質問をしない為にも、アルゴリズムからコーディングする際には サイクル毎の値の変遷も「頭の中」だけでなく、表をこさえて確認します。 ありがとうございます。

関連するQ&A

  • 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; アルゴリズムの考え方等が我流なので、皆様のアドバイスを頂けると幸いです。

  • C言語 値の合計について(PICマイコン上)

    C言語、値の合計について(PICマイコンを使用) C言語のアルゴリズムについての質問です。 申し訳ございませんが、前提が長く、質問が後半にあります。 1.行いたいこと パルス幅を取り込んで、パルス幅を足しこんでいく。この値を面積とする。 2.仕様 ・500usでループを回しており、その都度、パルス幅を取得しています。 (パルス幅は1つであったり、複数であったりします。パルスの数を「Rise」という 変数で記憶しています。) ・そのパルス幅を取得し、一定ループ後に合計値を計算したい。 例) ___|¯¯|___|¯¯¯|___ Rise=1。中央のくぼみの幅を計算 ↓ ___|¯¯|_|¯¯|_|¯|____ Rise=2。中央2つのくぼみを計算 3.問題点 Riseの値でif分岐をした、べた書きしたプログラムと、より一般化したプログラムの 面積の値(SUM_Areaの値)が異なる。 一般化したものの方が値が大きくなる。 /*以下プログラム*/ // べた書き if(Rise==2){ Captime[1]=Captime_rise[2]-Captime_down[1]; //パルス幅の計算 Area[1] += Captime[1]; //面積計算 SUM_Area=Area[1]; //合計の面積 } // Rise==2 LOOP END else if(Rise==3){ Captime[1]=Captime_rise[2]-Captime_down[1]; Captime[2]=Captime_rise[3]-Captime_down[2]; Area[1] += Captime[1]; Area[2] += Captime[2]; SUM_Area=Area[1]+Area[2]; } // Rise==3 LOOP END else if(Rise==4){ Captime[1]=Captime_rise[2]-Captime_down[1]; Captime[2]=Captime_rise[3]-Captime_down[2]; Captime[3]=Captime_rise[4]-Captime_down[3]; Area[1] += Captime[1]; Area[2] += Captime[2]; Area[3] += Captime[3]; SUM_Area=Area[1]+Area[2]+Area[3]; } // 一般化したもの for(i=1;i<Rise;i++){ Captime[i]=Captime_rise[i+1]-Captime_down[i]; Area[i]+=Captime[i]; SUM_Area+=Area[i]; } 4.考察 一般化したプログラムの SUM_Area+=・・・・ の部分のみをifで場合分けすると、 (SUM_Area=Area[1]+Area[2]+Area[3]; の様にRiseの値で分岐) 値が一致したので この部分が悪さをしていると考えています。 5.質問 今回の場合はSUM_Areaの部分は、べた書き(Riseでの分岐)しか方法がないのでしょうか。 Riseが64個まであるので、プログラムが冗長になってしまいます。 宜しくお願いします

  • 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) リセット信号と全ての値のクリア

  • 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の値が変わる?) リファレンスマニュアルや書籍も読んだのですがわかりません。 アドバイスを頂けると幸いです。

  • カットオフ周波数について

    カットオフ周波数について質問があります。 例えば、カットオフ周波数が1MHzの1次のLPFがあったとき、もし1MHzの信号を送信したとき信号は1/√2に減衰すると思います。 しかし、この信号がパルス信号だとしたらどうなるのでしょうか? もし、周波数1MHzのパルス信号のデューティ比が50%だとした場合、パルス幅は500nsとなります。 以下のURLを参考にして500nsのパルスが通過できるカットオフ周波数を計算したところ約700kHzとなりました。 http://www.analib.com/blog/calculator/rise-time/ つまり、カットオフ周波数1MHzのLPFならば周波数1MHzのパルス信号は減衰はほとんどなく通過できるということになります。 おそらく私が何か変な勘違いをしていると思うのですが、どなたかこの質問に回答できる方いらっしゃいましたら教えていただけると幸いです。

  • C言語 この記述のどこが間違っているのでしょうか?

    最大10文字の文字列入力を受け付け、 10回入力するか、「OK」が入力された時に 文字列を出力するプログラムを作ろうと思い、 その中で、1回目に『OK』が入力された時には、エラーメッセージを表示して終了するようにしたいのですが、 以下を入力したところ、うまく動作しませんでした。(見づらいのはご容赦ください) 制御文と配列を使って動作させるには、どう修正するべきでしょうか。 初心者ですが、ご教授お願い致します。 #include <stdio.h> #define MAX_INP 10 /* 入力最大回数 */ #define MAX_LGTH 5 /* 入力可能最大文字数 */ int main(void) { char str[MAX_INP][MAX_LGTH]; int cnt; /* 入力用カウンタ */ printf("\n"); for(cnt = 0 ; cnt < MAX_INP ; cnt++) /* 入力ループ */ { printf("Input String. -> "); /* 文字列入力メッセージ */ scanf("%s",&str[cnt][0]); /* 文字列入力 */ if(str[cnt][0]=='O' && str[cnt][1]=='K' && str[cnt][2]=='\0') { /* OKと入力された場合 */ break; /* ループから抜ける */ } if(cnt == 0) /*「OK」入力が1回目の場合 */ { printf("Error."); /* エラーメッセージ */ return 0; } } printf("\n"); for(cnt = 0 ; cnt < MAX_INPUT ; cnt++) /* 出力ループ */ { printf("%s\n",&str[cnt][0]); /* 文字列出力 */ } printf("\n"); return 0; } 【動作結果1】 Input string. -> abc Error. > 【動作結果2】 Input string. -> OK OK Uウ@ @ ■p 『 『 >

  • 図に示すような加速管の中で高速で移動している物体を、測定地点を3点設け

    図に示すような加速管の中で高速で移動している物体を、測定地点を3点設けて、その3点を通過する時間を計りたいと思っています。 考えているものとして、2つのレーザーと1つのパルスレーザーを設置し、2つのレーザーを照射していて、物体が横切ればレーザーを横断するわけになり、そこからパルスレーザーまでの到達位置・時刻aを出します。 a点に到達する時にパルスレーザーによるパルスに信号を送り最初のパルスからのパルス数により時間を算出しようと思っています。 これと同じものをb、c2点設置し最終的に何秒でどこに行き着くかを見たいというものです。 はっきりしない上に、わかりにくい説明だとは思うのですが解説・指摘お願いします

  • C言語 if文について

    #include <stdio.h> int main(void) { int a; printf("整数を入力してください:"); scanf("%d",&a); if(a % 10 == 5) puts("最下位の桁は5です。"); else puts("最下位の桁は5でありません。"); return 0; これでどうして読み込んだ整数値の最も下の桁が5であるかどうかを判断しているのでしょう? ifの式がいまいち理解できません。 解説できる方いませんか?

  • C言語 if文

    C言語のif文についての質問なのですが、ifを使い、条件Aの時は1のプログラムを実行、条件Bの時は2のプログラムを実行するようにしたとき、1と2のプログラム自体にもif文が使われています。その場合は、AとBの時のifと1と2に使われているifをどのように区別するのですか?(ちなみに1と2のif文については、それぞれ実行してみたところ動作可能でした。)説明が下手ですいません。初心者ですので、分かりやすく教えていただけると有難いです。

  • C言語 if分岐 strcmp

    失礼します。現在test_wordに格納されている文字列を数字の0又は空白だった場合の条件を記述していきたいのですが、うまくいきません。 最初の条件で0又は空白ではない場合を記述し else ifで0又は空白の場合を記述しています。 ステップ実行して確認しているのですが、 test_wordに0又は空白が入っているのに一番最初の処理をしてしまいます。 ご教授頂きたいです。よろしくお願いします。 char blank_word[10]; char miss_word[10]; strcpy(blank_word, ""); strcpy(miss_word,"0"); if ((strcmp(test_word, blank_word) != 0) || (strcmp(test_word,miss_word) != 0)) { 0又は空白ではないの処理; } else if (strcmp(test_word, blank_word) == 0 || strcmp(test_word, miss_word) == 0 && flag == 1) { 0又は空白である場合の処理; }

専門家に質問してみよう