關於安碩

【服務項目】

 自動化設備控制系統及機構設計
 PC Based 控制系統設計
 PLC 及 HMI 程式設計
 多軸運動控制
 機器視覺檢測系統設計
 資料收集及遠端監控
 設備電控電路設計及控制盤體配線
 機械手臂整合應用
 舊有設備整理及改善
 客製化程式開發
 IPC / 軸控模組 / IO 模組 代理

系統整合外包服務 E-mail: ling.ryan@gmail.com 歡迎來信連絡

2020年9月30日 星期三

[筆記]NP20C 數位壓力傳感器通訊




namespace PressureMonitor
{
    class NP70C
    {
        Modbus mModbus;
        public NP70C(SerialPort _SerialPort)
        {
            mModbus = new Modbus(_SerialPort);
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct Union
        {
            [FieldOffset(0)]
            public byte byte1;
            [FieldOffset(1)]
            public byte byte2;
            [FieldOffset(0)]
            public Int16 Value;
        }

        public int Pv = 0x00;
        public string ErrorMag = string.Empty;
        public void ReadPv()
        {
            byte Address = 0x01;
            UInt16 RegisterNumber = 0x02;
            UInt16 RegisterCount = 0x01;
            byte[] Data = null;
            Modbus.Error err;
            if ((err = mModbus.ReadHoldingRegister(Address, RegisterNumber, RegisterCount, ref Data)) != Modbus.Error.Success)
            {
                ErrorMag = err.ToString();
                return;
            }

            Union Temp = new Union();

            Temp.byte1 = Data[0];
            Temp.byte2 = Data[1];

            Pv = Temp.Value;
        }
    }
}



class Modbus
    {
        private SerialPort mSerialPort;

        public enum Error
        {
            Success,
            SerialPortNotOpenYet,
            SerialPortWriteFailure,
            SerialPortReadFailure,
        }
        public Modbus(SerialPort _SerialPort)
        {
            mSerialPort = _SerialPort;
        }


        public Error ReadHoldingRegister(byte Address, UInt16 RegisterNumber, UInt16 RegisterCount, ref byte[] Data)
        {
            byte[] Cmd = new byte[8];
            Cmd[0] = Address;
            Cmd[1] = 0x03;
            Cmd[2] = (byte)((RegisterNumber & 0xF0) >> 8);
            Cmd[3] = (byte)((RegisterNumber & 0x0F));
            Cmd[4] = (byte)((RegisterCount & 0xF0) >> 8);
            Cmd[5] = (byte)((RegisterCount & 0x0F));
            byte[] Crc = CalculateCRC(Cmd, 6);
            Cmd[6] = Crc[0];
            Cmd[7] = Crc[1];

            Error Err = Error.Success;

            if ((Err = SendCmd(Cmd)) != Error.Success) return Err;
            //Address(1) + FunctionCode(1) + RegisterNumber(2) + RegisterCount *2 + CRC(2)
            int MsgLen = 1 + 1 + 2 + 2 * RegisterCount + 2;
            byte[] Response = new byte[MsgLen];
            if ((Err = ReceiveMsg(MsgLen, ref Response)) != Error.Success) return Err;

            int DataLen = 2 * RegisterCount;
            Data = new byte[DataLen];
            for (int idx = 0; idx < DataLen; idx++)
            {
                Data[idx] = Response[5 + idx];
            }
            return Error.Success;

        }

        public Error SendCmd(byte[] Cmd)
        {
            if (mSerialPort.IsOpen == false) return Error.SerialPortNotOpenYet;
            try
            {
                mSerialPort.Write(Cmd, 0, Cmd.Length);
            }
            catch
            {
                return Error.SerialPortWriteFailure;
            }
            return Error.Success;
        }

        public Error ReceiveMsg(int MsgLen, ref byte[] Response)
        {
            if (mSerialPort.IsOpen == false) return Error.SerialPortNotOpenYet;

            byte[] REV = new byte[MsgLen];

            try
            {
                mSerialPort.Read(REV, 0, MsgLen);
                Response = REV;
            }
            catch
            {
                return Error.SerialPortReadFailure;
            }


            return Error.Success;
        }

        byte[] CalculateCRC(byte[] Mag, int len)
        {
            UInt16 Temp = 0xFFFF;

            for (int pos = 0; pos < len; pos++)
            {
                Temp ^= (UInt16)Mag[pos];          // 取出第一個byte與crc XOR

                for (int i = 8; i != 0; i--)
                {    // 巡檢每個bit  
                    if ((Temp & 0x0001) != 0)
                    {      // 如果 LSB = 1   
                        Temp >>= 1;                    // 右移1bit 並且 XOR 0xA001  
                        Temp ^= 0xA001;
                    }
                    else                            // 如果 LSB != 1  
                        Temp >>= 1;                    // 右移1bit
                }
            }
            byte[] Crc = new byte[2];
            Crc[0] = (byte)(Temp & 0xFF);
            Crc[1] = (byte)(Temp >> 8 & 0xFF);
            return Crc;
        }
    }




沒有留言:

張貼留言