Unity連接ModbusTcp發送讀取寄存器


unity連接modbus需要有NModbus4.dll文件

文件地址: (下載地址)

1.配置一個modbus主站(MThings測試軟件挺好用的)

2.unity用來連接

下面直接上代碼

 

using Modbus.Device;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using UnityEngine;


public class Concent_ : MonoBehaviour
{
    public ModbusMaster  modbusIpMaster;
    public TcpClient tcpClient;
    IPAddress address = new IPAddress(new byte[] { 127,0,0,1 });
    public int port = 502;
    
    public bool conen = false;
    public bool Reda_White = false;
    private ushort[] udata = new ushort[]{0x03};
    private ushort star=1;
    Thread mythread;
    //Thread youthread;
    public bool isconect = false;
    // Start is called before the first frame update
    void Start()
    {
        if (Connect (address.ToString (), port))
        {
            Debug.Log("連接成功");
        }
        else
        {
            Debug.Log("連接失敗");
        }
    }
    public bool Connect(string ip, int port)
    {
        try
        {
            tcpClient = new TcpClient(ip, port);

            tcpClient.SendTimeout = 1;
            modbusIpMaster = ModbusIpMaster.CreateIp(tcpClient);
            //開啟另一個線程(可用可不用)
            mythread = new Thread(WriteMessageFromClient);
            //線程開啟
            mythread.Start();
            conen = true;          
            return true;         
        }
        catch (Exception ex)
        {

            tcpClient.Close();

            Debug.LogError(ex.Message);
            return false;
        }
    }

    public void WriteMessageFromClient()
    {
        while (conen)
        {
            try
            {
                if (Reda_White)
                {                  
                    Write_jiChunQi(star, udata);
                    Debug.Log("發送成功");                                      
                }
                if (kuse)
                {
                 ushort [] msg=  modbusIpMaster.ReadHoldingRegisters(0x01,1, 0x01);                  
                }               
            }
            catch
            {
                break;
            }
        }
        tcpClient.Close();
    }
    public void Write_jiChunQi(ushort star,ushort[]data)
    {
        modbusIpMaster.WriteMultipleRegisters(1,star, data);
        
    }   
    /// 10進制轉16進制 
    private byte GetHex(string msg)
    {
        byte hex = Convert.ToByte(msg);
        return hex;
    }
    ///16進制轉10進制 
    public int GetDex(string msg)
    {
        int res = Convert.ToInt32(msg,16);
        return res;
    }
    //退出的時候關閉連接
    private void OnApplicationQuit()
    {
        tcpClient.Close();
    }
    public bool kuse = false;
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //WriteMultipleRegisters(設備地址,寄存器起始地址, 要寫入的值)  
            modbusIpMaster.WriteMultipleRegisters(0x01,star,udata);
            Debug.Log("發送成功");
        }
        if (Input.GetKeyDown (KeyCode.Space))
        {
            //ReadHoldingRegisters(設備地址, 寄存器起始地址, 讀取數量);  讀取多個寄存器
            ushort[] msg = modbusIpMaster.ReadHoldingRegisters(0x01, 1, 0x06);
            foreach (var item in msg)
            {
                Debug.Log(item);
            }                                 
        }
    }
   
}
Modbus連接

 讀取AI模塊

 public void Button_4()
    {
        //讀取AI模塊的值  功能碼04    ReadInputRegisters(設備地址,起始地址,讀取值的地址)        
        ushort[] msg = modbusIpMaster.ReadInputRegisters(0x01, 0x01, 0x01);
        foreach (var item in msg)                      
        {
            //轉換二進制  item是十進制的
            string ooo = Convert.ToString(item, 2);
            string s= ooo;
             //因為數據采集模塊是16位的 所以得往前面補0  變成一個16位數 
            for (int i = 0; i < 16 - ooo.Length; i++)
                s = s.Insert(0, "0");

             //遍歷字符串長度
            for (int i =0;i<s.Length;i++)
            {                
                //看看字符串中哪一位是1 代表數據采集模塊那個對應的孔 是開的狀態 
                if (s[i].ToString() == "1")
                {
                    Debug.Log(16-i+ "");                   
                }                
            }

        }
    }

 

連接PLC1200

using S7.Net;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;
using System.Net;
using System.Net.Sockets;
using Modbus.Device;


public class PLC_Controller : MonoBehaviour
{
    public enum PLCTYPE
    {
        S71200, S7200smart
    }

    Plc PLC1;//= new Plc(CpuType.S71200 ,"192.168.1.1",0,1);
    //在這里對Plc這類進行新建,public Plc(CpuType cpu, string ip, Int16 rack, Int16 slot),這個函數是對連接的Plc進行一個訪問初始化
    //需要的參數有PLC類型、IP地址、插槽號、機架號。其中后兩項在博途CPU屬性中可以查到。
    private TcpClient tcpClient;
    private  ModbusMaster modbusIpMaster;

    public PLCTYPE pLCTYPE = PLCTYPE.S71200;
    Thread PLCLink,NDATLink;
    public byte HighSet;

    public byte result;
    public double RealSet;
    public byte ReadValve;

    public ushort intValve;
    [Header ("模型cube")]
    public Cube_Ration Cube_Ration;
    float UnityHigh;
    // Start is called before the first frame update
    void Start()
    {
        BtnOpen();
       
    }

    public void BtnOpen()
    {

        try
        {
            if (pLCTYPE == PLCTYPE.S71200)
            {
                PLC1 = new Plc(CpuType.S71200, "192.168.1.88", 0, 1);  //這里的是做了一個外部設置IP地址的操作
                PLC1.Open();
            }
            else if (pLCTYPE == PLCTYPE.S7200smart)
            {
                PLC1 = new Plc(CpuType.S7200, "192.168.1.88", 0, 1);  //這里的是做了一個外部設置IP地址的操作
                PLC1.Open();
            }
           
           
            //打開與PLC的連接是有兩種方式,一個是Open();另一個是OpenAsync(),兩者之間的功能是一樣的,前者可以返回錯誤信息,比較適合初學者。

            if (PLC1.IsConnected)   //判斷是否連接
            {

                Debug.Log("Plc is Connected+連接成功");


                PLCLink = new Thread(LinkThread);
                PLCLink.Start();                    //這里我是想做一個階段性的中斷,所以選用另起線程,將查詢和寫入PLC的功能放入新的線程,數據處理在主線程。用來防止線程卡死。
            }
            else
            {
                Debug.Log("PLC 連接不成功,請檢查IP地址、機架、插槽等是否正確");
            }
        }
        catch (Exception ex)
        {
            Debug.Log(ex);

        }
       
    }

    public void BtnClose()
    {
        try
        {
            PLC1.Close();     //關閉與PLC的連接
           
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
          
            throw;
        }
    }

    public void BtnRead()
    {
        //復位按鍵
        try
        {
            PLC1.Write("DB1.DBX0.0", true);  //我做的是Unity上的仿真PID所以需要一個復位按鍵。
            //PLC1.Write("M0.0", false);
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
           
            throw;
        }
    }
    bool db1;
    public void LinkThread()
    {
        while (true)
        {
            if (PLC1.IsConnected)
            {
                //RealSet = Convert.ToDouble(PLC1.Read("DB1.DBW2"));
                //讀取PLC的值,這邊我還沒有做的很滿意,大家可以根據S7.Net的說明書和自己的意圖來寫合適的代碼
                //result = (byte)PLC1.Read("MB103");
                //intValve = (ushort)PLC1.Read("DB3.DBW12");
                //Debug.Log("DB1.DBW2:"+RealSet);
                Thread.Sleep(100);
                //Debug.Log ( PLC1.Read("DB1.DBX0.1"));
                RealSet = Convert.ToDouble(PLC1.Read("Q0.0"));
                Debug.Log(PLC1.Read("M0.0")+"   "+ RealSet+"  "+ Convert.ToInt16(PLC1.Read("VW0")));
                if (Convert.ToBoolean(PLC1.Read("M0.0"))==true|| sderr)
                {
                    Cube_Ration.ration = true;
                    Debug.Log("觸發不觸發:"+Cube_Ration.ration);
                }
                else
                {
                    Cube_Ration.ration = false;
                }
                if (sder )
                {
                    //PLC1.Write("DB1.DBW4", 110); //寫入成功
                    
                    //BtnRead();
                    //Debug.Log(PLC1.Read("DB1.DBX0.1"));
                    PLC1.Write("Q0.1", 1 );
                    PLC1.Write("M0.1", 1);
                    Debug.Log("寫入成功");
                }
                //else if (sderr)
                //{
                //    PLC1.Write("M0.1", false);
                //}

            }
                   
        }
    }
    
 

    private void OnApplicationQuit()
    {
        BtnClose();
    }
    bool sder = false;
    bool sderr = false;
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyUp (KeyCode.Space ))
        {
            sder = false;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            sder = true;
        }
        if (Input.GetKeyUp(KeyCode.A))
        {
            sderr = false;
        }
        if (Input.GetKeyDown(KeyCode.A))
        {
            sderr = true;
        }
    }

}

 

plc_腳本隨便掛在一個物體上面

下面是Cube 測試腳本,接受到PLC信號,cube旋轉測試

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum 旋轉軸
{
    X,Y,Z,NONE
}
public class Cube_Ration : MonoBehaviour
{
    [Header ("旋轉速度")]
    public float rotionspeed = 250;
    public 旋轉軸 rotationAxis = 旋轉軸.NONE;
    public bool ration;
    public Vector3 axisv;
    public 旋轉軸 rotationAxis_;
    public GameObject gam;
    private void Start()
    {
        Rotation_();

      
    }
    public void Rotation_()
    {
        switch (rotationAxis)
        {
            case 旋轉軸.X:
                axisv = new Vector3 (1,0,0);
                break;
            case 旋轉軸.Y:
                axisv = new Vector3(0, 1, 0);
                break;
            case 旋轉軸.Z:
                axisv = new Vector3(0, 0, 1);
                break;
            case 旋轉軸.NONE:
                axisv = Vector3.zero;
                break;
            default:
                break;
        }
        rotationAxis_ = rotationAxis;
    }
    void Update()
    {
        if (rotationAxis_!=rotationAxis)
        {
            Rotation_();
            Debug.Log("不一樣了");
        }
        if (ration)
        {
            this.transform.RotateAround(this.transform.localPosition, axisv, Time.deltaTime* rotionspeed);
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM