RL78 F13/F14を使っています。初心者です。
パルス幅検出のところで質問がございます。
以下の仕様のセンサを使用して車輪の速度、回転方向を検出したいと考えております。
使用する汎用のマイコンで2入力のうち、1つはTAU0のパルス幅検出機能にも対応していたのですが、
もう一つの端子は入力のみの機能しかありませんでした。
ですので、コード生成機能を使って、パルス割り込みを入れることは出来たのですが、
この割り込みはエッジを検出したときに入るフローで間違いないでしょうか?
割り込みに入った時にポートのH/Lを検出して傾転方向のフラグを立てているのですが、
稀にフラグが反転してしまいます。プログラムがおかしいのか、マイコンの性能的なものなのか分かりません。
私の頭ではこのようなやり方しか思いつきませんが、
他に何か良い方法があれば、教えていただけると助かります。
以下、割り込み時の処理
◆やっていること
①車輪0km/h判定のタイマクリア(200msパルス割り込みに入らないと0km/hと判定)
②回転方向のフラグセットP1.5がOFF(1)を検出すれば、フラグセットする。(フラグがクリアされたときにはメイン関数で計算した車輪速に-1をかける)
=============================================
/************************************************************************************************************************ Function Name: r_tau0_channel2_interrupt* Description : This function is INTTM02 interrupt service routine.* Arguments : None* Return Value : None***********************************************************************************************************************/__interrupt static void r_tau0_channel2_interrupt(void){ if ((TSR02 & _0001_TAU_OVERFLOW_OCCURS) == 1U) /* overflow occurs */ { g_tau0_ch2_width = (uint32_t)(TDR02 + 1U) + 0x10000U; } else { g_tau0_ch2_width = (uint32_t)(TDR02 + 1U); }
/* Start user code. Do not edit comment generated here */ T1ms_AB = Speed_Sensor_Clear; //車輪0km/h判定タイマセット if(P1.5 == D_IN_OFF) { CW_FG = 1; } else CW_FG = 0; /* End user code. Do not edit comment generated here */}
=====================================
AB相インクリメントエンコーダですね。位相計数モードをサポートしたタイマ RGを積んだやつならもう少し楽ができたんじゃないかと思います。フラグと言っているのはポートの入力値が思っている値じゃないと言うことでしょうか?多重割り込みが有効化されずにタイマの割り込みハンドラの開始が遅れてしまっているのではないかと思います。
早速のご返答ありがとうございます。
便利な機能があるのですね。RL78しか使ったことが無かったので、知りませんでした。
仰っている通り、割り込みに入った時にポートの状態が思った通りになりません。
初心者過ぎて解決の仕方の検討がつかないのですが、割り込み処理のレベルを上げるのは効果がありますか?
RX231の位相計数タイマで行っていた処理を、RL78(タイマRGなし)に移植した際
端子A、端子B(両方端子割り込み(INTPxに割り当て)、端子割り込みは両エッジ設定)を使い
・端子Aの割り込み関数
if(端子A == 0)
{
//端子Aのfallエッジ(↓)
if (端子B == 0) g_counter--;
else g_counter++;
}
else
//端子Aのriseエッジ(↑)
if(端子B == 0) g_counter++;
else g_counter--;
(端子Bの割り込み関数も同様)
カウントアップの条件は
端子A=H 端子B=↑, 端子A=L 端子B=↓, 端子A=↑ 端子B=L, 端子A=↓ 端子B=H の4条件
カウントダウンの条件は
端子A=H 端子B=↓, 端子A=L 端子B=↑, 端子A=↑ 端子B=H, 端子A=↓, 端子B=L の4条件
上記の様な処理を行えば、簡易位相計数タイマが実現出来るのかと思います。回転方向(カウンタがインクリメントされるか、デクリメントされるか)、他のタイマを使い一定期間内に何カウント動くかで回転数の検出ができるかと思います。(DCモータの回転数検出に使いましたが、8個の穴の空いたエンコーダディスクとの組み合わせで、10,000rpm程度の速度であれば、ハードウェアの位相計数タイマと同じ様な値が取得できました。)
チョコです。
tfさんのコメントのように、他のプログラムや割り込み等の影響がなければ、ソフトでも十分できるはずです。(ただし、「パルス幅は最小200μsecぐらい」なので、5kHzだと考えると若干高速かも。)
KKさんのようにタイマでパルス間隔測定を使えば、速度情報も同時に得ることはできるはずです。
以上
>割り込み処理のレベルを上げるのは効果がありますか?シリアル通信など別の処理もある状態ですよね?フラグ処理している割り込みハンドラの先頭で使ってないポートを反転動作させて出力し、AB相信号と合わせてオシロスコープで観察することをお勧めします。そんなポート無い!って状態でもLED出力ピンとかを実験的にに利用するなど工夫しみてみてください。本来ならAとBの両エッジに対して少し遅れて追加した反転出力が出ますが、それが遅れてくることが観測できると思います。他にどんな処理をしているか?分かりませんが、他の割り込み処理時間がT秒なら最悪でT秒待たされるのでそれによってフラグ処理に入るまでに実信号はエッジ変化した時点からT秒すぎます。エンコーダの周波数が最大いくつか?が肝ですが、他の割り込み処理がこのタイマの割り込み優先度より低くても多重割り込みできる状態でない場合は他の割り込みの処理時間がそのまま割り込みハンドラ起動までの遅れになります。「割り込み処理レベルを上げる」と言うのは割り込み優先度を上げるという意味で使われていると思いますが、そもそも、現状で他の処理より高い状態ですよね?他にもっと優先する処理があってそれの処理時間が長い場合は原理上成り立たないです。割り込みハンドラ内の処理を最低限にして割り込みハンドラの時間を短くするとか書き方の工夫も必要になります。
皆様ご連絡ありがとうございます。
処理の仕方としては問題ないことが分かりました。
あとは、皆様が仰っているように他の割り込み処理の影響がありそうな気がしています。
CAN割り込みだったり、I2Cだったり他の割り込み処理も多くあり、現在はそれを全て割り込み優先度レベル2で統一していました。
Shoji様が仰っているようにポートを反転させて、どのぐらいの処理遅れがあるか確認したいと思います。
ありがとうございます!!
今から書くことは全体に対して大きな改善では無いですが、フラグ設定に使うポート状態の判定、後回しではなく先にすべきでしょうね。少なくともポート状態を読み込むタイミングはハンドラの先頭がいいと思います。パルス幅検出ってのは手段ですよね?AB相エンコーダを使っていることから、やりたいことはエンコーダが繋がる軸の速度測定でしょうか?だとするとAB相の両方に対して2つのタイマでインプットキャプチャしてカウンタクリアされない動作モードでやるのがいいように思います。もっと言えばタイマのインプットキャプチャじゃなくて単にAB相信号ピンの両エンジ割り込みで4逓倍の位置情報を取得して、1ms周期タイマなどを使って位置情報(元々エンコーダというのは位置管理のためですし)を時系列で保存して位置変差を時間で割って計算するのもありかなと思います。
>少なくともポート状態を読み込むタイミングはハンドラの先頭がいいと思います。
残念ながら、標準では、それはできません。この処理はコード生成されたもので、ユーザのコードは後ろにしか書けません。コード生成のこの問題については、以前から指摘しているのですが、なかなか対応してもらえません。SC(スマート・コンフィギュレータ)では可能になっているのですが、コード生成が対応したとの話は聞いていません。多重割り込みも同様だったと思います。
>だとするとAB相の両方に対して2つのタイマでインプットキャプチャしてカウンタクリアされない動作モードでやるのがいいように思います。
RL78のTAUでは、そのようなことはできません。有効エッジを検出すると、キャプチャしてカウントはクリアされます。
>もっと言えばタイマのインプットキャプチャじゃなくて・・・・・
その方法には、わたしも賛成です。
タイマアレイユニットじゃなくてタイマRDを使えば、インプットキャプチャできますよね。信号線がつながっているかは私には分かりませんが。TI02と書いてあるあるのでTRDIOC1で使えそうですけど。
>他の割り込み処理も多くあり、現在はそれを全て割り込み優先度レベル2で統一していました。
これは、大いに問題があります。せっかく4レベルの優先順位があるので、割り込みに優先順位をつけて、多重割り込みを利用すべきです。(コード生成ではサポートされていないので、多重割り込みを許可する場合には、割り込み処理の先頭に「EI();」を書いておく必要があります。ただし、これだけでは非効率的です。)
やはり、処理の効率を上げるにはCC-RLでレジスタ・バンクの使用や多重割り込み許可を指定する必要があります。具体的には、「CC-RL コンパイラ ユーザーズマニュアル」の
の部分に以下のような「#pragma interrupt指令」で割り込み仕様を指定することになります。
このうちの1番上は、通常の割り込みでも使用するのですが、下の2つが多重割り込みを効率的に実現するためのものです。
ここらを参考にして、チャレンジしてください。
アドバイスいただいたようにポート反転処理をキャプチャ完了の割り込みに入れてみたところ、
最大で400μsぐらいトリガが入ってから処理するまでに時間がありました。
皆さんの予想通り、ポートの状態を読むころには次のパルスの周期に入って、フラグセットがおかしくなっていたと予想されます。回転方向を読めなくなってくる車速のパルス幅が300μsぐらいだったので、間違いなさそうです。実機が分解中のため、すぐに確認は出来ませんが、アドバイスいただいたとおり、割り込みのレベルを上げて、多重割り込みを許可した状態だと40μsぐらいのずれまで納めることが出来ました。この状態でうまくいくか試したいと思います。
ありがとうございました。
実機をエミュレートする信号を出力するようなものを作るのもいいですよ。私はパルス関係の確認とかはArduino UNOでちょっと工作して使っています。そうすれば机で全て片付きますよ。今ならUNO R4になって性能も格段にアップしてるし、みんな大好き?ルネサスです!