ホーム › フォーラム › Texas Instruments › マイコン › C2000 › IQ型のデジタル演算式について
このトピックには4件の返信が含まれ、2人の参加者がいます。5 年、 3 ヶ月前に 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;
}以上、宜しくお願い致します。
Attachments:
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ビットに合わせていただく方法のどちらかをご検討頂く必要がございます。
小数部のビット数を大きくすると、整数部の範囲が小さくなりますので、ご注意ください。
ご確認のほど、よろしくお願いいたします。
大変お世話になっております。
ご教示いただき、誠にありがとうございます。誤差発生の原理については理解することができました。
ありがとうございます。恐縮ですが、添付の通り、負荷を上げる時と下げる時で制御結果が変わる点についてもご見解をお願い致します。
以上、宜しくお願い致します。
Attachments:
大変お世話になっております。
上記のご質問の件ですが、こちらでも原因解析しておりますが、
(IoutCommand_Ch1 – IoutDetect_Ch1) < 0になった時に (IoutCommand_Ch1 – IoutDetect_Ch1)が
マイナスになることを想定しているのですが、そうなっておらず、
0になると仮定すると辻褄が合う気がします。本仮定が妥当な場合、その点からのご見解もお聞かせいただけますでしょうか。
以上、宜しくお願い致します。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;ご確認のほど、よろしくお願いいたします。
ご回答いただき、誠にありがとうございます。
CMPA32bitの下位8bitが予約ということを失念しておりました。
ご教示いただいた内容を反映させていただいたところ、
負荷の上げ下げに関わらず、3A制御ができるようになりました。ご対応いただき、重ね重ね誠にありがとうございました。
-
投稿者投稿