Examples - RS485 Network - Master (Advanced)

Top  Previous  Next

//-----------------------------------------------------------------------------
// Master.vpl, created 2003-04-07 15:44
// 
// This is a small demonstration program, that shows how to communicate using 
// the serial routines (via RS485) in the RTCU units. Two projects are involved,
// Master and Slave.
//
// Format:
// To Slave FROM Master:
// <STX> <SRC> <DST> <DO Data-LSB> <DO Data-MSB> 
//                   <AO-1-LSB> <AO-1-MSB> 
//                   <AO-2-LSB> <AO-2-MSB> 
//                   <AO-3-LSB> <AO-3-MSB> 
//                   <AO-4-LSB> <AO-4-MSB> <ETX>
//
//
// To Master FROM Slave:
// <STX> <SRC> <DST> <DI Data-LSB> <DI Data-MSB> 
//                   <AI-1-LSB> <AI-1-MSB> 
//                   <AI-2-LSB> <AI-2-MSB> 
//                   <AI-3-LSB> <AI-3-MSB> 
//                   <AI-4-LSB> <AI-4-MSB> <ETX>
//
//
// STX = 0xFF
// ETX = 0xFE
// STUFF = 0x1B
// <DO-Data-LSB>/<DO-Data-MSB> = New status for digital outputs
// <AO-n-LSB>/<AO-n-MSB> = New data for analog output n
//
// <DI-Data-LSB>/<DI-Data-MSB> = New status for digital inputs
// <AI-n-LSB>/<AI-n-MSB> = New data for analog input n
//
//-----------------------------------------------------------------------------
INCLUDE rtcu.inc
 
//  Input variables that can be configured via the configuration dialog (These are global)
VAR_INPUT
   SerialPort  : SINT; | Serial port to communicate on (0=service port, 1=port 2)
   MyNodeID    : SINT; | This units nodeid
   DestNodeID  : SINT; | NodeID of remote unit     
END_VAR;
 
//  Output variables that can be configured via the configuration dialog (These are global)
VAR_OUTPUT
   RXLed       : BOOL;                 | changes state after each receive (with correct nodeid)
END_VAR;
 
//  These are the global variables of the program
VAR
   xAI      : ARRAY[1..4] OF INT;   // Analog inputs values from remote unit
   xDI      : ARRAY[1..12] OF BOOL; // Digital inputs values from remote unit
   xAO      : ARRAY[1..4] OF INT;   // Analog output values to remote unit
   xDO      : ARRAY[1..12] OF BOOL; // Digital output values to remote unit
END_VAR;
 
//----------------------------------------------------------------------------
// Misc. helper functions
// Pack/Unpack INT and DINT's from an array of SINT
//----------------------------------------------------------------------------
function getINT:int;
var_input
   adr : ptr;
end_var;
memcpy(dst:=addr(getInt),src:=adr,len:=sizeof(getINT));
end_function;
 
function setINT;
var_input
   adr : ptr;
   v   : int;
end_var;
memcpy(dst:=adr,src:=addr(v),len:=sizeof(v));
end_function;
//----------------------------------------------------------------------------
 
PROGRAM Master;
VAR
   RX       : serFrameReceiver;
   Len      : SINT;
   RxBuffer : ARRAY[0..63] of SINT;
   TxBuffer : ARRAY[0..63] of SINT;
   Index    : SINT; // Temporary variable/counter
   tAnswer  : TON;
   str      : STRING;
END_VAR;
 
  serOpen(Port:=SerialPort, Baud:=57600, bit:=8, Parity:=0, RS485:=TRUE);
  RX(port:=SerialPort, enable:=TRUE, frame:=addr(rxbuffer), maxsize:=sint(sizeof(rxbuffer)), stuffch:=16#10, sof:=16#02, eof:=16#03);
  DebugMsg(message:="Master running");  
  tAnswer.pt:=1000;
 
   //----------------------------------------------------------------------
   // In this demo, just set the outputs of the remote node to something
   xAO[1]:=128;
   xAO[2]:=256;
   xAO[3]:=512;
   xAO[4]:=1023;
   FOR index:=1 TO 12 BY 2 DO
      xDO[index]:=TRUE;
   END_FOR;
  //----------------------------------------------------------------------
  
BEGIN
   // Update function block
   tAnswer();
 
   Sleep(delay:=100);
  
   // Build transmit frame
   TXBuffer[0]:=MyNodeID;    // Our nodeID
   TXBuffer[1]:=DestNodeID;  // Destination nodeID  
   // Set values for the 12 digital outputs
   TXBuffer[2]:=0;
   TXBuffer[3]:=0;
   FOR index:=0 TO 7 DO
      IF xDO[index+1] THEN
         TXBuffer[2]:=TXBuffer[2] OR shl8(in:=1, n:=index);
      END_IF;
   END_FOR;
   FOR index:=0 TO 3 DO
      IF xDO[index+9] THEN
         TXBuffer[3]:=TXBuffer[3] OR shl8(in:=1, n:=index);
      END_IF;
   END_FOR;
   // Set values for the 4 analog outputs
   setInt(adr:=addr(TXBuffer[4]), v:=xAO[1]);
   setInt(adr:=addr(TXBuffer[6]), v:=xAO[2]);
   setInt(adr:=addr(TXBuffer[8]), v:=xAO[3]);
   setInt(adr:=addr(TXBuffer[10]),v:=xAO[4]);
   // Send the request
   serSendData(port:=SerialPort, data:=addr(TXBuffer), size:=12, stuffch:=16#10, sof:=16#02, eof:=16#03);
 
   // Wait for response or a timeout (1 Sec)
   tAnswer.trig:=TRUE;  
   WHILE NOT RX.ready AND NOT tAnswer.DO
      RX();
      tAnswer();
   END_WHILE;
   tAnswer.trig:=FALSE;
  
   // If a response was received 
   IF RX.Ready THEN
      RXLed:=NOT RXLed;
      
      // and it is for this node...
      IF MyNodeID = RXBuffer[1] THEN
         // Get the values of the analog inputs
         xAI[1]:=getINT(adr:=addr(RXBuffer[4]));
         xAI[2]:=getINT(adr:=addr(RXBuffer[6]));
         xAI[3]:=getINT(adr:=addr(RXBuffer[8]));
         xAI[4]:=getINT(adr:=addr(RXBuffer[10]));
         // Get the values of the digital inputs
         FOR index:=0 TO 7 DO
            xDI[index+1]:=(RXBuffer[2] AND shl8(in:=1, n:=index)) <> 0;
         END_FOR;
         FOR index:=0 TO 3 DO
            xDI[index+9]:=(RXBuffer[3] AND shl8(in:=1, n:=index)) <> 0;
         END_FOR;
         
         //----------------------------------------------------------------------
         // In this demo, just show the inputs from the remote node
         DebugFmt(message:="Analog inputs: \1,\2,\3,\4", v1:=xAI[1], v2:=xAI[2], v3:=xAI[3], v4:=xAI[4]);
         str:="";
         FOR index:=1 to 12 DO
            str:=strConcat(str1:=str, str2:=intToStr(v:=int(xDI[index])));
         END_FOR;
         DebugMsg(message:=strConcat(str1:="Digital inputs: ", str2:=str));
         //----------------------------------------------------------------------
                  
      ELSE
         DebugMsg(message:="Message not for this node !");
      END_IF;
      serFrameReceiveDone(port:=SerialPort);
   ELSE
      DebugMsg(message:="Timeout waiting for response !");
   END_IF;
END;
 
END_PROGRAM;