PWM制御のデューティ変更時におけるトラブル

このQ&Aのポイント
  • PWM制御において、デューティ変更時に予期せぬ現象が発生しています。
  • デューティを急激に変化させた場合に、デューティが100%以上になる現象が起きます。
  • デューティを変更するタイミングやデューティの値が問題の可能性があります。
回答を見る
  • ベストアンサー

PWM制御のデューティ変更時におけるトラブル

SH7211マイコンのPWM(モード1)を使用して、定電流制御をしています。 PWMの周期を10KHzとし、その割り込みの周期で電流値を増設のADコンバータで取得、PID演算の後にPWMのデューティを変更して電流を制御するフィードバック機構です。 この時、10KHzで割り込みをして電流を一定に保つようデューティを常に変更しているのですが、過度に電流を流さないようデューティの値を変更する時はデューティが50%以上にならないようにしています。 ですが、PWM出力をオシロで見ていると、例えば電流値を5Aから1Aへ変更しようとした時、変更するタイミングで何故かデューティが100%以上になってしまい、本来電流値が下がるべき所で一瞬だけ5A以上となる現象に悩まされています。 CPUのマニュアルに、「周期レジスタとデューティレジスタのコンペアマッチが同時に発生すると出力は変化しない」とあり、その時デューティが100%以上になってしまう動作例が載っているのですが、プログラム上でデューティは50%以上にならないようにしていますので、この箇所は問題ないかと思います。 今現在わかっている事ですが 1) 割り込みで常にデューティは書き換えているのですが、電流値を変化させた時、つまりデューティレジスタの値を急激に変化させた時に発生しているように見えます。2A→1A程度の変化では発生しません。 2) 5A→1Aと減らした時と、1A→5Aと増やした時両方で発生します。 3) デューティを変更する直前でブレークをかけて、適当なタイミングでブレーク解除した時、この現象が発生する時と発生しない時があります(デューティを変更するタイミングが問題?)。 4) デューティレジスタの値を0とした場合、上記に書きました「周期レジスタとデューティレジスタのコンペアマッチが同時に発生すると出力は変化しない」事に該当するかもしれないと考え、デューティレジスタの値が0の時は強制的に値を10としましたが、この現象が発生しました。 また、プログラムの中身ですが 1) 周期レジスタの値は3999、デューティレジスタの値は0~1999の値で変化。 2) 出力は初期出力がHi、コンペアマッチでLowというHi→Low出力。 3) 割り込み関数の中でADコンバータから値を取得→PID演算→デューティレジスタの値を変更という処理をしています。 4) 割り込みレベルを他の割り込みと比べて一番高くしているため、割り込み関数処理中に他の割り込みは発生しません。 長文申し訳ございませんが、何か同じような現象が起きた方、または何かしらの解決策をご存知の方、アドバイスを宜しくお願いします。

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

  • ベストアンサー
  • bug_bug
  • ベストアンサー率78% (36/46)
回答No.1

とりあえず、ざっくり簡単なとこだけ。 TCNTがフリーランカウンタになっているならば、デューティー変更の際気をつけないとコンペアマッチが発生せず、1パルス分おかしな波形になったり、使い方によってはデューティーが逆転する可能性さえもありますね。 この場合、デューティーの変化量が大きいほど事象が発生しやすくなります。 サンプルの例で例えるならばデューティーレジスタを1999から399に変更した場合に、TCNTが400-1998の間にあると、1999で発生すべきコンペアマッチが発生せず、TCNTが次周期の399に達するまでHiを保持するでしょう。 TCNTも割り込みの度に初期化してあげることでとりあえず現象が収まるならばここが問題じゃないでしょうか? TCNTをフリーランカウンタとして使うためにはファーム側できちんと出力波形について条件分岐する必要があります。 コンペアマッチでトグルする仕様だったりすると1A->5Aへの変更時も同一周期に2度コンペアマッチが発生してしまうなど 意図しない動作をする可能性がありますね。 質問内容にここらの考慮が記載されてませんでしたので念のため。

antenna103
質問者

お礼

bug_bug様、ご回答有難うございます。 bug_bug様が仰るとおり、TCNTについては何も考えておらず、フリーランカウンタになっています。 動作検証ができるのは1月5日なのですが、その時に早速試してみます。 大変貴重なご意見、有難うございました。

antenna103
質問者

補足

回答への補足にて失礼します。 本日、実機にて動作確認をしてみた所、bug_bug様が仰ったとおり、TCNTとデューティレジスタの関係で、コンペアマッチせずに次の周期まで出力が維持されたため、このような現象が起きた事を確認できました。 プログラムに更なるコーティングを施し、今では問題なく動作しております。 これで、本制御のメインであるPID部分に専念できます。 これもbug_bug様のおかげです。 真に有難うございました。

関連するQ&A

  • PICのPWMの正しい使い方について教えてください

    PIC12F1822用のPWMの基本動作テストプログラムを作りましたが、PWM出力が意図どおりに得られません。 (XC8のテストプログラムを下に添付。テストパターン1/2の切り替えはコメントアウトをお願いします。  アナライザの出力を画像で添付しました。) テスト目的: タイマー0の周期割り込みに合わせて、PWMのデューティー比(または周期)を変更するプログラム   テストパターン 1 : パルスのデューティー比を変えるテスト 質問1: パルスのデューティー比を変えるテストは、PWM設定の一回おきにCCPからのPWMの出力が出ません テストパターン 2 : パルスの周波数を変えるテスト 質問2: 周波数を変えるテストはOKに見えるものの、1回目のPWMがHighとなるのと、割り込みの11回目、13回目あたりでPWM出力が欠落する 【回答のお願い】 どうも、PWMのレジスタ設定に手順、またはタイミングがあるのではないかと思いますが、原因がわからず困っております。 PICに詳しい方からのご指導をよろしくお願いいたします。                                    K.A. ------------------------------------------------------ /* * File: PIC12F1822 PWC * Author: K.A. * * Created on 2014/07/20 * * タイマー0の周期割り込みに合わせて、PWMのデューティー比(または周期)を変更するプログラム * */ #include <stdio.h> #include <stdlib.h> #include <xc.h> #pragma config FOSC=INTOSC, WDTE=OFF, PWRTE=ON, BOREN=ON, MCLRE=OFF #define _XTAL_FREQ 8000000 // クロック8MHz /* * */ // タイマー割込みの処理 int TMR0_Count = 0; // タイマーの割込み発生回数をカウントする変数 void interrupt Timer0(void) { // タイマー0の割込み発生か? Timer0 は 8bitの オーバーフロー・カウンタ if (TMR0IF == 1) { TMR0_Count++; if (TMR0_Count > 5) { TMR0_Count = 0; if (RA5 == 0) RA5 = 1; else RA5 = 0; // RA5は、動作表示用LED } TMR0IF = 0; // タイマー0割込フラグをリセット } } int main(int argc, char** argv) { unsigned int pulse_width = 5; OSCCON = 0b01110010; // 内部クロックは8MHz ANSELA = 0b00000000; // すべてをデジタルI/Oに割当 TRISA = 0b00001000; // すべてのピンは出力に割当てる(RA3は入力専用) PORTA = 0b00000000; // 出力ピンの初期化(全て'0'にする) RA5 = 0; // 動作確認用LED // Timer0  Timer0 は 8bitの オーバーフロー・カウンタ OPTION_REG = 0b00000001; // 内部クロックでTIMER0を使用、プリスケーラカウント値 1:2 // bit5:0=Fosc/4, bit3:0=PreScaler_ON, bit2-0:PreScaler TMR0 = 0; // タイマー0の初期化 (+2cycle) TMR0IF = 0; // タイマー0割込フラグを0にする TMR0_Count = 0; // 割込み発生の回数カウンターを0にする TMR0IE = 1; // タイマー0割込みを許可する GIE = 1; // 1: 全割込み処理を許可する /* PWM */ TRISA2 = 1; // RA2 出力をサスペンド TMR2IF = 0; // TMR2 フラグをクリア CCP1SEL = 0b0; // CCP1/P1Aの機能をRA2に割り当てる CCP1CON = 0x0C; // PWM モード // Period を 設定する xx ms=((PR2)+1)*4*125ns(8MHz)* PreScaler(x1-x64) PR2 = 127; // 4.096ms (プリスケーラが x64 の場合) T2CKPS0 = 0b1; // プリスケーラ 00:x1, 01:x4, 10:x16, 11:x64 T2CKPS1 = 0b1; // CCPR1L = pulse_width >> 2; // パルス幅上位8bit CCP1CON = ((pulse_width & 0x0003) << 4) | 0x0C; // パルは幅下位2bit TMR2ON = 1; // TMR2 カウント開始 while (TMR2IF == 0) { /** / do nothing /**/ } TRISA2 = 0; // RA2に出力を接続 while (1) { if (TMR0_Count == 0) { /**** テストパターン 1 : パルスのデューティー比を変えるテスト ****/ // パルスのデューティー比を変えるテストは、PWM設定の一回おきにCCPがPWMの出力が出ません。 なぜ? pulse_width = pulse_width + 10; if (pulse_width > 500) pulse_width = 5; /**/ /**** テストパターン 2 : パルスの周波数を変えるテスト **** / // 周波数を変えるテストはOKに見えるが、 // 1回目のPWMがHighとなるのと、割り込みの11回目、13回目あたりでPWM出力が欠落する PR2 = PR2 - 8 ; if (PR2 < 8) PR2 = 127; pulse_width = PR2 ; // Duty 25% に相当 /**/ CCPR1L = pulse_width >> 2; CCP1CON = ((pulse_width & 0x0003) << 4) | 0x0C; TMR0_Count++; // 続けて PWMの設定変更をしないためのフラグ代わり } } return (EXIT_SUCCESS); }

  • マイコンによるPWM制御

    7個のサーボをマイコンによって独立に駆動しようと試みています。 つまり、別の周期、DUTY比のPWM信号を7つ同時に出力できるマイコンが要求されます。 どのようなマイコンが最適でしょうか。 ほかの条件としては、 1.開発環境が整っている。 2.入手性がよい 3.ローコスト 4.20MIPS以上の処理性能 でしょうか。どなたかお願いします。

  • dsPICを用いたPWM出力

    dsPIC(30F4012)でPWMの出力をしてやりたいのですがソフトの知識があまりなく困っています。外部の可変抵抗の値をAD変換した後にそのAD変換した値をデューティ比と比例させてPWM波形を出力してやりたいのです(リアルタイムで変化)。開発環境はMPLAB(C30)です。ご指導お願いいたします。

  • PWM制御のヒーター回路

    PWM制御によるヒーター回路を探しています。 CPU側からデューティーを変化して出力電圧を制御して ヒーターの温度を制御するものです。 温度センサーで低温時での液晶の動作を良くするのが目的です。 良い回路がありましたら、教えて下さい。

  • PICによるPWM出力の周期について

    PIC(16f873)を用いて、モータをPWM制御しようと思っています。 そこでいくつか質問なんですが、PWMの周期は下記の式で与えられるとありますが、 PWM周期 = (PR2の値+1)x4x発振器周期xタイマー2のプリスケーラ値 この周期は、自分で適当に決めていいのでしょうか?それともモータによって決まっているんでしょうか?  そもそもPWMは、デューティ比で出力が変わると思うんですが、周期が違うとどのような違いが出るのでしょうか?周波数が高くなると細かい制御が出来るって感じでしょうか? 初歩的な質問ですが、よろしくお願いします。m(_ _)m

  • モータをPWM駆動した際の電流について

    ┌── 電池 ── 電流計1 ── モータ ─ 電流計2 ────── FET ─┐ │ └ 電圧計 ┘        └←← ダイオード ←←┘           │ │                                            │ └──────────────────────────────┘ となるシンプルな回路でPWM制御によるモータ駆動のテストしています。 周期は24kHzで、モータは安いDCモータです。 ※実際にはHブリッジでかつゲートドライバが入っていますが省略しています。   また、Hブリッジの駆動にはデッドタイムを500nsほど入れています。 この回路における電流計1と電流計2で計測される値の意味が、分からなくて困っています。 任意のPWM比でFETをドライブした際に、電流計1 & モータ & 電流計2には、 ほぼ電圧計*PWM比の平均電圧が加わる考えており、 電流計1と電流計2の抵抗値と、FETによる抵抗値が十分小さければ 平均電圧のほとんどはモータに加わる。 電流計1ではPWMのON期間の電流のみが計測され、 電流計2ではダイオードで帰還する分も併せて計測している。 このため概ねでは、電流計2 = 電流計1/PWM比 の値となると考えています。 電圧計*電流計1が電池の消費電力(入力電力)であり、 少なくともモータをロックしておけば、モータに加わる出力電力は(電圧計*PWM比)*電流計2となり、 電圧計*電流計1 = (電圧計*PWM比)*(電流計1/PWM比)が成り立つと考えてよいでしょうか? モータが熱として捨てる以外の損失が無ければという前提ですが。 実際に計測してみた値は、電圧計=11.6V、PWM比=10%、モータはロックにおいて 電流計1=0.26A、電流計2=0.48Aでした。 これに対し、直流安定な電源として、充電乾電池1本を繋いでモータをロックして計測した際に、 電圧=0.85V、電流=0.394Aより、巻線抵抗=2.16Ωでした。 PWMで計測した際の値で、平均電圧=1.16V、電流=0.48Aがモータに加わっていれば 巻線抵抗=2.42Ωのため充電乾電池による結果と概ね一致します。 しかし、電流計1の値をどのように読み取れば良いのかが分かりません。 私の考え方では、電流計1=0.048Aでなければ入力電力=出力電力が成り立ちません。 お手数ですが、どこに間違えがあるのか御教授いただきたいです。

  • インバータとPWM制御

    電気電子はまったくの素人なのですが、ワケあって勉強中です。 しかも、突然インバータだの、スイッチング電源だの・・・困りました。 インバータに関して現在理解できていること 「スイッチング素子を用いて、直流を交流にする」ということです。 このスイッチのタイミングをPWMによって変化させる場合、しかも、2つのスイッチを相補PWMを用いて(S1のデューティを変えて交流に変換する。スイッチS1がONのときスイッチS2がOFF。)直流から(単相)交流に変換するインバータの仕組みが良く分かりません。 私のイメージ・・・・ デューティ50%の時、 S1とS2がONの時間は互いに等しく、OFFの時間も互いに等しい。 ⇒正負が交互に・・・これで交流完成!? 2つのスイッチのデューティと交流の関係がイメージできません。 ご教授願います。

  • ソレノイドコイルのフィードバック制御の件

    お世話になります。 現在ソレノイドコイルの制御を考えております。 ソレノイドコイルは初めて使用致しますので、現在特性の調査中です。 使用方法はACソレノイドのPWMの出力で流して、電圧、電流とDUTYの依存性 を確認する所からはじめています。 しかし、PWMの出力DUTYと電圧はリニアの特性が出ていないようなので、 その理由は何か知りたいと思っています。出力DUTYと電流はリニアの 特性なのでなぜ電圧ではだめなのか理解できません。 また、ソレノイドコイルに電流を流すと鉄芯が発熱し、それによりL成分が 変化しているようにも思えますが、温度とL成分の関係を導けるような 良い文献、サイトはありませんでしょうか。 2点の質問となってしまいましたが、 ご回答、よろしくお願いいたします。

  • PWM信号をアナログ変換・・・

    発信器から発生させたPWM信号(周期5ms、5V出力、切り替わり時間3ns)をアナログ電圧へする回路を考えています。 おそらくアナログ電圧なので、直流の直線な信号を出力させると思うのですが、アナログ電圧へ変換する回路は、どのような回路があるのでしょうか? よろしくお願いします。 ちなみに・・・ 適正電圧7.2V、消費電流2.9Aのモータの制御を行えるものなので、PWM波形→7.2Vのアナログ電圧にしたいと思ってます。 よろしくお願いします

  • C言語についてです。(PWM)

    申し訳ありません。困っています。プログラムの勉強をしているのですが・・・ 三角波比較法により、ゲート信号を出力するプログラムです。 53: void pev_inverter_set_syncint(int bdn, float tpre); ・ ・ 55: pev_inverter_start_pwm( bdn, ch); プログラムではPWMのところにキャリア同期割り込み時間の設定関数を使っています。 53: void pev_inverter_set_syncint(int bdn, float tpre); キャリア同期割り込みをキャリアの山、または谷の前tpre[μs]時間前に発生するようにセットします。tpre:割り込みタイミングのオフセット[μs]、0~キャリア周期の半分」 55: pev_inverter_start_pwm( bdn, ch); キャリア同期割り込み信号出力の開始を行う関数。 キャリア同期割り込み信号の「山」の部分で割り込みが発生する。 質問です。 (1)キャリア同期割り込み信号とは、三角波のことなんでしょうか? (2)55行目で割り込みのタイミングを設定しているのに、53行目はなぜ必要なのですか? (3)tpre時間の意味がよく分かりません。PWMにどう関係していますか? 僕の浅はかな考えなんですが・・・簡単に言うと 53行目で、キャリア同期割り込み信号の準備をして 55行目で、実際にキャリア同期割り込み信号を出力する そして、u,v,w相の電圧の値と比較して、ゲート信号を作成する という考えであっているんでしょうか?すいません。誰か教えてくれませんか?

専門家に質問してみよう