ホーム フォーラム Texas Instruments マイコン C2000 IQ型のデジタル演算式について

このトピックには4件の返信が含まれ、2人の参加者がいます。5 年、 3 ヶ月前 amatsu1 さんが最後の更新を行いました。

6件の投稿を表示中 - 1 - 6件目 (全6件中)
  • 投稿者
    投稿
  • #7481 返信

    amatsu1
    参加者

    IQ型のデジタル演算式について

    デバイス型番:TMS320F28027

    いつも大変お世話になっております。

    早速ですが、現在、添付のような不具合が起こっております。
    なお、添付の通り、K0の値を大きくすると本不具合の程度が収まります。
    また、<< 14によりMSBが0になっているのではと考え、*16384に変えてみましたが、
    効果はございませんでした。

    ソースコード上でこのような不具合が起こりうりますでしょうか。

    _iq IoutCommand_Ch1; //grobal 宣言
    _iq IoutDetect_Ch1; //grobal 宣言
    _iq Ierror1_Ch1; //grobal 宣言
    _iq Ierror0_Ch1; //grobal 宣言
    iq K0; //grobal 宣言
    iq K2; //grobal 宣言

    IoutCommand_Ch1=3070;  //別関数で代入
    K0= _IQ(0.00002); //別関数で代入
    K2= _IQ(1); //別関数で代入

    interrupt void ADCINT1_ISR(void){
    _iq NxtCntVal_Ch1;

    IoutDetect_Ch1=AdcResult.ADCRESULT2;
    Ierror0_Ch1= (IoutCommand_Ch1 – IoutDetect_Ch1) << 14;
    NxtCntVal_Ch1 = __IQmpy(K0,Ierror0_Ch1,16)+__IQmpy(K2,CtrlVal1_Ch1,16);
    EPwm3Regs.CMPA.all=__IQsat(NxtCntVal_Ch1, MAX_CNTVAL, MIN_CNTVAL);
    CtrlVal1_Ch1=EPwm3Regs.CMPA.all;
    Ierror1_Ch1=Ierror0_Ch1;
    }

    以上、宜しくお願い致します。

    #7485 返信
    Yojiro
    Yojiro
    従業員

    amatsu1さん

    GLOBAL_Qは16でしょうか。

    小数部のビット数が16ビットの場合、小数部1ビットあたり 0.0000152587890625 となります。
    そのため、GLOBAL_Q = 16において、K0= _IQ(0.00002); とすると、K0は0x0000_0001(0.0000152…)となり、約23%の誤差が発生します。K0=_IQ(0.0005)では0x0000_0020(0.00048828125)になり、約2.3%の誤差になります。

    小数部のビット数に対し、設定されている係数が小さすぎるために不具合が発生しているものと考えます。

    つきましては、小数部ビット数に応じた有効桁数内での係数設定、あるいは小数部ビット数を大きくして計算してからCMPA設定時に16ビットに合わせていただく方法のどちらかをご検討頂く必要がございます。

    小数部のビット数を大きくすると、整数部の範囲が小さくなりますので、ご注意ください。

     

    ご確認のほど、よろしくお願いいたします。

    #7486 返信

    amatsu1
    参加者

    大変お世話になっております。
    ご教示いただき、誠にありがとうございます。

    誤差発生の原理については理解することができました。
    ありがとうございます。

    恐縮ですが、添付の通り、負荷を上げる時と下げる時で制御結果が変わる点についてもご見解をお願い致します。

    以上、宜しくお願い致します。

    #7488 返信

    amatsu1
    参加者

    大変お世話になっております。

    上記のご質問の件ですが、こちらでも原因解析しておりますが、
    (IoutCommand_Ch1 – IoutDetect_Ch1) < 0になった時に (IoutCommand_Ch1 – IoutDetect_Ch1)が
    マイナスになることを想定しているのですが、そうなっておらず、
    0になると仮定すると辻褄が合う気がします。

    本仮定が妥当な場合、その点からのご見解もお聞かせいただけますでしょうか。
    以上、宜しくお願い致します。

    #7489 返信
    Yojiro
    Yojiro
    従業員

    amatsu1さん

    (IoutCommand_Ch1 – IoutDetect_Ch1) < 0になった時に (IoutCommand_Ch1 – IoutDetect_Ch1)が
    マイナスになることを想定しているのですが、そうなっておらず、
    0になると仮定すると辻褄が合う気がします。

    ご指摘頂いた点ですが、_iq宣言は実際はsigned longですので、減算で負になる場合でも0になることはありません。

    制御ループ内の次回に使用する演算結果(CtrlVal1_Ch1)をCMPAレジスタへの設定値から保存されていますが、CMPAの小数部は8ビットになり、CtrlVal1_Ch1=EPwm3Regs.CMPA.all;により演算結果の下位8ビットは切り捨てられます。

    例として、エラー(IoutCommand_Ch1 – IoutDetect_Ch1)が1000 だった時を考えてみたいと思います。
    エラーが1000の場合、左14ビットシフトしているので Ierror0_CH1は1000 << 14= 0x3E8 * 16384 = 0xFA0000になります。
    K0=0.00002(=0x0000_0001)で、__IQmpy(K0,Ierror0_Ch1,16)を計算しても、0x0000_00FAとなり前回の反映値に対し加算したとしても、CMPA/CMPAHRレジスタの設定値に変化はありません。
    これが、原因であると考えます。

    次回に使用する演算結果(CtrlVal1_Ch1)は、CMPAレジスタ設定値ではなく、以下のように、演算結果を使用してご確認頂けますでしょうか。

    NxtCntVal_Ch1 = __IQmpy(K0,Ierror0_Ch1,16)+__IQmpy(K2,CtrlVal1_Ch1,16);
    EPwm3Regs.CMPA.all=__IQsat(NxtCntVal_Ch1, MAX_CNTVAL, MIN_CNTVAL);
    CtrlVal1_Ch1=EPwm3Regs.CMPA.all;

    NxtCntVal_Ch1 = __IQmpy(K0,Ierror0_Ch1,16)+__IQmpy(K2,CtrlVal1_Ch1,16);
    CtrlVal1_Ch1 =__IQsat(NxtCntVal_Ch1, MAX_CNTVAL, MIN_CNTVAL);
    EPwm3Regs.CMPA.all = CtrlVal1_Ch1;

    ご確認のほど、よろしくお願いいたします。

    #7492 返信

    amatsu1
    参加者

    ご回答いただき、誠にありがとうございます。

    CMPA32bitの下位8bitが予約ということを失念しておりました。

    ご教示いただいた内容を反映させていただいたところ、
    負荷の上げ下げに関わらず、3A制御ができるようになりました。

    ご対応いただき、重ね重ね誠にありがとうございました。

6件の投稿を表示中 - 1 - 6件目 (全6件中)