[netMarketing类库] simulation类:三菱FX2N PLC仿真

命名空间:netMarketing.automation.plc.softPlc

功能:三菱FX2N PLC仿真


功能详细说明:

目前暂时只支持三菱PLC fx2n的下列指令:

LD,LDI,LDP,LDF,AND,ANB,ANI,ANDP,ANDF,OR,ORI,ORB,ORP,ORF,OUT,MPS,MPP,MRD,INC,DEC,SET,RST,MOV,XCH,END

这个类是勇哥很早以前开发的,本意是想做一款plc学习软件,后来由于3D场景仿真困难比较大,这个项目就搁浅了。

后来发现这个类还有个意义是用来以PLC梯形图的方式调用封装好的C#的资源,即结合了PLC和C#各自的优点来开发上位机软件。

如果要实现这一点,需要开发梯形图编辑器,这个也是比较困难的事。勇哥在这方面暂时没有精力继续,期待有感兴趣的朋友可以深入研究下去,如果需要的话,勇哥可以提供源代码。


下面的程序是这个类的一个应用。

这个程序的梯型图编辑只是实现了基本的画元件,但是没能实现梯型图超过一屏后的滚动条卷动的处理过程。

另外,梯型图转指令或者指令转梯型图的功能也没能够完成。

image.png

下面的代码只是演示程序的主界面的代码,如果你有兴趣的话,完整的演示程序可以找勇哥索要。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;

namespace simulation
{

    public partial class MainForm : Form
    {
        public Point DownPoint;
        public LADDER ladder;
        public bool ladderUpdateFlag = false;

        private myPanel panMain;
        private List<List<LADDER>> ladderBinaryTree;
        private drawTools gt;
        private simulation sim;
        private string codePath = AppDomain.CurrentDomain.BaseDirectory + "code";
        private string partImagePath = AppDomain.CurrentDomain.BaseDirectory + "partImg";
        public MainForm()
        {
            panMain = new myPanel(this);
            DownPoint = new Point(panMain.startX,panMain.startY);
            ladder.ladderParam = "";
            ladder.ladderType = partTypeEnum.nopPart;
            InitializeComponent();
            this.panel1.Controls.Add(this.panMain);
            this.panMain.BringToFront();
            this.panMain.Dock = DockStyle.Fill;
            this.panMain.BorderStyle = BorderStyle.Fixed3D;
            this.panMain.MouseDown += new MouseEventHandler(panMain_MouseDown);
            this.panMain.MouseDoubleClick += new MouseEventHandler(panMain_MouseDoubleClick);

            sim = new simulation();
            ladderBinaryTree = new List<List<LADDER>>();
            timer1.Start();
        }

        void panMain_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            inputPart part = null;
            var partNode = panMain.getCurPosLadderNode();
            part = new inputPart(partNode.ladderType);
            part.PartParam = partNode.ladderParam;
            part.ShowDialog();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (!Directory.Exists(codePath))
                Directory.CreateDirectory(codePath);
            if (!Directory.Exists(partImagePath))
                Directory.CreateDirectory(partImagePath);
            updateProgramList();

            Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
            gt = new drawTools(this.pbImg.CreateGraphics(), new Pen(Color.Black, 1), bmp);         
        }

        private void updateProgramList()
        {
            this.lbxProList.Items.Clear();
            var files = Directory.GetFiles(codePath, "*.*");
            for (int i = 0; i < files.Length; i++)
            {
                string[] ary1 = files[i].Split('\\');
                files[i] = ary1[ary1.Length - 1];
            }
            this.lbxProList.Items.AddRange(files);
        }



        private void timer1_Tick(object sender, EventArgs e)
        {

            IList<string> dMsg = new List<string>();
            IList<string> tMsg = new List<string>();
            IList<string> cMsg = new List<string>();
            for (ushort i = 0; i < 10; i++)
            {

                dMsg.Add(string.Format("D{0}:{1}",i,sim.GetD(i).Value));
                var tuple1=sim.GetT(i);
                tMsg.Add(string.Format("T{0}:{1},{2}", i, tuple1.Item1, tuple1.Item2));
                var tuple2 = sim.GetC(i);
                cMsg.Add(string.Format("C{0}:{1},{2}", i, tuple2.Item1, tuple2.Item2));

                ushort index = i;
                if (i == 8) index = 10;
                if (i == 9) index = 11;
                if (sim.GetX(index).OnOff)
                {
                    if (i == 0) btnX0.BackColor = Color.Yellow;
                    if (i == 1) btnX1.BackColor = Color.Yellow;
                    if (i == 2) btnX2.BackColor = Color.Yellow;
                    if (i == 3) btnX3.BackColor = Color.Yellow;
                    if (i == 4) btnX4.BackColor = Color.Yellow;

                    if (i == 5) btnX5.BackColor = Color.Yellow;
                    if (i == 6) btnX6.BackColor = Color.Yellow;
                    if (i == 7) btnX7.BackColor = Color.Yellow;
                    if (i == 8) btnX10.BackColor = Color.Yellow;
                    if (i == 9) btnX11.BackColor = Color.Yellow;
                }
                else
                {
                    if (i == 0) btnX0.BackColor = SystemColors.ControlLight;
                    if (i == 1) btnX1.BackColor = SystemColors.ControlLight;
                    if (i == 2) btnX2.BackColor = SystemColors.ControlLight;
                    if (i == 3) btnX3.BackColor = SystemColors.ControlLight;
                    if (i == 4) btnX4.BackColor = SystemColors.ControlLight;

                    if (i == 5) btnX5.BackColor = SystemColors.ControlLight;
                    if (i == 6) btnX6.BackColor = SystemColors.ControlLight;
                    if (i == 7) btnX7.BackColor = SystemColors.ControlLight;
                    if (i == 8) btnX10.BackColor = SystemColors.ControlLight;
                    if (i == 9) btnX11.BackColor = SystemColors.ControlLight;
                }

                if (sim.GetY(index).OnOff)
                {
                    if (i == 0) btnY0.BackColor = Color.Yellow;
                    if (i == 1) btnY1.BackColor = Color.Yellow;
                    if (i == 2) btnY2.BackColor = Color.Yellow;
                    if (i == 3) btnY3.BackColor = Color.Yellow;
                    if (i == 4) btnY4.BackColor = Color.Yellow;
                    if (i == 5) btnY5.BackColor = Color.Yellow;
                    if (i == 6) btnY6.BackColor = Color.Yellow;
                    if (i == 7) btnY7.BackColor = Color.Yellow;
                    if (i == 10) btnY10.BackColor = Color.Yellow;
                    if (i == 11) btnY11.BackColor = Color.Yellow;
                }
                else
                {
                    if (i == 0) btnY0.BackColor = SystemColors.ControlLight;
                    if (i == 1) btnY1.BackColor = SystemColors.ControlLight;
                    if (i == 2) btnY2.BackColor = SystemColors.ControlLight;
                    if (i == 3) btnY3.BackColor = SystemColors.ControlLight;
                    if (i == 4) btnY4.BackColor = SystemColors.ControlLight;
                    if (i == 5) btnY5.BackColor = SystemColors.ControlLight;
                    if (i == 6) btnY6.BackColor = SystemColors.ControlLight;
                    if (i == 7) btnY7.BackColor = SystemColors.ControlLight;
                    if (i == 10) btnY10.BackColor = SystemColors.ControlLight;
                    if (i == 11) btnY11.BackColor = SystemColors.ControlLight;
                }

                if (sim.GetM(i).OnOff)
                {
                    if (i == 0) btnM0.BackColor = Color.Yellow;
                    if (i == 1) btnM1.BackColor = Color.Yellow;
                    if (i == 2) btnM2.BackColor = Color.Yellow;
                    if (i == 3) btnM3.BackColor = Color.Yellow;
                    if (i == 4) btnM4.BackColor = Color.Yellow;
                }
                else
                {
                    if (i == 0) btnM0.BackColor = SystemColors.ControlLight;
                    if (i == 1) btnM1.BackColor = SystemColors.ControlLight;
                    if (i == 2) btnM2.BackColor = SystemColors.ControlLight;
                    if (i == 3) btnM3.BackColor = SystemColors.ControlLight;
                    if (i == 4) btnM4.BackColor = SystemColors.ControlLight;
                }
            }
            object[] m = sim.RunningCompilerLogicList.ToList().ConvertAll(s => (object)s).ToArray();
            listBox1.BeginUpdate();
            listBox1.Items.Clear();
            listBox1.Items.AddRange(m);
            listBox1.EndUpdate();
            toolMsg1.Text ="扫描周期总数:"+sim.CycleCount+ ", 一个扫描周期耗时(毫秒): " + sim.CycleSpeed.ToString();
            toolMsg2.Text = panMain.LadderRows + "," + panMain.LadderCols;

            this.lbxD.BeginUpdate();
            this.lbxD.Items.Clear();
            this.lbxD.Items.AddRange(dMsg.ToArray());
            this.lbxD.EndUpdate();

            this.lbxT.BeginUpdate();
            this.lbxT.Items.Clear();
            this.lbxT.Items.AddRange(tMsg.ToArray());
            this.lbxT.EndUpdate();

            this.lbxC.BeginUpdate();
            this.lbxC.Items.Clear();
            this.lbxC.Items.AddRange(cMsg.ToArray());
            this.lbxC.EndUpdate();

         
        }

        private void btnX0_Click(object sender, EventArgs e)
        {
            string name = ((Button)sender).Name;
            switch (name)
            {
                case "btnX5":
                    sim.SetX(5, !sim.GetX(5).OnOff);
                    break;
                case "btnX6":
                    sim.SetX(6, !sim.GetX(6).OnOff);
                    break;
                case "btnX7":
                    sim.SetX(7, !sim.GetX(7).OnOff);
                    break;
                case "btnX10":
                    sim.SetX(10, !sim.GetX(10).OnOff);
                    break;
                case "btnX11":
                    sim.SetX(11, !sim.GetX(11).OnOff);
                    break;


                case "btnM0":
                    sim.SetM(0, !sim.GetM(0).OnOff);
                    break;
                case "btnM1":
                    sim.SetM(1, !sim.GetM(1).OnOff);
                    break;
                case "btnM2":
                    sim.SetM(2, !sim.GetM(2).OnOff);
                    break;
                case "btnM3":
                    sim.SetM(3, !sim.GetM(3).OnOff);
                    break;
                case "btnM4":
                    sim.SetM(4, !sim.GetM(4).OnOff);
                    break;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            sim.EndSimulation();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (!sim.SimulationStatus && this.tbFileName.Text.Length>2 && this.richTextBox1.Text.Length>5)
            {
                bool fileExist = File.Exists(codePath + "\\" + this.tbFileName.Text.Trim());
                string msg = "是否要保存" + this.tbFileName.Text.Trim() + "?";
                if (fileExist) msg = "程序 [" + this.tbFileName.Text.Trim() + "] 已经存在,是否覆盖 ?";
                var m1 = MessageBox.Show(msg, "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                if (m1 == DialogResult.OK)
                {
                    try
                    {
                        File.WriteAllText(codePath + "\\" + this.tbFileName.Text.Trim(), richTextBox1.Text);
                        updateProgramList();
                    }
                    catch (Exception e1)
                    {
                        MessageBox.Show(e1.Message);
                    }
                }
            }
                
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            if (!sim.SimulationStatus && lbxProList.SelectedIndex>=0)
            {
                var m1 = MessageBox.Show("是否要载入代码 " + lbxProList.SelectedItem.ToString() + " ?",
                    "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                if (m1 == DialogResult.OK)
                {
                    try
                    {
                        richTextBox1.Text = File.ReadAllText(codePath + "\\" + lbxProList.SelectedItem.ToString().Trim());
                    }
                    catch (Exception e1)
                    {
                        MessageBox.Show(e1.Message);
                    }
                }
            }
        }

        private void btnDelCodeFile_Click(object sender, EventArgs e)
        {
            if (!sim.SimulationStatus && lbxProList.SelectedIndex>=0)
            {
                var m1 = MessageBox.Show("是否要删除代码 " + lbxProList.SelectedItem.ToString() + " ?",
                   "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                if (m1 == DialogResult.OK)
                {
                    try
                    {
                        File.Delete(codePath + "\\" + lbxProList.SelectedItem.ToString().Trim());
                        this.tbFileName.Text = "";
                        this.richTextBox1.Text = "";
                        updateProgramList();
                    }
                    catch (Exception e1)
                    {
                        MessageBox.Show(e1.Message);
                    }
                }
            }
        }

        private void btnX0_MouseDown(object sender, MouseEventArgs e)
        {
             string name = ((Button)sender).Name;
             switch (name)
             {
                 case "btnX0":
                     sim.SetX(0, !sim.GetX(0).OnOff);
                     break;
                 case "btnX1":
                     sim.SetX(1, !sim.GetX(1).OnOff);
                     break;
                 case "btnX2":
                     sim.SetX(2, !sim.GetX(2).OnOff);
                     break;
                 case "btnX3":
                     sim.SetX(3, !sim.GetX(3).OnOff);
                     break;
                 case "btnX4":
                     sim.SetX(4, !sim.GetX(4).OnOff);
                     break;
             }
        }

        private void btnX0_MouseUp(object sender, MouseEventArgs e)
        {
            string name = ((Button)sender).Name;
            switch (name)
            {
                case "btnX0":
                    sim.SetX(0, !sim.GetX(0).OnOff);
                    break;
                case "btnX1":
                    sim.SetX(1, !sim.GetX(1).OnOff);
                    break;
                case "btnX2":
                    sim.SetX(2, !sim.GetX(2).OnOff);
                    break;
                case "btnX3":
                    sim.SetX(3, !sim.GetX(3).OnOff);
                    break;
                case "btnX4":
                    sim.SetX(4, !sim.GetX(4).OnOff);
                    break;
            }
        }

        private void lbxProList_SelectedIndexChanged(object sender, EventArgs e)
        {
            var listbox = (ListBox)sender;
            if(listbox.SelectedItem!=null)
                tbFileName.Text = listbox.SelectedItem.ToString();
        }

        private void lbxProList_DoubleClick(object sender, EventArgs e)
        {
            btnLoad_Click(null, null);
        }

      


        private void tslStartSimulation_Click(object sender, EventArgs e)
        {
            if (this.richTextBox1.Lines.Length > 1)
            {
                try
                {
                    sim.setCode(this.richTextBox1.Lines);
                    sim.StartSimulation();
                    this.tslStartSimulation.Enabled = false;
                    this.tslStopSimulation.Enabled = true;
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void tslStopSimulation_Click(object sender, EventArgs e)
        {
            if (!this.tslStartSimulation.Enabled)
            {
                sim.EndSimulation();
                this.tslStartSimulation.Enabled = true;
                this.tslStopSimulation.Enabled = false;
            }
        }

        private void toolStripButton19_Click(object sender, EventArgs e)
        {
            //int startX = 30;
            //Graphics g = this.pbImg.CreateGraphics();
            //Pen p = new Pen(Color.Black, 1);
            //g.DrawLine(p, new Point(startX, 0), new Point(startX, 5000));
            //g.DrawLine(p, new Point(startX + 520, 0), new Point(startX + 520, 5000));
            Scada formScada = new Scada();
            formScada.ShowDialog();
        }

        void panMain_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                DownPoint = new Point(e.X, e.Y);//保存鼠标按下坐标
                uint rows = 1;
                for (rows = 1; rows <= 16; rows++)
                {
                    if (e.Y > (rows - 1) *panMain.cursorHeight && e.Y < rows *panMain.cursorHeight)
                    {
                        break;
                    }
                }

                ushort cols = 1;
                for (cols = 1; cols <= 16; cols++)
                {
                    if (e.X > (cols - 1) *panMain.cursorWidth && e.X < cols *panMain.cursorWidth &&
                        rows<=panMain.getHaveEditNums())
                    {
                        panMain.LadderCols = cols;
                        panMain.LadderRows = rows;
                        break;
                    }
                }
                panMain.Invalidate();
            }
        }


        public void tsbLadderParamReset()
        {
            ladder.ladderParam = "";
            ladder.ladderType = partTypeEnum.nopPart;
        }

        private void tsbNopen_Click(object sender, EventArgs e)
        {
            inputPart part=null;
            switch (((ToolStripButton)sender).Name)
            {
                case "tsbNopen":
                    part= new inputPart(partTypeEnum.nopenPart);
                    break;
                case "tsbOrOpen":
                    part = new inputPart(partTypeEnum.orOpenPart);
                    break;
                case "tsbClose":
                    part = new inputPart(partTypeEnum.closePart);
                    break;
                case "tsbOrClose":
                    part = new inputPart(partTypeEnum.orClosePart);
                    break;
                case "tsbCoil":
                    part = new inputPart(partTypeEnum.coilPart);
                    break;
                case "tsbApplication":
                    part = new inputPart(partTypeEnum.applicationPart);
                    break;
                case "tsbHline":
                    part = new inputPart(partTypeEnum.hlinePart);
                    break;
                case "tsbVline":
                    drawVline();
                    return;
                case "tsbDelHline":
                    delHline();
                    return;
                case "tsbDelVline":
                    delVline();
                    return;
                case "tsbP":
                    part = new inputPart(partTypeEnum.pPart);
                    break;
                case "tsbF":
                    part = new inputPart(partTypeEnum.fPart);
                    break;
                case "tsbOrP":
                    part = new inputPart(partTypeEnum.orpPart);
                    break;
                case "tsbOrF":
                    part = new inputPart(partTypeEnum.orfPart);
                    break;
                case "tsbNot":
                    part = new inputPart(partTypeEnum.notPart);
                    break;
                case "tsbAndLine":
                    break;
                case "tsbDelAndLine":
                    break;
                case "tsbNewLadder":
                    newLadder();
                    break;
                case "tsbConvert":
                    ladderConverToCode();
                    return;
                case "tsbDisCommon":
                    disOnOffCommon();
                    break;
                case "tsbSaveLadder":
                    panMain.saveLadder();
                    return;
                case "tsbOpenLadder":
                    panMain.readLadder();
                    panMain.Invalidate();
                    return;
                default:
                    part = new inputPart(partTypeEnum.anyPart);
                    break;
            }
            var res = part.ShowDialog();
            if (res == DialogResult.OK)
            {
                ladder.isHaveVline = panMain.getCurPosLadderNode().isHaveVline;
                ladder.ladderParam = part.PartParam;
                ladder.ladderType = part.PartType;
                panMain.setProgramData(ladder);
                panMain.Invalidate();
            }
        }

        private void drawVline()
        {
            panMain.setCurPosLadderNodeVlineParam(true);
            panMain.Invalidate();
        }

        private void delVline()
        {
            panMain.setCurPosLadderNodeVlineParam(false);
            panMain.Invalidate();
        }

        private void delHline()
        {
            panMain.setProgramData(new LADDER()
            {
                ladderType = partTypeEnum.nopPart,
                isHaveVline = panMain.getCurPosLadderNode().isHaveVline,
                ladderParam = ""
            });
            panMain.Invalidate();
        }

        private void disOnOffCommon()
        {

        }

        private void newLadder()
        {

        }

        private void ladderConverToCode()
        {
            panMain.compileLadder();
            richTextBox1.Lines= myPanel.complierCoder.ToArray(); 
        }

        private void drawPart(LADDER part)
        {
            ladder.isHaveVline = part.isHaveVline;
            ladder.ladderParam = part.ladderParam;
            ladder.ladderType = part.ladderType;
            panMain.setProgramData(ladder);
            panMain.Invalidate();
        }
    }




}

关于这个仿真器,勇哥还写了一篇论文,有兴趣的朋友可以参考:

基于visual c#.net的虚拟PLC仿真软件开发


--------------------- 

作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

返回类库功能说明目录


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864