浏览代码

pid + 下垂

xiuwei 1 年之前
父节点
当前提交
128026651d

+ 5 - 0
pom.xml

@@ -14,6 +14,11 @@
             <version>1.18.16</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>wei.yigulu</groupId>
+            <artifactId>protocol-iec104</artifactId>
+            <version>2.4.23</version>
+        </dependency>
     </dependencies>
 
 

+ 19 - 18
src/main/java/contorllogic/PidController.java

@@ -1,6 +1,9 @@
 package contorllogic;
 
 import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
 
 /**
  * PID控制器
@@ -25,29 +28,27 @@ import lombok.Data;
  */
 
 @Data
+@NoArgsConstructor
 public class PidController {
-    private double kp; // 比例系数 控制着控制器对误差的响应速度
-    private double ki; // 积分系数 控制着控制器对误差的持续时间的响应
-     private double kd; // 微分系数 控制着控制器对误差变化率的响应
-    private double setpoint; // 目标值
-    private double integral; // 积分项
-    private double lastError; // 上一次误差
+    private BigDecimal kp=BigDecimal.ONE; // 比例系数 控制着控制器对误差的响应速度
+    private BigDecimal ki=BigDecimal.valueOf(0.1); // 积分系数 控制着控制器对误差的持续时间的响应
+    private BigDecimal kd=BigDecimal.valueOf(0); // 微分系数 控制着控制器对误差变化率的响应
+    private BigDecimal ratedFrequency = BigDecimal.valueOf(50); // 频率目标值
+    private BigDecimal integral = BigDecimal.ZERO; // 积分项
+    private BigDecimal lastError = BigDecimal.ZERO; // 上一次误差
 
-    public PidController(double kp, double ki, double kd, double setpoint) {
-        this.kp = kp;
-        this.ki = ki;
-        this.kd = kd;
-        this.setpoint = setpoint;
-        this.integral = 0;
-        this.lastError = 0;
+    public PidController (BigDecimal kp,BigDecimal ki,BigDecimal kd){
+        this.kp=kp;
+        this.ki=ki;
+        this.kd=kd;
     }
 
-    public double calculate(double input) {
+    public BigDecimal calculate(BigDecimal input) {
         //目标值减当前值 求出差距值
-        double error = setpoint - input;
-        integral += error;
-        double derivative = error - lastError;
+        BigDecimal error = ratedFrequency.subtract(input);
+        integral=integral.add(error);
+        BigDecimal derivative = error.subtract(lastError);
         lastError = error;
-        return kp * error + ki * integral + kd * derivative;
+        return kp.multiply(error).add(ki.multiply(integral)).add(kd.multiply(derivative));
     }
 }

+ 48 - 0
src/main/java/contorllogic/PowerVariationCalculator.java

@@ -0,0 +1,48 @@
+package contorllogic;
+
+import java.math.BigDecimal;
+
+/**
+ * △P 计算  通过△f
+ * △P = 目标有功- 当前有功
+ * <p>
+ * △P=-1/δ%*Pn*△f/fn
+ */
+public class PowerVariationCalculator {
+
+
+    /**
+     * 装机容量
+     */
+    private BigDecimal Pn=BigDecimal.valueOf(50);
+
+    /**
+     * 额定频率
+     */
+    private BigDecimal Fn=BigDecimal.valueOf(50);
+
+
+    /**
+     * 调差率
+     */
+    private BigDecimal slope=BigDecimal.valueOf(3);
+
+
+    /**
+     *  计算需要调节的有功的变化值
+     * @param f 频率
+     * @return  有功变化调节值
+     */
+    public  BigDecimal calculate(BigDecimal f){
+        BigDecimal g1 = BigDecimal.valueOf(-100).divide(slope, 2, BigDecimal.ROUND_HALF_UP);
+        BigDecimal g2 = f.subtract(Fn).divide(Fn, 2, BigDecimal.ROUND_HALF_UP);
+        return  g1.multiply(Pn).multiply(g2);
+    }
+
+
+
+
+
+
+
+}

+ 0 - 12
src/main/java/contorllogic/Test.java

@@ -1,12 +0,0 @@
-package contorllogic;
-
-public class Test {
-    public static void main(String[] args) {
-        PidController pidController = new PidController(1, 0.01, 0, 20);
-
-
-        for (int i = 0; i < 30; i++) {
-            System.out.println(pidController.calculate(i));
-        }
-    }
-}

+ 146 - 0
src/main/java/fmprotocol/DataBean.java

@@ -0,0 +1,146 @@
+package fmprotocol;
+
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+@Setter
+public class DataBean {
+
+    //频率
+    private BigDecimal F=BigDecimal.valueOf(-99);
+
+
+    //A相电压
+    private BigDecimal Ua=BigDecimal.valueOf(-99);
+    //B相电压
+    private BigDecimal Ub=BigDecimal.valueOf(-99);
+    //C相电压
+    private BigDecimal Uc=BigDecimal.valueOf(-99);
+
+
+    //A相电流
+    private BigDecimal Ia=BigDecimal.valueOf(-99);
+    //B相电流
+    private BigDecimal Ib=BigDecimal.valueOf(-99);
+    //C相电流
+    private BigDecimal Ic=BigDecimal.valueOf(-99);
+
+
+    //A相有功
+    private BigDecimal Pa=BigDecimal.valueOf(-99);
+    //B相有功
+    private BigDecimal Pb=BigDecimal.valueOf(-99);
+    //C相有功
+    private BigDecimal Pc=BigDecimal.valueOf(-99);
+
+
+    //A相无功
+    private BigDecimal Qa=BigDecimal.valueOf(-99);
+    //B相无功
+    private BigDecimal Qb=BigDecimal.valueOf(-99);
+    //C相无功
+    private BigDecimal Qc=BigDecimal.valueOf(-99);
+
+
+    //A相视在功率
+    private BigDecimal Sa=BigDecimal.valueOf(-99);
+    //B相视在功率
+    private BigDecimal Sb=BigDecimal.valueOf(-99);
+    //C相视在功率
+    private BigDecimal Sc=BigDecimal.valueOf(-99);
+
+
+    //A相未发生过流
+    private Boolean OIIa = false;
+    //B相未发生过流
+    private Boolean OIIb = false;
+    //C相未发生过流
+    private Boolean OIIc = false;
+
+
+    //A相未发生过压
+    private Boolean OVUa = false;
+    //B相未发生过压
+    private Boolean OVUb = false;
+    //C相未发生过压
+    private Boolean OVUc = false;
+
+
+    //A相是否失压
+    private Boolean LostVoltA = false;
+    //B相是否失压
+    private Boolean LostVoltB = false;
+    //C相是否失压
+    private Boolean LostVoltC = false;
+
+
+    //电压相序是否异常
+    private Boolean UPhSqErr = false;
+
+
+    public String toString() {
+        return "频率:" + F + " ;   </br>" +
+                "A相电压:" + Ua + " ;   B相电压:" + Ub + " ;   C相电压:" + Uc + " ;   </br>" +
+                "A相电流:" + Ia + " ;   B相电流:" + Ib + " ;   C相电流:" + Ic + " ;   </br>" +
+                "A相有功:" + Pa + " ;   B相有功:" + Pb + " ;   C相有功:" + Pc + " ;   </br>" +
+                "A相无功:" + Qa + " ;   B相无功:" + Qb + " ;   C相无功:" + Qc + " ;   </br>" +
+                "A相视在:" + Sa + " ;   B相视在:" + Sb + " ;   C相视在:" + Sc + " ;   </br>" +
+                "A相过流:" + (OIIa ? "是" : "否") + " ;   B相过流:" + (OIIb ? "是" : "否") + " ;   C相过流:" + (OIIc ? "是" : "否") + " ;   </br>" +
+                "A相过压:" + (OVUa ? "是" : "否") + " ;   B相过压:" + (OVUb ? "是" : "否") + " ;   C相过压:" + (OVUc ? "是" : "否") + " ;   </br>" +
+                "A相失压:" + (LostVoltA ? "是" : "否") + " ;   B相失压:" + (LostVoltB ? "是" : "否") + " ;   C相失压:" + (LostVoltC ? "是" : "否") + " ;   </br>" +
+                "电压相序:" + (UPhSqErr ? "异常" : "正常");
+
+    }
+
+
+    public String toWebString() {
+        return "频率:" + F + " ;   </br>" +
+                "A相电压:" + Ua + " ;   B相电压:" + Ub + " ;   C相电压:" + Uc + " ;   </br>" +
+                "A相电流:" + Ia + " ;   B相电流:" + Ib + " ;   C相电流:" + Ic + " ;   </br>" +
+                "A相有功:" + Pa + " ;   B相有功:" + Pb + " ;   C相有功:" + Pc + " ;   </br>" +
+                "A相无功:" + Qa + " ;   B相无功:" + Qb + " ;   C相无功:" + Qc + " ;   </br>" +
+                "A相视在:" + Sa + " ;   B相视在:" + Sb + " ;   C相视在:" + Sc + " ;   </br>" +
+                "A相过流:" + (OIIa ? "是" : "否") + " ;   B相过流:" + (OIIb ? "是" : "否") + " ;   C相过流:" + (OIIc ? "是" : "否") + " ;   </br>" +
+                "A相过压:" + (OVUa ? "是" : "否") + " ;   B相过压:" + (OVUb ? "是" : "否") + " ;   C相过压:" + (OVUc ? "是" : "否") + " ;   </br>" +
+                "A相失压:" + (LostVoltA ? "是" : "否") + " ;   B相失压:" + (LostVoltB ? "是" : "否") + " ;   C相失压:" + (LostVoltC ? "是" : "否") + " ;   </br>" +
+                "电压相序:" + (UPhSqErr ? "异常" : "正常");
+
+    }
+
+
+    public List<String> toWebDataList() {
+       List<String> list=new ArrayList<>();
+       list.add(F.toString());
+       list.add(Ua.toString());
+        list.add(Ub.toString());
+        list.add(Uc.toString());
+        list.add(Ia.toString());
+        list.add(Ib.toString());
+        list.add(Ic.toString());
+        list.add(Pa.toString());
+        list.add(Pb.toString());
+        list.add(Pc.toString());
+        list.add(Qa.toString());
+        list.add(Qb.toString());
+        list.add(Qc.toString());
+        list.add(Sa.toString());
+        list.add(Sb.toString());
+        list.add(Sc.toString());
+
+        list.add(OIIa?"是":"否");
+        list.add(OIIb?"是":"否");
+        list.add(OIIc?"是":"否");
+        list.add(OVUa?"是":"否");
+        list.add(OVUb?"是":"否");
+        list.add(OVUc?"是":"否");
+
+        list.add(LostVoltA?"是":"否");
+        list.add(LostVoltB?"是":"否");
+        list.add(LostVoltC?"是":"否");
+        list.add(UPhSqErr?"是":"否");
+        return list;
+    }
+}

+ 108 - 0
src/main/java/fmprotocol/DataBeanPacker.java

@@ -0,0 +1,108 @@
+package fmprotocol;
+
+import io.netty.buffer.ByteBuf;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+public class DataBeanPacker {
+
+
+    private DataBean lastDataBean = new DataBean();
+
+
+    private DataBeanPacker() {
+    }
+
+
+    private static class LazyHolder {
+        private static final DataBeanPacker INSTANCE = new DataBeanPacker();
+    }
+
+    /**
+     * 获取单例实例
+     *
+     * @return the instance
+     */
+    public static final DataBeanPacker getInstance() {
+        return DataBeanPacker.LazyHolder.INSTANCE;
+    }
+
+    public synchronized DataBean getLastDataBean() {
+        return this.lastDataBean;
+    }
+
+    public synchronized DataBean setLastDataBean(DataBean dataBean) {
+        this.lastDataBean = dataBean;
+        return this.lastDataBean;
+    }
+
+    public DataBean decodeAnRecode(ByteBuf byteBuf) {
+        return setLastDataBean(decode(byteBuf));
+    }
+
+
+    public static DataBean decode(ByteBuf byteBuf) {
+        byteBuf.readInt();
+        DataBean dataBean = new DataBean();
+        dataBean.setUa(decodeBA(byteBuf).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
+        dataBean.setUb(decodeBA(byteBuf).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
+        dataBean.setUc(decodeBA(byteBuf).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
+
+
+        dataBean.setIa(decodeBA(byteBuf).divide(BigDecimal.valueOf(10), 1, RoundingMode.HALF_UP));
+        dataBean.setIb(decodeBA(byteBuf).divide(BigDecimal.valueOf(10), 1, RoundingMode.HALF_UP));
+        dataBean.setIc(decodeBA(byteBuf).divide(BigDecimal.valueOf(10), 1, RoundingMode.HALF_UP));
+
+
+        dataBean.setPa(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+        dataBean.setPb(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+        dataBean.setPc(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+
+
+        dataBean.setQa(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+        dataBean.setQb(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+        dataBean.setQc(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+
+
+        dataBean.setSa(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+        dataBean.setSb(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+        dataBean.setSc(decodeDCBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+
+
+        dataBean.setF(decodeBA(byteBuf).divide(BigDecimal.valueOf(1000), 3, RoundingMode.HALF_UP));
+
+        byte b = byteBuf.readByte();
+        dataBean.setOVUc((byte) ((b) & 0x01) == 0x01);
+        dataBean.setOVUb((byte) ((b >> 1) & 0x01) == 0x01);
+        dataBean.setOVUa((byte) ((b >> 2) & 0x01) == 0x01);
+        dataBean.setOIIc((byte) ((b >> 3) & 0x01) == 0x01);
+        dataBean.setOIIb((byte) ((b >> 4) & 0x01) == 0x01);
+        dataBean.setOIIa((byte) ((b >> 5) & 0x01) == 0x01);
+        b = byteBuf.readByte();
+        dataBean.setLostVoltC((byte) ((b) & 0x01) == 0x01);
+        dataBean.setLostVoltB((byte) ((b >> 1) & 0x01) == 0x01);
+        dataBean.setLostVoltA((byte) ((b >> 2) & 0x01) == 0x01);
+        dataBean.setUPhSqErr((byte) ((b >> 3) & 0x01) == 0x01);
+        return dataBean;
+    }
+
+
+    private static BigDecimal decodeBA(ByteBuf byteBuf) {
+        return BigDecimal.valueOf(((byteBuf.readByte() & 0xff) | ((byteBuf.readByte() & 0xff) << 8)));
+    }
+
+
+    private static BigDecimal decodeDCBA(ByteBuf byteBuf) {
+        return BigDecimal.valueOf((byteBuf.readByte() & 0xff) | ((byteBuf.readByte() & 0xff) << 8)
+                | ((byteBuf.readByte() & 0xff) << 16) | ((byteBuf.readByte() & 0xff) << 24));
+    }
+
+    private static BigDecimal decode_F_DCBA(ByteBuf byteBuf) {
+       return new BigDecimal(Float.toString(Float.intBitsToFloat((byteBuf.readByte() & 0xff) | ((byteBuf.readByte() & 0xff) << 8)
+                | ((byteBuf.readByte() & 0xff) << 16) | ((byteBuf.readByte() & 0xff) << 24))));
+    }
+    private static BigDecimal decode_F_BA(ByteBuf byteBuf) {
+        return new BigDecimal(Float.toString(Float.intBitsToFloat((byteBuf.readByte() & 0xff) | ((byteBuf.readByte() & 0xff) << 8))));
+    }
+}

+ 37 - 0
src/main/java/fmprotocol/FmRtuMasterBuilder.java

@@ -0,0 +1,37 @@
+package fmprotocol;
+
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+import wei.yigulu.netty.AbstractRtuModeBuilder;
+import wei.yigulu.netty.ProtocolChannelInitializer;
+import wei.yigulu.purejavacomm.PureJavaCommChannel;
+
+/**
+ * cdt的客户端
+ *
+ * @author: xiuwei
+ * @version:
+ */
+@Accessors(chain = true)
+@Slf4j
+public class FmRtuMasterBuilder extends AbstractRtuModeBuilder {
+
+
+    public FmRtuMasterBuilder(String commPortId) {
+        super(commPortId);
+    }
+
+    @Override
+    protected ProtocolChannelInitializer getOrCreateChannelInitializer() {
+        if (this.channelInitializer == null) {
+            this.channelInitializer = new ProtocolChannelInitializer<PureJavaCommChannel>(this) {
+                @Override
+                protected void initChannel(PureJavaCommChannel ch) throws Exception {
+                    ch.pipeline().addLast(new FmRtuMasterDelimiterHandler().setLog(getLog()));
+                    ch.pipeline().addLast(new FmRtuMasterHandler((FmRtuMasterBuilder) builder));
+                }
+            };
+        }
+        return this.channelInitializer;
+    }
+}

+ 95 - 0
src/main/java/fmprotocol/FmRtuMasterDelimiterHandler.java

@@ -0,0 +1,95 @@
+package fmprotocol;
+
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import org.joda.time.DateTime;
+import wei.yigulu.netty.AbstractDelimiterHandler;
+import wei.yigulu.utils.DataConvertor;
+
+
+/**
+ * 未继承netty的数据帧处理拆包类
+ *
+ * @author 修唯xiuwei
+ * @version 3.0
+ */
+
+public class FmRtuMasterDelimiterHandler extends AbstractDelimiterHandler {
+
+
+    private static byte HEAD_TAIL_1 = (byte) 0xff;
+
+    private static byte HEAD_TAIL_2 = (byte) 0x55;
+
+
+    private static final int LENGTH = 56;
+
+    /**
+     * 判断是否是断包的最大时间间隔
+     */
+    @Setter
+    @Getter
+    @Accessors(chain = true)
+    protected int maxTimeSpace = 250;
+
+
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+        log.info("-----------------------------------------------------------------");
+        log.info("接收到原始的报文 :" + DataConvertor.ByteBuf2String((ByteBuf) msg));
+        if (isOverMaxLength((ByteBuf) msg)) {
+            return;
+        }
+
+        if (!((cumulation.readableBytes() == 1 && cumulation.getByte(0) == HEAD_TAIL_1) ||
+                cumulation.readableBytes() > 2 && checkHead(cumulation))) {
+            log.warn("该段报文未以ff 55开头");
+            int headIndex = getHeadIndex(cumulation.readerIndex(), cumulation.writerIndex(), cumulation, new byte[]{HEAD_TAIL_1, HEAD_TAIL_2});
+            if (headIndex != -1) {
+                log.warn("该段报文发现ff 55 的报文片段,,舍弃部分报文:" + DataConvertor.ByteBuf2String(cumulation.readBytes(headIndex+2)));
+            } else {
+                log.warn("该段报文未发现ff 55 的报文片段,整段报文全部清除");
+                log.warn("这段字节中没有数据头,舍弃:" + DataConvertor.ByteBuf2String(cumulation.readBytes(cumulation.readableBytes())));
+                clearCumulation();
+                return;
+            }
+        }
+        while (cumulation.readableBytes() >= LENGTH) {
+            ByteBuf byteBuf = cumulation.readBytes(LENGTH);
+            if (checkHead(byteBuf) && checkTail(byteBuf)) {
+                log.info("发现符合ff 55开头,ff 55 结尾的56字节报文");
+                ctx.fireChannelRead(byteBuf);
+            }else{
+                log.info("该56字节不符合ff 55开头,ff 55 结尾的格式");
+                log.info( DataConvertor.ByteBuf2String(byteBuf));
+                byteBuf.release();
+            }
+        }
+        if (cumulation.readableBytes() == 0) {
+            clearCumulation();
+        } else {
+            timeMark = DateTime.now();
+        }
+
+    }
+
+
+    private boolean checkHead(ByteBuf msg) {
+        if (msg.getByte(0) == HEAD_TAIL_1 & msg.getByte(1) == HEAD_TAIL_2) {
+            return true;
+        }
+        return false;
+    }
+
+
+    private boolean checkTail(ByteBuf msg) {
+        if (msg.getByte(msg.readableBytes() - 2) == HEAD_TAIL_1 & msg.getByte(msg.readableBytes() - 1) == HEAD_TAIL_2) {
+            return true;
+        }
+        return false;
+    }
+}

+ 71 - 0
src/main/java/fmprotocol/FmRtuMasterHandler.java

@@ -0,0 +1,71 @@
+package fmprotocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.EventLoop;
+import io.netty.channel.SimpleChannelInboundHandler;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import wei.yigulu.utils.DataConvertor;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 16进制报文解析工具
+ *
+ * @author xiuwei
+ */
+@Data
+@Slf4j
+public class FmRtuMasterHandler extends SimpleChannelInboundHandler<ByteBuf> {
+
+
+    private static final int LEN = 52;
+
+    private FmRtuMasterBuilder FmMaster;
+
+    public FmRtuMasterHandler(FmRtuMasterBuilder FmMaster) {
+        this.FmMaster = FmMaster;
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        FmMaster.getLog().info("-----连接串口{}成功-----", this.FmMaster.getCommPortId());
+    }
+
+    /**
+     * channel断连及不稳定时调用的方法
+     *
+     * @param ctx
+     * @throws Exception
+     */
+    @Override
+    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+        FmMaster.getLog().error("串口{}连接中断,正在启动重连机制... ", this.FmMaster.getCommPortId());
+        //在客户端与服务端连接过程中如果断连,就会调用的方法
+        final EventLoop eventLoop = ctx.channel().eventLoop();
+        eventLoop.schedule(() -> {
+            FmMaster.getLog().info("正在重连串口{}", this.FmMaster.getCommPortId());
+            this.FmMaster.create();
+        }, 3L, TimeUnit.SECONDS);
+    }
+
+    /**
+     * channel连接及传输报错时调用的方法
+     *
+     * @param ctx
+     * @param cause
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+        FmMaster.getLog().error("串口异常消息:", cause);
+    }
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
+       FmMaster.getLog().info("接收到串口{}发来数据帧: <= " + DataConvertor.ByteBuf2String(msg), this.FmMaster.getCommPortId());
+        if (msg.readableBytes() == LEN) {
+            DataBeanPacker.getInstance().decodeAnRecode(msg);
+        }
+    }
+}

+ 14 - 0
src/test/java/Test.java

@@ -0,0 +1,14 @@
+import contorllogic.PidController;
+import contorllogic.PowerVariationCalculator;
+
+import java.math.BigDecimal;
+
+public class Test {
+    public static void main(String[] args) {
+        PidController pidController = new PidController();
+        PowerVariationCalculator pc=new PowerVariationCalculator();
+        for (int i = 0; i < 80; i=i+3) {
+            System.out.println(pc.calculate( pidController.calculate(BigDecimal.valueOf(i))));
+        }
+    }
+}

+ 2 - 0
src/test/java/Testa.java

@@ -0,0 +1,2 @@
+public class Testa {
+}