将KELLER传感器连接到MATLAB

引言


凯勒(KELLER)生产带数字输出的高精度传感器,该传感器连接到专有软件以显示和累积读数。 通常,用户需要将传感器集成到他们自己的监视和控制系统中。 在这项工作中,以PR-33X高精度压力传感器为例,我们展示了KELLER传感器与MATLAB集成环境的连接,该集成环境最初是为控制系统的分析和综合而开发的,它具有用于处理和显示信号数据的强大工具。

压力变送器KELLER PR 33X的简要规格


标准压力范围(VPI),bar 30
压力测量精度,总计(10 ... 40°C)VPI的0.025%
RS 485输出
波特率9600或115200波特
电源电压(U)8 ... 28 V
使用寿命1000万次循环0 ... 100%VPI

压力变送器还包括一个集成的温度传感器。

介面


所有索引为X的KELLER产品都有一个数字接口(RS485半双工),支持MODBUS RTU和Keller Bus协议。

通过RS485-USB转换器连接到PC。 为了获得最佳兼容性,公司建议使用Keller转换器K-114。

软体类


为了配置和记录传感器读数,使用了免费的CCS30软件,其界面如图1所示。

图片
图1. CCS30程序[3]对图形和表格数据的累积和显示。

PC连接


根据图2中的示意图,使用USB到RS-232 / 422/485 MOXA USB串行端口转换器将PR-33X压力传感器连接到PC。

图片
图2. PR-33X压力变送器与PC和12 V电源的连接图当供电低于5.69 V(最高4.95 V)时,传感器读数会增加。 当电源低于4.95V时,不会传输数据(传感器不起作用)。

安装驱动程序并将MOXA转换器连接到PC后,COM端口将出现在设备管理器列表中 图片 和适配器 图片 。 在我们版本的最后一个设备的选项卡(图3)中,选择了具有两线连接方案的RS-485接口。

图片
图3.将MOXA转换器配置为RS-485 2W接口。

传输格式


根据包含以下字段[2]的Modbus协议消息,在计算机(控制设备)和传感器(从设备)之间进行数据交换。

图片

首先,计算机向传感器发送请求消息,然后传感器在请求的操作成功时作为响应发送自己的消息,并带有自己的校验和;如果发生错误,则发送代码为1的函数(无效的函数或数据地址等)。

传感器的响应(响应)仅在收到控制设备的请求后才发布。

发送到传感器的消息包含以下功能代码之一。

图片

图片
图4.根据Modbus RTU标准[1]发送和接收的消息的格式。

使用的传感器寄存器PR-33X的地址


图片

Modbus消息示例(读取集成压力和温度传感器)[2]


图片

将传感器读数转换为IEEE754浮点格式


将传感器读数的四个接收字节转换为浮点数的推荐过程如图5所示。该示例使用上表中显示的数据[2]。

图片
图5.将四字节传感器读数转换为浮点数的规则。

用于读取和显示压力和温度传感器PR-33X的MATLAB程序


PR-33X传感器读取和显示程序包括一个主模块和三个子例程。 转换器的工作波特率为115200。 根据要求读取压力和温度数据。

程序输入数据是设备的COM端口地址(Com_Port =变量)和转换器的地址。 如果仅连接一个转换器,则通常Device_Addr = 1。

读数的数量由Loop常数设置(在示例中,Loop = 1000;)。

主要模块:

clear all; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Input data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Com_Port = 'COM9'; Device_Addr = 1; % Address of Sensor, 8 bit: 1..255 Function = 3; % 3 or 4 is read; Pr_Rg_Addr = 2; % First address of two pressure data registers (4 bytes) Temp_Rg_Addr = 8; % First address of two temperature data registers Address_Range = 2; % Range of data address %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % End of Input data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Make COM port connection s=serial(Com_Port,'Baudrate',115200); % 9600 115200 fopen (s); pause(0.1); Loop = 1000; pr(1:Loop) = 0; temp(1:Loop) = 0; for i = 1:Loop %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Read pressure %%%%%%%%%%%%%%%%%%%%%%%%%%%%% RTU_request = RTU_code(Device_Addr,Function,Pr_Rg_Addr,Address_Range); fwrite(s, RTU_request); %pause(0.01); % >=0.001s for PR-33X, for 115200 Baudrate while ~(get(s,'BytesAvailable')>8) end BytesAvailable = get(s,'BytesAvailable'); Rx = fread(s,BytesAvailable)'; pr(i) = sensorOUT_to_float(Rx); % in bar %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Read temperature %%%%%%%%%%%%%%%%%%%%%%%%%%%%% RTU_request = RTU_code(Device_Addr,Function,Temp_Rg_Addr,Address_Range); fwrite(s, RTU_request); while ~(get(s,'BytesAvailable')>8) end BytesAvailable = get(s,'BytesAvailable'); % if BytesAvailable > 0 Rx = fread(s,BytesAvailable)'; temp(i) = sensorOUT_to_float(Rx); % in bar end % Close COM port fclose (s); delete (s); figure (3) clf('reset'); % Clear current figure window [AX,H1,H2] = plotyy (1:length(pr),pr,1:length(temp),temp); hold(AX(1)); hold(AX(2)); set(H1,'LineWidth',2); grid(AX(2),'on'); xlabel('Sampling, num'); % Y1_max = max(get(AX(1),'ytick')); % set(AX(1),'ytick',[0:Y1_max/10:Y1_max]); % set(AX(2),'ytick',[0:0.2:2]); set(get(AX(1),'Ylabel'),'String',', '); set(get(AX(2),'Ylabel'),'String',', . '); title(sprintf('   ')); % End of m file 

Modbus RTU请求生成例程


 function RTU_request = RTU_code(Device_Addr,Function,Data_First_Address,Address_Range) % Device_Addr == Device Address 8 bit: 1..255 % Function == % 3 or 4 is read; 6 is write in one register; 16 - write in two registers, % Data_First_Address == Address of first register data (2 bytes) % Addrress_Range == Range of Addreses; % Data_First_Address_Bytes = [floor(Data_First_Address/256) rem(Data_First_Address,256)]; Address_Range_Bytes = [floor(Address_Range/256) rem(Address_Range,256)]; % Master's Tx data without Check sum Code = [Device_Addr Function Data_First_Address_Bytes Address_Range_Bytes]; Code_Char = dec2hex(Code); if size(Code_Char,2)==1 Code_Char(:,2)=Code_Char(:,1); Code_Char(:,1)='0'; end Code_Char_line = []; for I = 1:length(Code) Code_Char_line = [Code_Char_line Code_Char(I,1:2)]; end % Check sum calculation Check_Sum = crc_calculator(Code_Char_line); % Master's Tx data with Check sum RTU_request = [Code hex2dec(Check_Sum(1:2)) hex2dec(Check_Sum(3:4))]; % End of m file 

Modbus RTU序列校验和计算例程


 function output_hex_string = crc_calculator (Input_hex); %Input_hex = 'F70302640008'; % <= 2 * 16 Char F = [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]; xor_constant = [1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1]; for i = 1 : length (Input_hex) / 2; A = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]; if ~(i > length (Input_hex)/2) A_hex = Input_hex ((i-1)*2+1:i*2); % Two HEX bytes A_bin = dec2bin (hex2dec (A_hex)); length_A_bin = length (A_bin); for j = 0 : length_A_bin - 1 A (16 - j) = str2num(A_bin (length_A_bin - j)); end end F = xor (F,A); for ii = 1 : 8 if F(16) ==1 if xor_constant (1) == 0 F_shift (1) = 0; else F_shift (1) = 1; end for j = 2 : 16; if xor_constant (j) == F (j-1); F_shift (j) = 0; else F_shift (j) = 1; end end else F_shift = circshift(F',1)'; end F = F_shift; end end h = num2str(F); h = h(1:3:length(h)); output_hex_string = num2str([dec2hex(bin2dec(h(9:12))) dec2hex(bin2dec(h(13:16))) dec2hex(bin2dec(h(1:4))) dec2hex(bin2dec(h(5:8)))]); % End of m file 

子例程,用于将传感器读数的四个字节转换为浮点数


 % Transmission Sensor's output bytes to float value function val = sensorOUT_to_float(Rx) B(1) = Rx(4); B(2) = Rx(5); B(3) = Rx(6); B(4) = Rx(7); %1 bit of sign + 8 bits of exponent + 23 bits of mantis ( = 32 bits or 4x8 bytes) v_res = []; for i = 1:4 v_bit = dec2bin(B(i)); if length(v_bit)<8 % add zeros to get 8 bits for j = 1:(8-length(v_bit)) v_bit = ['0' v_bit]; end end v_res = [v_res v_bit]; end % Checking % v_res = ['0' '10000010' '01010010000001011011110'] == 10.5631999969482421875  s_mnt = bin2dec(v_res(1)); %sign of mantis E = bin2dec(v_res(2:9)); %exponent M = bin2dec(v_res(10:32)); % mantis if s_mnt==0 val = (1+M/8388608)*2^(E-127); % 8388608 = 2^23 else val = -(1+M/8388608)*2^(E-127); end % End of m file 

上述程序读取的PR-33X压力和温度曲线图的示例如图6所示。

图片
图6.由MATLAB开发的程序接收到的PR-33X转换器的输出。 程序在9秒钟内以115200波特读取1000个压力读数。 程序在17秒内以115200波特的速度分别读取1000个压力读数和1000个温度读数。

MATLAB程序切换转换器的数据传输速度


要切换到新频率,需要在程序中设置设备的COM端口地址(Com_Port =变量)和所需的转换器频率(BR_Rate = 9600;或BR_Rate = 115200;)。

注意事项 要在设置UART转换器的寄存器的零位后切换到新的数据传输频率,必须先关闭(断电),然后再次打开转换器。

 %      (9600  115200 )    UART   -  clear all; % Input data Com_Port = 'COM9'; BR_Rate = 115200; % 9600 or 115200 % End of Input data % Device_Addr = 1; % Address of Sensor, 8 bit: 1..255 % Function = 6; % Write; % UART_Rg_Addr = 512; % First address of UART Rg (2 bytes) % Data = 0 0; % Rate 9600 bod % Data = 0 1; % Rate 115200 bod % RTU_request = [Device_Addr Function UART_Rg_Addr Data Check_sum] % RTU_request = [ 1 6 2 0 0 0 136 114]; % 9600 bod request in hex % RTU_request = [ 1 6 2 0 0 1 73 178]; % 115200 bod request in hex if BR_Rate == 9600 % 115200 s=serial(Com_Port,'Baudrate',115200); fopen (s); pause(0.1); RTU_request =[ 1 6 2 0 0 0 136 114]; else s=serial(Com_Port,'Baudrate',9600); fopen (s); pause(0.1); RTU_request = [ 1 6 2 0 0 1 73 178]; end fwrite(s, RTU_request); pause(0.004); % >=0.001s for PR-33X, for 115200 Baudrate BytesAvailable = get(s,'BytesAvailable'); if BytesAvailable > 0 Rx = fread(s,BytesAvailable)' end % close COM port fclose (s); delete (s); % End of m file 

书目清单


  1. 博士 鲍勃·戴维多夫(Bob Davidov)。 与工业网络设备的通信。 portalnp.ru/wp-content/uploads/2013/08/12.02_Discrete-IO-unit_-MK110-_RS-485-ModBus-RTU-_-ASCII-DCON-OVEN__Ed3.pdf
  2. 通信协议的描述。 用于KELLER 30和40系列压力变送器。 Class.Group = 5.20 Class.Group = 5.21 3.2版(俄语)。 www.izmerkon.ru
  3. 控制中心系列30。用户指南。 FürCCS30版本1.1。 www.izmerkon.ru
  4. 博士 鲍勃·戴维多夫(Bob Davidov)。 技术系统中的计算机控制技术portalnp.ru/author/bobdavidov

Source: https://habr.com/ru/post/zh-CN440966/


All Articles