關於安碩

【服務項目】

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

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

2019年11月8日 星期五

[筆記]使用TraceListener 類別作出類似 DebugView 功能

對 PC-Based 的開發工程師來說,IDE 的 Debug Mode 在設備試機時期提供相當的便利性,可以即時觀察變數變化或是線程運作都十分方便。但若上線運作的設備便不太可能把整個原始碼放在設備,這時有一個簡單的方式在程式執行期即時觀察到相關參數的狀態便可大幅縮減工程人員除錯的困難。

以下是運用 TraceListener 類別作出類似 DebugView 功能。

[攝影] 韓國晨靜樹木園


2019年10月26日 星期六

[筆記] C# 的 模擬 C++ Union 方法

Modbus 通訊中針對暫存區作讀寫時必須將數值拆解成 4 個 Byte 後帶入訊息
這時使用 Union 可以簡單的轉換

2019年10月9日 星期三

[筆記] 以 Modbus 對台達 PLC 資料收集

ASCII Mode 的通訊格式


LRC 的的計算方式是由 Address 開始到 Data 的最後一個 Byte 的加總值,移除進位後取 2 的補數就是LRC 的值。


class MyModbus
    {
        public static SerialPort sp = new SerialPort();

        public static bool Init()
        {
            sp.PortName = "COM2";
            sp.BaudRate = 9600;
            sp.DataBits = 7;
            sp.StopBits = StopBits.One;
            sp.Parity = Parity.Even;
            sp.ReadTimeout = 1000;
            sp.Open();
            return true;
        }

        public static bool Close()
        {
            sp.Close();
            return true;
        }

        public static bool Send(string Massage)
        {
            if (sp.IsOpen == false) return false;
            sp.DiscardInBuffer();
            sp.DiscardOutBuffer();
            sp.Write(Massage);
            return true;
        }

        public static bool Receive(out string Massage)
        {
            Massage = string.Empty;
            if (sp.IsOpen == false) return false;
            string str = sp.ReadTo("\r\n");
            //比對開頭碼是否為':'
            if (str[0] != ':') return false;
            //移除符號
            str = str.Trim(':', '\r', '\n');
            //檢查 LRC
            string checksum = str.Substring(str.Length - 2, 2);
            string Data = str.Substring(0, str.Length - 2);
            if (checksum != Lrc(Data)) return false;
            Massage = str;
            return true;
        }


        public static string BulidMassage(byte Address, byte Type, string Start, string Data)
        {
            string Cmd = Address.ToString("X2") + Type.ToString("X2") + Start + Data;
            string Massage = ':' + Cmd + Lrc(Cmd) + "\r\n";
            return Massage;
        }


        public static string Lrc(string Massage)
        {
            byte sum = 0;
            for (int idx = 0; idx < Massage.Length; idx += 2)
            {
                string str = Massage.Substring(idx, 2);
                byte value = Convert.ToByte(str, 16);
                sum = (byte)((sum + value) & 0xff);

            }
            //取補數
            byte checksum = (byte)((~sum + 1) & 0xff);
            string Hex = checksum.ToString("X2");
            return Hex;
        
        }

    }

關放 PLC 內的 Address 可參考 PLC 冊。



class MyPLC
    {
        public MyPLC()
        {
            MyModbus.Init();
        }

        ~MyPLC()
        {
            MyModbus.Close();
        }

        public bool[] ReadAllY()
        {
            bool[] Y = new bool[8];
            //string Massage = MyModbus.BulidMassage(1, 3, "0614", "0008");
            string Massage = MyModbus.BulidMassage(1, 2, "0500", "0008");
            MyModbus.Send(Massage);
            string Data = string.Empty;
            MyModbus.Receive(out Data);

            string Temp = Data.Substring(6, 2);
            byte Value = Convert.ToByte(Temp);

            for (int idx = 0; idx < Y.Length; idx++)
            {
                Y[idx] = (Value & (0x01 << idx)) > 0x00 ? true : false;
            }
            return Y;
        }

        public bool SetY(int Number , bool OnOFF)
        {
            string CoilNumber = "05" + Number.ToString("X2");
            string Massage = MyModbus.BulidMassage(1, 5, CoilNumber, OnOFF ? "FF00" : "0000");
            MyModbus.Send(Massage);
            string Data = string.Empty;
            MyModbus.Receive(out Data);

            string Temp = Data.Substring(4, 4);
            if (Temp != CoilNumber) return false;
            Temp = Data.Substring(8, 4);
            if(OnOFF)
            {
                if (Temp != "FF00") return false;
            }
            else
            {
                if (Temp != "0000") return false;
            }

            return true;
        }


        public bool[] ReadAllX()
        {
            bool[] X = new bool[16];
            string Massage = MyModbus.BulidMassage(1, 2, "0200", "0010");
            MyModbus.Send(Massage);
            string Data = string.Empty;
            MyModbus.Receive(out Data);

            string Temp = Data.Substring(6, 2);
            byte Value = Convert.ToByte(Temp);

            for (int idx = 0; idx < X.Length; idx++)
            {
                X[idx] = (Value & (0x01 << idx)) > 0x00 ? true : false;
            }
            return X;
        }

        public bool[] ReadAllM()
        {
            bool[] X = new bool[16];
            string Massage = MyModbus.BulidMassage(1, 2, "0800", "0008");
            MyModbus.Send(Massage);
            string Data = string.Empty;
            MyModbus.Receive(out Data);

            string Temp = Data.Substring(6, 2);
            byte Value = Convert.ToByte(Temp);

            for (int idx = 0; idx < X.Length; idx++)
            {
                X[idx] = (Value & (0x01 << idx)) > 0x00 ? true : false;
            }
            return X;
        }

        public bool SetM(int Number, bool OnOFF)
        {
            string CoilNumber = "08" + Number.ToString("X2");
            string Massage = MyModbus.BulidMassage(1, 5, CoilNumber, OnOFF ? "FF00" : "0000");
            MyModbus.Send(Massage);
            string Data = string.Empty;
            MyModbus.Receive(out Data);

            string Temp = Data.Substring(4, 4);
            if (Temp != CoilNumber) return false;
            Temp = Data.Substring(8, 4);
            if (OnOFF)
            {
                if (Temp != "FF00") return false;
            }
            else
            {
                if (Temp != "0000") return false;
            }

            return true;
        }

    }