使用java连接西门子S7 1200PLC,读写数据

Source

一:PLC设置

plc右键属性中需要设置以下几个点
1:web服务器中的----常规这两个选项勾选上

2: 防护与安全 选择 连接机制 勾选 允许来自远程对象的PUT/GET通信访问
3:设置一下PLC的IP地址(不用设置也行,知道IP就行)
4:创建 java读写的db数据块,设置编号,等会要用,不想改代码就,编号设置为5
5:选择数据库右键选择属性,去掉优化快速访问

6:创建一些输入输出变量,等会读取和写入
7:将输出赋值初始值

8:编译装载到PLC上面

二:IDEA搭建

IDEA软件下好之后,需要自己搞一个maven用作自己的仓库,存放各种依赖(不然就手动下载jar包导入进去)

1:新建项目,搭建项目的一些基础依赖就不展示了,只需要在pom.xml中添加一下这个依赖就行

<dependency>
    <groupId>com.github.s7connector</groupId>
    <artifactId>s7connector</artifactId>
    <version>2.1</version>
</dependency>

2:只需要在src下面的main里面的java下面创建一个plc的包就行,我这个是用练手的项目连接PLC的,不需要和我一样

3:连接class类

public class S7ConnectorPLC {
    public S7Connector initConnect(String ipAddress) {
        //默认端口
//      创建与PLC的链接
        S7Connector connector = S7ConnectorFactory.buildTCPConnector()
                .withHost(ipAddress)
                .withRack(0) // 架机号 可选,建议选择,可能会报错
                .withSlot(1) // 插槽号 可选,建议选择,可能会报错
                .build();
        return connector;
    }

}

读取class,之前创建的DB块的编号在这里面用上,区块编号

public class ReadPLC {
    //Int类型的封装类 用来转义
    private static IntegerConverter intCon = new IntegerConverter();
    //String...
    private static StringConverter strCon = new StringConverter();
    //Boolean...
    private static BitConverter boolCon = new BitConverter();
    //real实数浮点...
    private static RealConverter realCon = new RealConverter();

    //获取到的数据存储
    public boolean in_bool = false;//bool
    public Integer in_int = null;//int
    public String in_String = "";//string
    public double in_real = 0.0;//real

    public void Cyclic_read(S7Connector connector) {

        byte[] PlcData = null;
        //读取bool型
        PlcData = connector.read(DaveArea.DB, // 选择数据区块
                5, // 区块编号
                1, // 数据值长度 boolean长度1
                0); // 开始位置偏移量
        Boolean extract_bool = boolCon.extract(new Boolean(false).getClass(), PlcData, 0, 0);//接收转换的数值
        in_bool = extract_bool;//赋值给全局变量

//        读取整型
        PlcData = connector.read(DaveArea.DB, // 选择数据区块
                5, // 区块编号
                2, // 数据值长度 int长度2
                2); // 开始位置 偏移量
        Integer extract_int = intCon.extract(new Integer(0).getClass(), PlcData, 0, 0);
        in_int = extract_int;

//        读取字符串型
        PlcData = connector.read(DaveArea.DB, // 选择数据区块
                5, // 区块编号
                16, // 数据值长度 String最小3 随值长度增加
                4); // 开始位置偏移量
        String extract_string = strCon.extract(new String().getClass(), PlcData, 0, 0);
        in_String = extract_string;

//        读取小数型
        PlcData = connector.read(DaveArea.DB, // 选择数据区块
                5, // 区块编号
                4, // 数据值长度 double长度4
                260); //偏移量
        Double num1 = realCon.extract(new Double(0).getClass(), PlcData, 0, 0);
        /*        BigDecimal bd1 = new BigDecimal(num1);
        System.out.println("转换real浮点= " + bd1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());*/
        in_real = num1;

        try {
            connector.close();//关闭链接
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}

写入class

public class Java_To_write {
    //@Test
    public void Java_To_write(S7Connector connector) {
        byte[] bytes = null;

        boolean out_boolen = true;
//        bytes = S7Type.BOOL;
//        connector.write(DaveArea.DB, 5, 264, bytes);

//        向plc中写int整型数据
//        向PLC中写短整型(2字节,对应PLC INT类型)数据
        //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数:DB块地址,若plc中是DB1000,则填1000
        //第三个参数:偏移量
        //第四个参数:写入的数据 二进制数组byte[]
        short out_int = 15;
        bytes = ByteBuffer.allocate(2).putShort(out_int).array();
        connector.write(DaveArea.DB, 5, 266, bytes);

//        向PLC中写整型(4字节,对应PLC DINT类型)数据
        int data=15;
         bytes = ByteBuffer.allocate(4).putInt(data).array();
        connector.write(DaveArea.DB,5, 528,bytes);


//        写入字符串
        //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数:DB块地址,若plc中是DB1000,则填1000
        //第三个参数:偏移量
        //第四个参数:写入的数据 二进制数组byte[]  ,总长度为10的话,有效数据只能是10-8,第一位代表总长,第二位,代表有效数据字节
        String out_string = "helloPlc";
        int writeStrLength = 10;//地址块大小
        byte[] writeBytes = new byte[writeStrLength];
        writeBytes[0] = (byte) writeStrLength;//写入本字符串块总宽度
        out_string = out_string.trim();//清除掉两边的空串
        int availableEffectCharLength = 0;//有效字符数控制
        if (out_string.length() > writeStrLength - 2) {//>writeStrLength-2 截断到最大有效数据位
            availableEffectCharLength = writeStrLength - 2;

        } else {//<=writeStrLength-2
            availableEffectCharLength = out_string.length();
        }
        writeBytes[1] = (byte) availableEffectCharLength;//写入有效字节数
        byte[] strBytes = out_string.getBytes(StandardCharsets.US_ASCII);
        for (int i = 0; i < availableEffectCharLength; i++) {
            writeBytes[i + 2] = strBytes[i];
        }
        connector.write(DaveArea.DB, 5, 268, writeBytes);


        /**
         * 写入PLC中的浮点型数据
         * java float : plc Real 4 字节
         * java double : plc LReal 8 字节
         **/
        //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数:DB块地址,若plc中是DB1000,则填1000
        //第三个参数:偏移量
        //第四个参数:写入的数据 二进制数组byte[]
        float out_real=new Float(5.54);
        bytes = ByteBuffer.allocate(4).putFloat(out_real).array();
        connector.write(DaveArea.DB,5, 524,bytes);

        /**
         * 写入PLC中的浮点型LREAL(java中是double)数据
         * java float : plc Real 4 字节
         * java double : plc LReal 8 字节
         **/
        //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数:DB块地址,若plc中是DB1000,则填1000
        //第三个参数:偏移量
        //第四个参数:写入的数据 二进制数组byte[]
        float out_Lreal=new Float(15.56);
        bytes = ByteBuffer.allocate(8).putDouble(out_Lreal).array();
        connector.write(DaveArea.DB,5, 532,bytes);


        try {
            connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}

测试class,PLC的IP地址不要忘记改成自己的,上面注释代码是测试读取的,想测试读取将注释取消掉,下面三行注释。

public class domain {
    public static void main(String[] args) throws InterruptedException {

        ReadPLC readPLC = new ReadPLC();//创建读取plc数据对象
/*        while (true) {
            S7Connector connector = initConnect();//初始化
            readPLC.Cyclic_read(connector);//读取
            System.out.println("=============读取plc信息==============");
            System.out.println(readPLC.in_bool);
            System.out.println(readPLC.in_int);
            System.out.println(readPLC.in_String);
            System.out.println(readPLC.in_real);
            System.out.println("=============读取plc信息==============");
            Thread.sleep(1000);//stop 0.5s
        }*/
        Java_To_write plcwrite = new Java_To_write();
        S7Connector connector = initConnect();//初始化
        plcwrite.Java_To_write(connector);
    }

    public static S7Connector initConnect() {
        S7ConnectorPLC s7ConnectorPLC = new S7ConnectorPLC();
        S7Connector connector = s7ConnectorPLC.initConnect("192.168.0.101");//plc地址
        return connector;
    }
}

在测试类中右键运行

额外:启动项目部署,在浏览器中显示,在controller控制层中将数据传到前台页面中

写入一样的,定义一个输入框,限制类型,通过表单什么的将数据传到后台,根据类型去调用

Java_To_write里面的函数,将数据传到PLC

注意:本次连接使用的PLC型号是1214c,全部都是实物,没有任何仿真模拟。

本文参考地址java读写西门子1500plc数据块 - 知乎 (zhihu.com),没有实物的可以看看这篇