三菱PLC 通訊 python代碼

前幾天,需要使用到激光傳感器,需要PLC來控制。就學習了一下PC與PLC通訊。

學的不深,可能有很多問題,歡迎指正。

PLC那一端是電氣的同事幫忙弄的,使用的是MC協議。

一開始,我是用的是二進制方式(這個方式我用不了,應該是PLC那一端設置了ASCII方式吧...不太清楚):

import socket
import re

PORT = 7001

def read_register(host, start_digit, digit_num=1, port=PORT, dic=True):
    '''
    Example:
        read D400 single word: read_register('192.168.100.2', 400)
    '''
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((host, port))

    str1= '500000ffff03000c00100001040000'\
            + reverse_per_two_char('{:0=6x}'.format(start_digit))\
            + 'a8' + reverse_per_two_char('{:0=6x}'.format(digit_num))
    msg = bytes.fromhex(str1)  # 轉成字節
    client.send(msg)
    res = client.recv(1024).hex()
    if dic:
    # 十六進制轉十進制
        return {start_digit: int(reverse_per_two_char(res[-4*digit_num:]), 16)}
    else:
        return int(reverse_per_two_char(res[-4*digit_num:]), 16) 

def reverse_per_two_char(chars):
    '''
    reverse '010203' to '030201'
    '''
    return ''.join(reversed(re.findall('..?', chars)))

if __name__ == "__main__":

    host = '192.168.100.2'
    start_digit = 400
    # a = is_open(host)
    a = read_register(host, start_digit) # 讀某個寄存器中的內容
    b = int(a, 16)  # 得到的真實數據
    max_distance = 2000 # 傳感器的最大最小測量距離
    min_distance = 100
    A = max_distance-(27648-b)*(max_distance-min_distance)/(27648 - 0)  #三菱PLC協議的轉換公式,轉換成真實距離
    print("真實距離:",A)

和PLC能連上,但是讀不了數據,就用了ASCii方式:

import socket
import re
import numpy as np

PORT = 7001
def read_register(host, start_digit, digit_num=1, port=PORT, dic=True):
    '''
        最終用了ASCII碼的方式
    '''
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((host, port))
    str1= "500000FF03FF000018000004010000D*"+'{:0=6d}'.format(start_digit)+"0001"
    msg = np.fromstring(str1, dtype=np.uint8)
    client.send(msg)
    res = client.recv(1024)
    if dic:
        return int(res[22:26],16)  # 這幾位是結果
    else:
        return int(reverse_per_two_char(res[-4*digit_num:]), 16)


if __name__ == "__main__":
    host = '192.168.100.2'
    start_digit = 400

    # a = is_open(host)
    a = read_register(host, start_digit) # 讀某個寄存器中的內容
    print(a)

二進制:

頭(這裏都是固定的)

#str1 ='5000' '00FF' "FF0300""0C00" "1000"
#     |header|Network|Module|Length|Time|  

具體的操作,這裏只介紹讀 D400,寫也是類似的

#     '0104'    '0000'        'a8'       '900100'   '0100'
# |read command|sub comand|D register|strat digit| digit number

strat digit就是要讀的那個寄存器 400在十六進制裏是190,補齊6位就是000190,前後轉換就是900100

digit number,是要讀的個數,這裏是1 ,0001=>0100

ASCII碼:

#str1 ='5000' '00FF' "03FF00""0018" "0000"
#     |header|Network|Module|Length|Time|  

#     '0104'    '0000'        'D*'       '000400'   '0001'
# |read command|sub comand|D register|strat digit| digit number

這個相比來說更簡單。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章