精华内容
下载资源
问答
  • 读取plc内部寄存器的状态 # --*--coding:utf-8--*-- import time from redis import StrictRedis import snap7 from threading import Thread import logging from struct import pack, unpack class MemoryMap...

    通过仿真redis修改&读取plc内部寄存器的状态

    # --*--coding:utf-8--*--
    
    import time
    from redis import StrictRedis
    import snap7
    from threading import Thread
    import logging
    from struct import pack, unpack
    
    
    class MemoryMap(object):
        """ A class from plc memory to redis """
        DB_AREA = 0X84
        M_AREA = 0X83
        Q_AREA = 0X82
        I_AREA = 0X81
    
        def __init__(self,
                     addr="192.168.2.1",
                     tcp_port=102,
                     rack=0,
                     slot=1,
                     host="127.0.0.1",
                     port=6379,
                     password=None,
                     ):
            self.addr = addr
            self.tcp_port = tcp_port
            self.rack = rack
            self.slot = slot
            self.host = host
            self.port = port
            self.password = password
    
            self.logger = logging.getLogger()
            self.logger.setLevel(logging.ERROR)
            self.ch = logging.StreamHandler()
            self.ch.setFormatter(logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s"))
            self.logger.addHandler(self.ch)
    
    
        def conn_plc(self):
    
            plc_client = snap7.client.Client()
            while True:
                try:
                    plc_client.connect(self.addr, self.rack, self.slot)
                    if plc_client.get_connected():
                        break
                except Exception as e:
                    self.logger.error(e)
    
                time.sleep(2)
            return plc_client
    
        def get_data(self, area, db_num, start, size):
            plc_client = self.conn_plc()
            raw_data = None
            try:
                raw_data = plc_client.read_area(area, db_num, start, size)
            except Exception as e:
                self.logger.error(e)
            return raw_data
    
        def handle_data(self):
            raw_data = self.get_data(self.DB_AREA, 1, 0, 1000)
            # bytearray_bytes
            bytes_data = bytes(raw_data)
            data = unpack('B' * 1000, bytes_data)
            return data
    
        def write_data(self, area, db_num, start, bytes_data):
            plc_client = self.conn_plc()
            try:
                plc_client.write_area(area, db_num, start, bytes_data)
            except Exception as e:
                self.logger.error(e)
    
        def create_redis_client(self):
            redis_store = None
            try:
                redis_store = StrictRedis(host=self.host,
                                          port=self.port,
                                          password=self.password,
                                          decode_responses=True)
            except Exception as e:
                self.logger.error(e)
            return redis_store
    
        def upload_data(self):
            """
             function: transfer data from local to cloud_redis
             detect data every second
            """
            redis_store = self.create_redis_client()
            buffer = tuple()
            while True:
                try:
                    data = self.handle_data()
                    if data != buffer:
                        for index, byte in enumerate(data):
                            redis_store.hset("byte_data", f"VB{index}", byte)
                    buffer = data
                except Exception as e:
                    self.logger.error(e)
                time.sleep(1)
    
        def download_data(self, func):
            redis_store = None
            try:
                redis_store = self.create_redis_client()
            except Exception as e:
                self.logger.error(e)
            while True:
                try:
                    previous_dict = redis_store.hgetall('byte_data')  # type:dict
                    previous_key = list(previous_dict.keys())
                    time.sleep(1)
                    next_dict = redis_store.hgetall('byte_data')  # type:dict
                    for key in previous_key:
                        if next_dict.get(key) != previous_dict.get(key):
                            func(key)
                except Exception as e:
                    self.logger.error(e)
    
        def download_callback(self, *args):
            try:
                redis_store = self.create_redis_client()
                value = redis_store.hget('byte_data', args[0])
                byte_value = pack('B', int(value))
                self.write_data(self.DB_AREA, 1, int(str(args[0])[2:]), byte_value)
            except Exception as e:
                self.logger.error(e)
            return None
    
    
    def main():
        mm = MemoryMap(
            addr="192.168.0.2",
            rack=0,
            slot=1,
            host="49.233.15.221",
            password="root"
        )
        thread_list = list()  # type:list
        thread_list.append(Thread(target=mm.upload_data))
        thread_list.append(Thread(target=mm.download_data, args=(mm.download_callback,)))
        for t in thread_list:
            t.start()
        for t in thread_list:
            t.join()
    
    
    if __name__ == '__main__':
        main()
    
    展开全文
  • 寄存器PLC地址寄存器modbus协议地址

    万次阅读 多人点赞 2017-10-24 22:25:28
    寄存器PLC地址指存放于控制器中的地址,这些控制器可以是PLC,也可以使触摸屏,或是文本... 寄存器modbus协议地址指通信时使用的寄存器地址,在实际编程中,由于寄存器PLC地址前缀的区分作用,所以只需说明后4位数...

           寄存器PLC地址指存放于控制器中的地址,这些控制器可以是PLC,也可以使触摸屏,或是文本显示器。PLC地址一般采用10进制描述,共有5位,其中第一位代码寄存器类型。第一位数字和寄存器类型的对应关系如表1所示。PLC地址例如40001、30002等。
           寄存器modbus协议地址指通信时使用的寄存器地址,在实际编程中,由于寄存器PLC地址前缀的区分作用,所以只需说明后4位数,而且需转换为4位十六进制地址。例如PLC地址40001对应寻址地址0x0000,40002对应寻址地址0x0001,寄存器寻址地址一般使用16进制描述。再如,PLC寄存器地址40003对应协议地址0002,PLC寄存器地址30003对应协议地址0002。在实际编程中,由于前缀的区分作用,所以只需说明后4位数,而且需转换为4位十六进制地址。
           支持 Modbus 协议的设备或软件,使用时用户直接设置或看到的应 当是 Modbus 数据地址。Modbus 地址所访问的数据,是通过各种 “功能”读写而来。 功能码是 Modbus 地址的底层。 如果 Modbus 通 信的一方提供的所谓 Modbus 协议只有功能码,则需要注意了解此 功能号与 Modbus 地址间的对应关系。

           使用 modbus 地址时应注意下述问题:

     1)40001~4xxxx 是美国 modicon 公司和 ge 公司 plc 使用的 modbus 地址,它是基于1的地址,即同类元件的首地址为1。西门子 plc 的 modbus 地址是基于0的地址。 

    2)美国的 modbus 地址左起第2位用来表示元件的类型,例如 i0.0的 modbus 地址为010001。 因为数据类型已经包含在功

    展开全文
  • 显控plc寄存器说明

    2020-10-12 14:26:42
    寄存器地址说明,范围、掉电保持范围,最大长度及存储单位、读写权限。 某些特殊寄存器有固定功能。包含:位寄存器M、数据寄存器D等等。
  • 永宏PLC 寄存器之Modbus地址映射 遵循modbus标准,格式依据www.modbus.org 映射分5码、6码。 使用FBs-CM5EH组modbus服务。 1、代码转换规则 2、转换范围(5码) 3、转换范围(6码)

    永宏PLC 寄存器之Modbus地址映射

    遵循modbus标准,格式依据www.modbus.org
    映射分5码、6码。
    使用FBs-CM5EH组modbus服务。

    1、代码转换规则
    在这里插入图片描述

    2、转换范围(5码)
    在这里插入图片描述
    3、转换范围(6码)
    在这里插入图片描述

    展开全文
  • 施耐德PLC寄存器与组态王的寄存器的对应关系,解决两者的连接问题,比如%MF、%MW 、%M 寄存器等
  • C# ModBus Tcp 直接读写PLC寄存器

    千次阅读 2020-05-25 14:45:06
    C# ModBus Tcp读写数据 直接...1.这边使用裸Tcp/ip协议 通过socket发送modbus的通讯报文地址数据等操作plc寄存器(没有使用别人写好的类库)。界面如下: 2.TCP部分程序如下: 内联代码片。 using System; using Syst

    C# ModBus Tcp 直接读写PLC寄存器

    MODBUS通用数据帧:
    在这里插入图片描述在这里插入图片描述测试用modbus服务器下载地址:
    https://download.csdn.net/download/weixin_42288222/12457317
    测试修改寄存器的值为1
    代码下载地址:

    具体modbus协议见pdf文档这里就不说了(下载包里有)
    在这里插入图片描述
    https://download.csdn.net/download/weixin_42288222/12457342

    1.这边使用裸Tcp/ip协议 通过socket发送modbus的通讯报文地址数据等,操作plc寄存器(没有使用别人写好的类库)。

    界面如下:
    界面
    2.TCP部分程序如下: 内联代码片

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace ModbusTcp
    {
        class TCP
        {
            public delegate void ChangeFormList(bool change);
            public event ChangeFormList ChangeList;
            public delegate void TcpStutas(bool change);
            public event TcpStutas ReturnFromPLC;
            readonly object obj = new object();
            public string STR;//接收到的消息
            public string SendMsg;
            /// <summary>
            /// 连接状态:true 连接中 false 连接中断
            /// </summary>
            public bool isConnected;
            Socket socketSend;
            public bool Connect(string ip, int port)
            {
                try
                {
                    socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    IPAddress IP = IPAddress.Parse(ip);
                    IPEndPoint point = new IPEndPoint(IP, port); ;
                    socketSend.Connect(point);
                    isConnected = true;
                    return true;
                }
                catch (Exception)
                {
                    MessageBox.Show("请填写正确的IP地址和端口号!");
                    return false;
                }
            }
            /// <summary>
            /// 接收服务端返回的消息
            /// </summary>
            void Received()
            {
                try
                {
                    //1M的缓存区
                    byte[] data = new byte[1024];
                    //实际接收到的有效字节数
                    int len = socketSend.Receive(data);// 将接受到的数据存入到输入buffer中
                    if (len == 0)
                    {
                        isConnected = false;
                    }
                    int length = data[5];//读取数据长度  
                    Byte[] datashow = new byte[length + 6];//定义所要显示的接收的数据的长度  
                    for (int i = 0; i <= length + 5; i++)//将要显示的数据存放到数组datashow中  
                        datashow[i] = data[i];
                    string stringdata = BitConverter.ToString(datashow);//把数组转换成16进制字符串  
                    if (data[7] == 0x01) { STR = stringdata; };
                    if (data[7] == 0x02) { STR = stringdata; };
                    if (data[7] == 0x03) { STR = stringdata; };//功能码为3
                    if (data[7] == 0x05) { STR = stringdata; };
                    if (data[7] == 0x06) { STR = stringdata; };//功能码为6
                    if (data[7] == 0x0F) { STR = stringdata; };
                    if (data[7] == 0x10) { STR = stringdata; };
                    ChangeList(true);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("接收数据出现异常!" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
    
            }
            /// <summary>
            /// 向服务器发送消息
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void Send(byte[] msg)
            {
                lock (obj)
                {
                    try
                    {
                        socketSend.Send(msg);
                        for (int i = 0; i < msg.Length; i++)
                        {
                            SendMsg += msg[i];
                        }
                        ReturnFromPLC(true);
                        Thread.Sleep(10);
                        Received();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(" 发送数据出现异常!" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
    
            }
            /// <summary>
            /// 16转10进制
            /// </summary>
            /// <param name="msg"></param>
            /// <returns></returns>
            public int GetDex(string msg)
            {
                int res = Convert.ToInt32(msg, 16);
                return res;
            }
        }
    }
    
    

    3.主界面部分: 内联代码片

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace ModbusTcp
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            /*具体详见modbus协议中文版.pdf
             功能码说明(括号内为对应的16进制):
             01(01):byte访问 读线圈
             02(02):byte访问 读输入离散量
             05(05):byte访问 写单个线圈
             15(0F):byte访问 写多个线圈
             03(03):16位byte访问 读多个寄存器
             04(04):16位byte访问 读输入寄存器
             06(06):16位byte访问 写单个寄存器
             16(10):16位byte访问 写多个寄存器
             23(17):16位byte访问 读/写多个寄存器
             22(16):16位byte访问 屏蔽写寄存器
             20(14):文件记录访问 读文件记录
             21(15):文件记录访问 写文件记录
             43(2B):封装接口     读设备识别码
             */
            private void button1_Click(object sender, EventArgs e)
            {
                //连接Tcp服务器
                tcp.Connect(textBox1.Text, 502);
            }
            TCP tcp = new TCP();
            private void Form1_Load(object sender, EventArgs e)
            {
                tcp.ChangeList += new TCP.ChangeFormList(f_ChangeList);//tcp通讯显示发送
                tcp.ReturnFromPLC += new TCP.TcpStutas(f_TcpAtutas);//tcp通讯显示返回
            }
    
            private void f_TcpAtutas(bool change)
            {
                Invoke(new Action(() =>{
                    richTextBox1.Text += tcp.STR + "***" + DateTime.Now.ToString("yyyy/mm/dd HH:mm:ss") + "\r\n";
                } ));
            }
    
            private void f_ChangeList(bool change)
            {
                Invoke(new Action(() => {
                    richTextBox2.Text += tcp.STR + "***" + DateTime.Now.ToString("yyyy/mm/dd HH:mm:ss") + "\r\n";
                }));
            }
    
            /// <summary>
            /// 数据格式:0-6位:报文头;7位:功能码;8-9位:起始地址;10-11位:寄存器位数(读)/写入数据(写)
            /// </summary>
            byte[] data = new byte[] { 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x00, 0x00, 0x01 };
            private void button2_Click(object sender, EventArgs e)
            {
                try
                {
                    data[7] = GetHex(textBox2.Text);
                    data[11] = GetHex(textBox3.Text);
                    data[9] = GetHex(textBox4.Text);
                    tcp.Send(data);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                
            }
            /// <summary>
            /// 10转16
            /// </summary>
            /// <param name="msg"></param>
            /// <returns></returns>
            private byte GetHex(string msg)
            {
                byte hex = Convert.ToByte(msg);
                return hex;
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                if (tcp.isConnected)
                {
                    button1.Enabled = false;
                    textBox1.Enabled = false;
                }
                else
                {
                    button1.Enabled = true;
                    textBox1.Enabled = true;
                }
            }
        }
    }
    
    
    展开全文
  • C#编成Modbus TCP连接PLC寄存器读取、写入,完整分享源代码,有需要的人可以下载
  • PC读写西门子PLC寄存器的值

    万次阅读 多人点赞 2018-08-20 16:27:08
    西门子PLC调试助手工具适用于西门子S7-300、S7-400、S7-1200、S7-1500等具备Ethernet TCP/IP通讯方式的PLC的(I、M、Q、DB区)寄存器值的读写,采用的是102端口网络通讯方式,方便西门子... (2)寄存器地址参数设置...
  • labview使用modbus读取plc采集的编码器数据进行定位时,测得while循环的扫描周期为10ms,当电机速度为1mm/s时,![图片说明](https://img-ask.csdn.net/upload/202010/09/1602233078_626309.png)读取的值每个相差2,...
  • ython snap7读写西门子S系列PLC寄存器的值(PLC的I、Q、M区)
  • C#编成Modbus TCP连接PLC寄存器读取、写入,完整分享源代码,有需要的人可以下载亲测好用,挺不错的资源,大家快来下载吧!挺有用的!需要的话可以来下载哦!
  • 使用西门子S7-200CN PLC,V4.0 STEP 7 MicroWIN SP9上导入Modbus Slave Port0(v1.0),下载slave.mwp到PLC并运行,串口连接PLC与数据采集网关(PC、树莓派或开发板),运行数据采集网关上的server.py,运行另一台PC上...
  • C#通过 MX Component的dll文件读写PLC寄存器的D区和M区的值 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using ...
  • https://wenku.baidu.com/view/ad9312dedd88d0d233d46ac7.html
  • 首先将需要读取的PLC内部元件的地址找到,主要内部元件地址如下: D: PLC-Address*2+1000H; T: PLC-Address+00C0H; C: PLC-Address*2+01C0H; S: PLC-Address*3; M: PLC-Address*2+0100H; Y: PLC-Ad...
  • 西门子PLC基于MODBUS RTU通信协议的寄存器地址对应关系及错误代码
  • 西门子 SiemensTCP/IP调试助手工具是利用python 开发的,适用于西门子S7-300、S7-400、S7-1200、S7-1500等具备Ethernet TCP/IP通讯方式的PLC的(I、M、Q、DB区)寄存器值的读写,采用的是102端口网络通讯方式,方便...
  • 1. ScanRet = PLC.CmdWrite(cmbWriteMry.SelectedIndex + 1, cmbWriteType.SelectedIndex + 1, Val(txtWriteAdd.Text), Val(txtWriteCnt.Text), WD) 1. txtReWrite.Text = ScanRet.ToString 1. End Sub 1.
  • 西门子PLC基于MODBUS RTU通信协议时的寄存器地址对应关系及错误代码 西门子PLC在使用MODBUS RTU通信协议时,寄存器的地址是如何对应的?为什么第一个寄存器地址是40001? 功能码对照表如下:(H为16进制) 由上面...
  • 此函数是写数值进去寄存器,我连续不断的往里面写值时,内存会慢慢增加,最后程序奔溃 Stack Overflow emit writeCoils(M5031, 1); Sleep(10); emit writeHoldingRegisters(D5010, strDataResult.toInt()); ...
  • 我有一个松下plc,在这个plc中有近6000个寄存器有数据,我应该怎样才能快速的将这些读取出来。我目前是用R232接口,用C#语言,但一次只能读取20多个寄存器的值,循环读取会很慢,有什么快速读取方法?
  • 移位寄存器指令SHRB是将DATA数值移入移位寄存器。S_BIT指定移位寄存器的位。N指定移位寄存器的长度和移位方向(移位加 = N,移位减 = -N)。移位寄存器的长度是64位的,可以正也可以负。我们要注意的是SHRB指令移出...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,733
精华内容 1,493
关键字:

plc寄存器地址