Basic Communications Advanced Communications navigation bar

Table of Contents > QUARC > User's Guide > Communications

Intermediate Communications

The Intermediate communications blockset provides a more flexible communications architecture than the Basic communications blocks, but is still relatively straightforward to use. The Intermediate communications blocks may found under the QUARC Targets/Communications/Intermediate library in the Simulink Library Browser. This blockset includes the following blocks: Stream Call, Stream Answer, Stream Read, Stream Write and Stream Formatted Write. These blocks are intended for use in the main diagram; hence they are non-blocking. They do not wait for data to be sent or received, but return immediately. These blocks are more low-level than the Basic communications blocks discussed in the Basic Communications section but offer more flexibility. For example, it is possible to send and receive multiple items over a single connection using these blocks. This section is meant as an overview of how to use the Intermediate communications blockset. It shows how these blocks may be used to establish a connection between two models. Therefore, it is highly recommended that the user refers to these blocks' reference pages by using the Intermediate Communications Blocks section.

Two example models are used in this section to demonstrate how to use the Intermediate blocks for communications. Please refer to the QUARC Intermediate Communications Demo reference page in the MATLAB Demo section to open these models.

The first model is called "quarc_intermediate_client" and acts as the client. This model is illustrated in the following figure.

The Stream Call block connects to a local or remote host. It uses the URI of the host to connect to the host. In our case, the host URI is tcpip://localhost:18000, which causes the TCP/IP protocol to be used to connect to localhost on port 18000. Once a connection is established, the Stream Call block outputs the connection at its stm port. This stream signal is passed as an input to the other Intermediate Stream blocks to refer to the stream. The cls input is used to close the connection by setting it to a non-zero value, in case of errors or if the peer closes the connection. There are two Scopes connected to the other output ports of this block for monitoring purposes. For further details about this block, please refer to the Stream Call block's reference page.

The Stream Write block sends data over a stream. Since the stream created by the Stream Call block is fed into the stm input port of this block, it sends its data over this stream. The data being sent, in our case, is a sine wave generated by the Signal Generator block. The stream is passed to its stm output port for use by other Intermediate Stream blocks. Note that the stm output is just a copy of the stm input. The benefit of having the stm output is that the execution order of the Stream blocks may be controlled simply by daisy-chaining the blocks in the desired order. The err output can be used to check if an error occurred while sending data over the stream. This port is also connected to a Scope for monitoring purposes. For more information about this block, please refer to the Stream Write block's reference page.

The Stream Read block receives data from a stream. Since the stream created by the Stream Call block is passed to this block from the Stream Write block, it receives data from this stream. The data output port is fed into an Enabled Subsystem block. The enable signal is the new output of this block, which indicates whether the value at the data output is newly received data from the peer. If the new output is false, or zero, then no new data has been received. Inside the Enabled Subsystem is just a simple scope to plot the received data. The reason for this implementation, rather than connecting the data output directly to a Scope, is to demonstrate how to use the new output to process only the newly received data. Since there is no use for the stream after this point, the stm output port is terminated. The cls output indicates whether the peer has closed the connection or not. The err signal can be used to check if an error occurred while receiving data from the stream. These two output ports are connected to Scopes for monitoring purposes. For more information about this block, please refer to the Stream Read block's reference page.

Note that the err outputs of the Stream Write and Stream Read blocks are compared to zero to check if any error occurred during sending or receiving. Negative values indicate an error occurred. The outputs of the Compare to Zero blocks along with the cls output of the Stream Read block are fed into a Logical Operator block which performs a logical OR operation of these three outputs. The reason for performing a logical OR operation on these outputs is to close the connection in case of errors or a closed connection by the peer. The output of the Logical Operator block is passed through a Memory block to prevent algebraic loops and then fed into the cls input port of the Stream Call block to force the block to close the connection if an error occurs or the peer closed its side of the connection. Once the Stream Call block closes the connection, its stm output will be invalidated and the other Stream blocks will output zero at their err and new outputs. As a result, the cls input of the Stream Call block will go back to zero and the Stream Call block will attempt to reconnect to the host.

The second model is called "quarc_intermediate_server". It acts as the server. The following figure illustrates this sample model.

The operation of this sample model is almost identical to the "quarc_intermediate_client" model. However, there is a Stream Answer block instead of a Stream Call block so that the model acts as a server. In addition, the data being sent to the client by the Stream Write block is a sawtooth wave instead of a sine wave. The Stream Answer block listens for and accepts a connection from a local or remote host using the given URI. Since we want the two models to communicate with each other, the URI to which it listens is the same as the host URI used by the Stream Call block in the "quarc_intermediate_client" model. The first time the block executes it creates a listening stream. In subsequent executions, it tries to accept a connection. Once a connection is established, it outputs the connection at its stm port. This stream signal is passed as an input to other Intermediate Stream blocks to refer to the stream. The listening stream is maintained as long as the lcls input remains zero or false. If the lcls becomes non-zero then it closes the listening stream, provided it is not currently connected to a remote host. For our example, a constant value of 0 is fed into this input to indicate that the listening stream may never be closed (except upon model termination). The ccls input port is the same as the cls input port of the Stream Call block. For further details on this block, please refer to the Stream Answer block's reference page.

After building the models, starting both models causes the scopes to trace the desired signals. The "Received Data" scope of the client model traces the sawtooth wave received from the server model. The "Received Data" scope of the server model, in turn, traces the sine wave received from the client model, which verifies that the connection was indeed established. The figures below depict these two scopes:

Due to the use of an Enabled Subsystem in both models, the traces stop if either side stops running. In other words, the received data gets plotted only when it is new.

As mentioned earlier, the Intermediate communications blocks are non-blocking and are meant to be used in the main diagram. You have more flexibility with these blocks than the Basic communications blocks in the sense that you can have multiple 0 Stream Read and Stream Write blocks for a single connection. The order in which the blocks execute is determined by the order in which their stm ports are connected. For instance, in the "quarc_intermediate_client" model, the Stream Write block executes before the Stream Read block because the stm output of the Stream Call block is first fed into the Stream Write block and then passed on to the Stream Read block.

Words of Caution

Check both sides of the connection

Warning When using multiple Stream Read or Stream Write blocks for one connection, always make sure that the order in which these blocks are connected is the same as the order in which data is being sent or received by the peer. Also verify that the correct data types are being sent and received at each end of the connection.

Always check whether data was actually sent or received

Warning Always remember that the Intermediate communications blocks do not wait for data to be sent or received. Always verify that the data was sent or received. Never presume.

Suppose two Stream Read blocks are daisy-chained so that they execute in sequential order. They may not receive the correct data unless precautions are taken. Since the blocks do not wait for data to be received, but merely check whether there is data available, the first block may return with no data. If the data arrives before the second block executes then the second block will receive the data that was intended for the first block!

To avoid this situation, always check the new output of the Stream Read block. If the new output is false, then the second Stream Read block should not be executed. Putting the second Stream Read block in a subsystem enabled by the new output of the first block is one way to achieve this validation.

Likewise, always check the err output of the Stream Write block. If it is greater than zero then the data was written to the stream successfully. Otherwise, the data was not written to the stream, and subsequent writes which depend on the data being written successfully should not be executed in that sampling instant.

 

navigation bar