Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Write float value in modbus register and Read value whit comma from codesys

alverman
2018-05-25
2018-05-28
  • alverman - 2018-05-25

    good morning,
    I have an arduino that runs a sct013 probe,
    Its output value is of the float type.
    How should I write it in the modbus register and then read the comma value in codesys?

    Thanks, Alberto

     
  • Anonymous - 2018-05-25

    Originally created by: Viacheslav Mezentsev

    Arduino:

    /**
     *  Modbus slave example 1:
     *  The purpose of this example is to link a data array
     *  from the Arduino to an external device.
     *
     *  Recommended Modbus Master: QModbus
     *  http://qmodbus.sourceforge.net/
     */
     
    \#include <ModbusRtu.h>
     
    // data array for modbus network sharing
    uint16_t au16data[16] = {
      3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1 };
     
    /**
     *  Modbus object declaration
     *  u8id : node id = 0 for master, = 1..247 for slave
     *  u8serno : serial port (use 0 for Serial)
     *  u8txenpin : 0 for RS-232 and USB-FTDI 
     *               or any pin number &gt; 1 for RS-485
     */
    Modbus slave(1,0,0); // this is slave @1 and RS-232 or USB-FTDI
    typedef union 
    {
        struct 
        {
            uint16_t hi;
            uint16_t lo;
        } regs;
        float value;
    } Data;
    Data data;
    void setup() 
    {
      slave.begin( 19200 ); // baud-rate at 19200
      
      data.value = 1.0f;
      au16data[0] = data.regs.hi;
      au16data[1] = data.regs.lo;
    }
     
    void loop() {
      slave.poll( au16data, 16 );
    }
    

    Codesys 3.5.12.20:

    program PLC_PRG
    var constant
       READ_COILS               : byte := 16#01;
       READ_DISCRETE_INPUTS     : byte := 16#02;
       READ_HOLDING_REGISTERS   : byte := 16#03;
       READ_INPUT_REGISTERS     : byte := 16#04;
       WRITE_SINGLE_COIL        : byte := 16#05;
       WRITE_SINGLE_REGISTER    : byte := 16#06;
       WRITE_MULTIPLE_COILS     : byte := 16#0F;
       WRITE_MULTIPLE_REGISTERS : byte := 16#10;
        
       MODE_IDLE:        byte := 0;
       MODE_CONNECT:    byte := 1;
        MODE_SET_DATA:  byte := 2;
        MODE_REQUEST:   byte := 3;
       MODE_CLOSE:     byte := 4;
       MODE_ERROR:     byte := 5;  
        // Номера портов для устройств /dev/ttyUSBn Raspberry Pi 3.
        TTYS0: byte := 1;
        TTYS1: byte := 2;    
        TTYS2: byte := 3;
        TTYS3: byte := 4;
        TTYS4: byte := 5;   
    end_var       
    var
        xBusy, xDone, xError: bool;
        ex: byte;   
        mode: uint := MODE_CONNECT;
        dw: dword;        
        start, stop, t: ulint;
        sleepus: ulint := 100;
        rvalue: real;
        timeout: time;
        tmpbuf: array [ 0 .. 255 ] of byte;
        result: RTS_IEC_RESULT;
        hCom: RTS_IEC_RESULT;
        t1: ton;        
        pFloatValue: pointer to real;
        ComSettings: COM_Settings := ( sPort := TTYS0, ulBaudrate := SYS_BR_19200, byParity := SYS_NOPARITY, byStopBits := SYS_ONESTOPBIT, ulBufferSize := 255 );        
        ReadHoldRegs: ModbusRequest := ( uiFunctionCode := READ_HOLDING_REGISTERS );  
    end_var
    // Перед использованием необходимо:
    // - обновить устройство;
    // - обновить библиотеки;
    // - настроить параметры последовательного порта;
    case mode of
          
       MODE_CONNECT:
               
          // Настройка параметров соединения.
            // Таймаут ожидания ответа.
            timeout := t#50ms;
               
            // Открываем порт.
            hCom := SysComOpen( ComSettings.sPort, adr( result ) );
            // Устанавливаем параметры порта.
            result := SysComSetSettings( hCom, adr( ComSettings ), 0 );
                
            t1( in := false );
                    
            mode := sel( result = Errors.ERR_OK, MODE_ERROR, MODE_REQUEST );
                
       MODE_REQUEST:                         
            
            SysTimeRtcHighResGet( start );
        
            repeat
                
                // Выполняем запрос.
                ReadHoldRegs( xExecute := true, usiSlaveAddr := 1, uiReadOffset := 0, uiReadLen := 2, 
                    hComPort := hCom, tTimeout := timeout, pReadBuf := adr( tmpbuf ), 
                    xBusy => xBusy, xDone => xDone, xError => xError, byModbusErrorCode => ex );            
                
                SchedWaitSleep( sleepus );
            
            until xDone or xError end_repeat
            
            SysTimeRtcHighResGet( stop );
        
            // Фактическое время выполнения запроса, [мсек].
            t := stop - start;
                    
            if xDone then                        
                
                pFloatValue := adr( tmpbuf[0] );           
                
                rvalue := pFloatValue^;
         
          end_if
            
            // Ошибка.
            if xError then
                
                case ex of
                
                    MB_ErrorCodes.RESPONSE_SUCCESS: ;
                    MB_ErrorCodes.RESPONSE_TIMEOUT: ;
                    MB_ErrorCodes.RESPONSE_INVALID_DATA: ;
                    MB_ErrorCodes.REQUEST_FAILED_TO_SEND: SysComClose( hCom ) ;
                    
                end_case                     
                
            end_if
                
            t1( in := false );
            
            mode := sel( ex = MB_ErrorCodes.REQUEST_FAILED_TO_SEND, MODE_IDLE, MODE_ERROR );
          
       // Интервал между запросами.
       MODE_IDLE:
       
          t1( in := true, pt := t#1s );
            
            if t1.q then
                  
                ReadHoldRegs( xExecute := false );
                mode := MODE_REQUEST;
     
            end_if
       // Ошибка.
       MODE_ERROR:
       
          t1( in := true, pt := t#1s );
            
            if t1.q then mode := MODE_CONNECT; end_if
     
    end_case
    

    IMG: 2018

    Raspberry.ReadHoldRegsSyncTest.ST.zip [58.72 KiB]

     
  • alverman - 2018-05-28

    Thanks Viacheslav,
    I've understood the Arduino part and applied it to my sketch and it seems to work.
    In fact, from the modbus monitor I see the two bytes assigned.
    The part in codesys is not clear to me, it's out of my reach.
    You could eliminate the superfluous?
    I use modbus tcp

    Thanks, Alberto

     

Log in to post a comment.