原创 【TI博客大赛】DSP程序里的重构

2012-10-16 13:07 1599 5 5 分类: 处理器与DSP

【重构动机】

看了一半重构的书,真心感觉以前写的代码很烂。耦合严重,维护困难。于是重构第一刀就是刚写的重复控制器实验平台。

由于CCS编译器中对C++ template 支持不是很完善,所以只能使用较常用的,先前的代码已经贴了,现在讲讲改进后的。

原先程序中最大的缺陷在于重复控制器被我写成了两个类,由于gamma轴与alpha、beta轴中无差拍部分不一样,gamma轴需要在电感和电阻的系数上乘以4,所以只好分了两个类来实现。

class CFControler;

class CF4Controler;

这样做虽然可以成功,但存在严重的维护问题,由于是重复控制附加在无差拍上的,一旦重复控制器的结构和参数有所改变,两个类里面的都得改变,copy/paste的手法一直是写程序最忌讳的手法(重构给我带来的第一个也是最重要的启发),如果能够将相同的提取出来,不同的分离出来,便是一个很好的策略。

【做法/步骤】

原来的调用过程是这样的:

CFControler<_iq> CtrlA;//alpha

CFControler<_iq> CtrlB;//beta

CF4Controler<_iq> CtrlG;//gamma

ctrlOutA = CtrlA(referenceA, feedbackA, voltageA);

ctrlOutB = CtrlB(referenceB, feedbackB, voltageB);

ctrlOutG = CtrlG(referenceG, feedbackG, voltageG);

重构的基本原则是不改变外部结构,因此我想这些调用也保持不变。

如果先写测试代码,我想是这样一个效果:

CFControler<_iq,ctrlAB> CtrlA;//alpha

CFControler<_iq,ctrlAB> CtrlB;//beta

CFControler<_iq,ctrlG> CtrlG;//gamma

ctrlOutA = CtrlA(referenceA, feedbackA, voltageA);

ctrlOutB = CtrlB(referenceB, feedbackB, voltageB);

ctrlOutG = CtrlG(referenceG, feedbackG, voltageG);

因为我想只保持一个类,因此声明类时,我只需在template中第二参数指明是哪种类型的控制器即可。

下面进行修改:

先声明两个空类,用来函数的分流:

class ctrlAB{}; //for controler of alpha and beta

class ctrlG{};  //for controler of gamma

然后在类中增加GetDeadbeat函数,这两个函数在不同的控制器不同,因此需要分开写。

template

class CFControler

{

typedef ctlType __ctlType;

public:

CFControler():jiaozheng_y(0),jiaozheng_x(0){}

T operator()(T ref,T feedback,T voltage);

private:

queue y;,202>

queue x;,200>

T GetDeadbeat(T current, T feedback, T voltage, ctrlAB) // alpha and beta

{

T result = current * 40 ;

result = voltage - result - _IQmpy(feedback,_IQ(0.3));

return result;

}

T GetDeadbeat(T current, T feedback, T voltage, ctrlG)       //gamma

{

T result = current * 160 ;

result = voltage - result - _IQmpy(feedback,_IQ(1.2));

return result;

T jiaozheng_y;

T jiaozheng_x;

};

这样对于operator () 函数可以完全一致:

template

T CFControler::operator ()(T ref,T feedback,T voltage),ctltype>

{

T e,ctlOut;

e =ref - feedback;

//这是最终的重复控制器

/*

ctlOut = _IQmpy(y.Get(1),_IQ(0.7408));

ctlOut += _IQmpy(y.Get(199),_IQ(0.25));

ctlOut += _IQmpy(y.Get(200),_IQ(0.3148));

ctlOut -= _IQmpy(y.Get(201),_IQ(0.1204));

ctlOut -= _IQmpy(y.Get(202),_IQ(0.1852));

ctlOut += _IQmpy(x.Get(197),_IQ(0.125));

ctlOut += _IQmpy(x.Get(198),_IQ(0.12625));

ctlOut -= _IQmpy(x.Get(199),_IQ(0.1225));

ctlOut -= _IQmpy(x.Get(200),_IQ(0.125));

*/

//这是未加校正环节的重复控制器

ctlOut  = _IQmpy(y.Get(199),_IQ(0.25));

ctlOut += _IQmpy(y.Get(200),_IQ(0.5));

ctlOut += _IQmpy(y.Get(201),_IQ(0.25));

ctlOut += x.Get(198);

x.Push(e);

y.Push(ctlOut);

//校正环节

T currentOut = _IQmpy(jiaozheng_y,_IQ(0.7408));

currentOut += ctlOut;

currentOut -= _IQmpy(jiaozheng_x,_IQ(0.99));

jiaozheng_y = currentOut;

jiaozheng_x = ctlOut;

ctlOut = currentOut;

ctlOut = _IQmpy(ctlOut,_IQ(0.2));

ctlOut = ctlOut + e;

//ctlOut = ctlOut + 20 * e;

//无差拍控制

ctlOut = GetDeadbeat(ctlOut,feedback,voltage,__ctlType());

return ctlOut;

}

ctlOut = GetDeadbeat(ctlOut,feedback,voltage,__ctlType());

这句代码是整个分流的核心,也是本次重构的关键技术。

【技术效果】

通过这样的修改,如果重复控制的结构或者参数有所变化,就可以直接在这个类进行修改,没有其他相关联的地方,调试时及其方便,改参数——编译链接——下载——运行,整个过程可能一分钟都不到,比MATLAB仿真调试还要来得方便!~这就是效果!~

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
5
关闭 站长推荐上一条 /3 下一条