Connecting KELLER sensors to MATLAB

    Introduction


    KELLER manufactures high-precision sensors with digital output, which are connected to proprietary software for display and accumulation of readings. Often, the user needs to integrate sensors into their own monitoring and control systems. In this work, using the PR-33X high-precision pressure sensor as an example, we show the connection of KELLER sensors to the MATLAB integrated environment, originally developed for the analysis and synthesis of control systems, which has powerful tools for processing and displaying signal data.

    Brief specification of pressure transmitter KELLER PR 33X


    Standard pressure range (VPI), bar 30
    Accuracy of pressure measurement, total (10 ... 40 ° C) 0.025% VPI
    Output signal RS 485
    Baud rate 9600 or 115200 baud
    Supply voltage (U) 8 ... 28 V
    Service life 10 million cycles 0 ... 100% VPI

    The pressure transmitter also contains an integrated temperature sensor.

    Interface


    All KELLER products with index X have a digital interface (RS485 half duplex) that supports MODBUS RTU and Keller Bus protocols.

    Connection to a PC is carried out via RS485-USB converter. For best compatibility, the company recommends using the Keller converter K-114.

    Software


    To configure and record sensor readings, free CCS30 software is used, the interface of which is shown in Figure 1.

    image
    Figure 1. Accumulation and display of graphical and tabular data by CCS30 [3].

    PC connection


    The PR-33X pressure sensor was connected to a PC using a USB to RS-232/422/485 MOXA USB Serial Port

    image
    converter as shown in
    Figure 2. Figure 2. Connection diagram of the PR-33X pressure transmitter to a PC and a 12 V power supply. When powered Below 5.69 V (up to 4.95 V), the sensor readings increase. When powered below 4.95V, data is not transmitted (the sensor does not work).
    After installing the driver and attaching the MOXA converter to the PC, the COM port imageand adapter appear in the list of device manager image. In the tab (Figure 3) of the last device for our version, the RS-485 interface with a two-wire connection scheme is selected.

    image
    Figure 3. Configuring the MOXA converter to the RS-485 2W interface.

    Transmission Formats


    Data exchange between the computer (control device) and the sensor (slave device) is carried out according to the Modbus protocol messages containing the following fields [2].

    image

    First, the computer sends a request message to the sensor, then the sensor in response sends its own message with its own checksum when the requested action is successful, or sends a function with code 1 if an error occurs (invalid function or data address, etc.).

    The response (response) of the sensor is issued only after receiving a request from the control device.

    The message sent to the sensor contains one of the following function codes.

    image

    image
    Figure 4. Format of transmitted and received messages according to the Modbus RTU standard [1].

    Addresses of used sensor registers PR-33X


    image

    Examples of Modbus messages (reading of the integrated pressure and temperature sensor) [2]


    image

    Convert sensor readings to IEEE754 floating point format


    The recommended procedure for converting the four received bytes of the sensor readings into a floating-point number is shown in Figure 5. The example uses the data [2] shown in the table above.

    image
    Figure 5. Rules for converting four-byte sensor readings into a floating-point number.

    MATLAB program for reading and displaying pressure and temperature sensors PR-33X


    The PR-33X sensor reading and display program includes a main module and three subroutines. The converter operates at 115200 baud. Pressure and temperature data are read out upon request.

    The program input data is the COM port address of your device (Com_Port = variable) and the address of your converter. If only one converter is connected, then, as a rule, Device_Addr = 1. The

    number of readings is set by the Loop constant (in the example, Loop = 1000;).

    The main module:

    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 request generation routine


    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 sequence checksum calculation routine


    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

    Subroutine for converting four bytes of the sensor readings to a floating point number


    % 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

    Examples of graphical display of pressure and temperature of the PR-33X converter read by the above program are shown in Figure 6.

    image
    Figure 6. Output data of the PR-33X converter obtained by the program developed in MATLAB. The program reads 1000 pressure readings at 115200 baud in 9 seconds. The program reads 1000 pressure readings and 1000 temperature readings (separately) at 115200 baud in 17 seconds.

    MATLAB program switching data transfer speed of the converter


    To switch to a new frequency, it is necessary in the program to set the COM port address of your device (Com_Port = variable) and the required frequency of the converter (BR_Rate = 9600; or BR_Rate = 115200;)

    ATTENTION. To switch to a new data transmission frequency after setting the zero bit of the register of the UART converter, it is necessary to TURN OFF (de-energize) and then turn ON the converter again.

    % ПЕРЕХОД НА НОВУ СКОРОСТЬ ОБМЕНА (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

    Bibliographic list


    1. Dr. Bob Davidov. Communication with industrial network devices. portalnp.ru/wp-content/uploads/2013/08/12.02_Discrete-IO-unit_-MK110-_RS-485-ModBus-RTU-_-ASCII-DCON-OVEN__Ed3.pdf
    2. Description of communication protocols. For KELLER 30 and 40 series pressure transmitters. Class.Group = 5.20 Class.Group = 5.21. Version 3.2 (in Russian). www.izmerkon.ru .
    3. Control Center Series 30. User Guide. Für CCS30 Version 1.1. www.izmerkon.ru
    4. Dr. Bob Davidov. Computer control technologies in technical systems portalnp.ru/author/bobdavidov

    Also popular now: