Use user variables between projects

You have learned how log functions work in previous sections. To help you understand how these functions work together, we provide two Visual Studio projects to demonstrate how user variables are created, sent, and retrieved between different applications, and display these variables in Analysis Console. Remember that you don't have to do it this way. You can use one or multiple applications to finish your job. It all depends on your needs.

Before you start this tutorial, you should read Work with user variables and Debug messages, which contain the necessary information for you to learn how to handle user variables and display values in KINGSTAR Analysis Console.

Code

We break the steps down into a few parts for you to learn it easily.

Before we start, in RT_Project_01, in Log.cpp, add the following function. We include the header wchar.h because wide characters will be used. We are writing code in the LogProject function. The first line of code, RtPrintf("Use user variables between projects.\n\n");, displays the message that describes what this function is going to do.

NOTE:  Some header files overlaps with others in different sections.

Copy
#include "RT_Project_01.h"
#include <wchar.h>

int LogProject()
{
    RtPrintf("Use user variables between projects.\n\n");
    return 0;
}

Step I: RT_Project_01

  1. In LogProject, add the following user variables and set their default values. In addition to the three variables we mentioned in previous sections, we add more variables to be used to check conditions and display values. You can review the section Add variables to know how to add them.
  2. Copy
    /* Sender and Reader */
    /*This is an example to demonstrate how to pass and use user variables
      between different applications. The instances of the UserVariable
      structure are in the shared memory, so they can be used by KINGSTAR APIs
      and KS applications.
      In this example, RT_Project_01 sends data, RT_Project_01_Reader reads the data
      and sends it to Analysis Console.*/

    /*Declare the instances of UserVariable.
      uTemperature, uVoltage, uWarning: user variables.
      Ready: checks whether RT_Project_01_Reader is running.
      Send: checks whether the data should be sent.
      uValues: the values used in the variables that will be displayed
               in Analysis Console.*/

    UserVariable uTemperature = { 0, L"Temperature", NULL, logDouble };
    UserVariable uVoltage = { 0, L"Voltage", NULL, logDouble };
    UserVariable uWarning = { 0, L"Warning", NULL, logBool };
    UserVariable Ready = { 0, L"Ready", NULL, logBool };
    UserVariable Send = { 0, L"Send", NULL, logBool };
    UserVariable uValue1 = { 0, L"Value1", NULL, logDouble };
    UserVariable uValue2 = { 0, L"Value2", NULL, logDouble };
    UserVariable uValue3 = { 0, L"Value3", NULL, logDouble };
    UserVariable uValue4 = { 0, L"Value4", NULL, logDouble };

    //Add user variables.
    KsError nRet = AddVariable(&uTemperature);
    if (nRet != errNoError)
        RtPrintf("AddVariable failed: %x\n", nRet);

    nRet = AddVariable(&uVoltage);
    if (nRet != errNoError)
        RtPrintf("AddVariable failed: %x\n", nRet);

    nRet = AddVariable(&uWarning);
    if (nRet != errNoError)
        RtPrintf("AddVariable failed: %x\n\n", nRet);

    nRet = AddVariable(&Ready);
    if (nRet != errNoError)
        RtPrintf("AddVariable Ready failed: %x\n", nRet);

    nRet = AddVariable(&Send);
    if (nRet != errNoError)
        RtPrintf("AddVariable Send failed: %x\n", nRet);

    nRet = AddVariable(&uValue1);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue1 failed: %x\n", nRet);

    nRet = AddVariable(&uValue2);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue2 failed: %x\n", nRet);

    nRet = AddVariable(&uValue3);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue3 failed: %x\n", nRet);

    nRet = AddVariable(&uValue4);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue4 failed: %x\n", nRet);

    //Set default values to user variables.
    *((double*)uTemperature.Value) = 1;
    *((double*)uVoltage.Value) = 1;
    *((BOOL*)uWarning.Value) = FALSE;
    *((BOOL*)Ready.Value) = FALSE;
    *((BOOL*)Send.Value) = TRUE;
    *((double*)uValue1.Value) = 0;
    *((double*)uValue2.Value) = 0;
    *((double*)uValue3.Value) = 0;
    *((double*)uValue4.Value) = 0;
  3. Next, we want users to start the RT_Project_01_Reader project. We use a while loop to check whether RT_Project_01_Reader is started. If it is not, RT_Project_01 will keep waiting. If it is started, the RT_Project_01 will proceed.
  4. Copy
    RtPrintf("Start RT_Project_01_Reader to continue...\n\n");

    //Check whether RT_Project_01_Reader is running.
    while (*((BOOL*)Ready.Value) == FALSE)
    {
        Sleep(10);
    }

    //After RT_Project_01_Reader is run, display the message.
    RtPrintf("The project is ready.\n\n");
  5. After RT_Project_01_Reader is ready, we start to send data to it. In this guide we use a nested for loop to control the timing of data transmission. The outer loop sends the data when Send becomes TRUE, and adds some variation to the value of the variable uWarning. The inner loop uses equations to generate dummy data and sends it three times to RT_Project_01_Reader.
  6. Copy
    //Send the values of user variables to RT_Project_01_Reader.
    //This loop sends the variables three times.
    for (int i = 0; i < 3; i++)
    {
        //When Send is FALSE, wait RT_Project_01_Reader to read the data.
        while (*((BOOL*)Send.Value) == FALSE)
        {
            Sleep(10);
        }

        //When Send is TRUE, send the data.

        //Add some variation to uWarning.
        if (i % 2 == 0)
            *((BOOL*)uWarning.Value) = FALSE;
        else
            *((BOOL*)uWarning.Value) = TRUE;

        //This loop is to calculate the values for a variable.
        for (int j = 0; j < 3; j++)
        {
            //When Send is FALSE, hold the calculation.
            while (*((BOOL*)Send.Value) == FALSE)
            {
                Sleep(10);
            }

            //When Send is TRUE, reset the values to zero and do the calcuation.

            //Reset uValues.
            *((double*)uValue1.Value) = 0;
            *((double*)uValue2.Value) = 0;
            *((double*)uValue3.Value) = 0;
            *((double*)uValue4.Value) = 0;

            /*To repeatedly use uValues, we use a switch statement to do the trick.
              Each uValue will be reset to zero after the values they contain are sent
              to RT_Project_01_Reader.
              Since the for-i loop is repeated three times, each value is calculated
              three times.*/
            switch (j)
            {
                /*These values are used for demonstration. You should determine your
                  own equation to calculate each value.*/
            case 0:
                *((double*)uValue1.Value) = *((double*)uTemperature.Value) * 1 + i;
                *((double*)uValue2.Value) = *((double*)uTemperature.Value) * 10.5 + i;
                *((double*)uValue3.Value) = *((double*)uTemperature.Value) * 20.7 + i;
                *((double*)uValue4.Value) = *((double*)uTemperature.Value) * 30.6 + i;
                break;

            case 1:
                *((double*)uValue1.Value) = *((double*)uVoltage.Value) * 1 + i;
                *((double*)uValue2.Value) = *((double*)uVoltage.Value) * 5.2 + i;
                *((double*)uValue3.Value) = *((double*)uVoltage.Value) * 10.4 + i;
                *((double*)uValue4.Value) = *((double*)uVoltage.Value) * 15.3 + i;
                break;

            case 2:
                *((double*)uValue1.Value) = *((BOOL*)uWarning.Value);
                *((double*)uValue2.Value) = *((BOOL*)uWarning.Value);
                *((double*)uValue3.Value) = *((BOOL*)uWarning.Value);
                *((double*)uValue4.Value) = *((BOOL*)uWarning.Value);
                break;

            default:
                RtPrintf("The switch statement is not working properly.\n\n");
            }

            //Set Send to FALSE for RT_Project_01_Reader to process the data.
            *((BOOL*)Send.Value) = FALSE;
        }
    }

Step II: RT_Project_01_Reader

This is a Visual Studio project used to demonstrate how user variables and debug messages work only. Since this project doesn't have other uses, we write all code in the main function, which is in main.cpp.

In the main function, add the following code:

  1. Before we deal with the user variables created in RT_Project_01, we need to use Create to link the project to the KINGSTAR Subsystem process. Displaying the devices on the EtherCAT network allows us to know whether the the connection is successful.
  2. Copy
    //Launch or connect to the KINGSTAR Subsystem process.
    KsError nRet = errNoError;
    nRet = Create(0, 0);
    if (nRet != errNoError)
    {
        RtPrintf("InitializeLink failed: %x\n", nRet);
        return FALSE;
    }

    //Create an instance of the SubsystemStatus structure and get the state from it.
    SubsystemStatus Subsystem = { ecatOffline, ecatOffline, 0, 0, 0, {ecatOffline}, {ecatOffline}, {axisOffline} };
    GetStatus(&Subsystem, NULL);

    //Display the details of the EtherCAT network. These should be the same as RT_Project_01.
    RtPrintf("Number of Devices found: %d\n", Subsystem.SlaveCount);
    RtPrintf("Number of Axes found: %d\n", Subsystem.AxesCount);
    RtPrintf("Number of I/O found: %d\n", Subsystem.IOCount);
    RtPrintf("\n");    //Launch or connect to the KINGSTAR Subsystem process.
    KsError nRet = errNoError;
    nRet = Create(0, 0);
    if (nRet != errNoError)
    {
        RtPrintf("InitializeLink failed: %x\n", nRet);
        return FALSE;
    }

    //Create an instance of the SubsystemStatus structure and get the state from it.
    SubsystemStatus Subsystem = { ecatOffline, ecatOffline, 0, 0, 0, {ecatOffline}, {ecatOffline}, {axisOffline} };
    GetStatus(&Subsystem, NULL);

    //Display the details of the EtherCAT network. These should be the same as RT_Project_01.
    RtPrintf("Number of Devices found: %d\n", Subsystem.SlaveCount);
    RtPrintf("Number of Axes found: %d\n", Subsystem.AxesCount);
    RtPrintf("Number of I/O found: %d\n", Subsystem.IOCount);
    RtPrintf("\n");
  3. After connected, we declare the same user variables as we previously declared in RT_Project_01, and use GetVariable to get their addresses one by one. GetVariable is required to use in this project because we need to make changes to these variables between two projects. Without GetVariable, even if you declare the same-name variables in second project, they are still different from the variables in the first.
  4. You can also use GetVariables. In this guide we use GetVariable becuase it's intuitive and easy to use.

    Copy
    //Declare the same instances of UserVariable in RT_Project_01.
    UserVariable uTemperature = { 0, L"Temperature", NULL, logDouble };
    UserVariable uVoltage = { 0, L"Voltage", NULL, logDouble };
    UserVariable uWarning = { 0, L"Warning", NULL, logBool };
    UserVariable Ready = { 0, L"Ready", NULL, logBool };
    UserVariable Send = { 0, L"Send", NULL, logBool };
    UserVariable uValue1 = { 0, L"Value1", NULL, logDouble };
    UserVariable uValue2 = { 0, L"Value2", NULL, logDouble };
    UserVariable uValue3 = { 0, L"Value3", NULL, logDouble };
    UserVariable uValue4 = { 0, L"Value4", NULL, logDouble };

    //Get the address of the user variables.
    /*In Sender application (RT_Project_01), you don't need to use GetVariable because
      you can get the address of a variable after you use AddVariable. But in Reader
      application (RT_Project_01_Reader), you must use GetVariable to access the variables.*/
    GetVariable(&uTemperature);
    GetVariable(&uVoltage);
    GetVariable(&uWarning);
    GetVariable(&uValue1);
    GetVariable(&uValue2);
    GetVariable(&uValue3);
    GetVariable(&uValue4);
    GetVariable(&Ready);
    GetVariable(&Send);
  5. After retrieve the variables, we set Ready and Send to TRUE. Ready is used to tell RT_Project_01 that we are ready, so RT_Project_01 can continue; Send is used to determine whether RT_Project_01 should send the data. We have listed each variable's meaning when we declare them in RT_Project_01. Take a look at them.
  6. Copy
    //By default, we set Ready to TRUE so RT_Project_01 will continue to run.
    *((bool*)Ready.Value) = TRUE;
    *((bool*)Send.Value) = TRUE;
  7. When Send is TRUE, RT_Project_01 calculates the values for each variable. After the calculation is done, Send will be set to FALSE and RT_Project_01_Reader sends the variable and its calculated values to Analysis Console. Each time RT_Project_01_Reader sends the data, Send will be set to TRUE, so the entire process starts from RT_Project_01 again, until all the variables and their values are calculated and sent to Analysis Console.
  8. Copy
    //Display the logs and their values in Analysis Console.
    //These values are for demonstration.
    for (int i = 0; i < 3; i++)
    {
        //When Send is TRUE, wait RT_Project_01 to send the data.
        while (*((bool*)Send.Value) == TRUE)
        {
            Sleep(10);
        }

        //When Send is FALSE, receive the data.

        //Send the logs to Analysis Console.
        RtPrintf("DebugMessage %d starts.\n\n", i);
     
        //Get the values of the first variable and send them to Analysis Console.
        DebugMessage(0, logInfo, L"Melting temperature of metal", TRUE,
            *((double*)uValue1.Value),
            *((double*)uValue2.Value),
            *((double*)uValue3.Value),
            *((double*)uValue4.Value));

        /*After the first variable is sent, wait RT_Project_01 to reset
          uValues to zero, and calculate the values of the second variable.*/
        *((bool*)Send.Value) = TRUE;

        while (*((bool*)Send.Value) == TRUE)
        {
            Sleep(10);
        }

        //Get the values of the second variable and send them to Analysis Console.
        DebugMessage(1, logInfo, L"Voltage of power", TRUE,
            *((double*)uValue1.Value),
            *((double*)uValue2.Value),
            *((double*)uValue3.Value),
            *((double*)uValue4.Value));

        /*After the first variable is sent, wait RT_Project_01 to reset
          uValues to zero, and calculate the values of the third variable.*/
        *((bool*)Send.Value) = TRUE;

        while (*((bool*)Send.Value) == TRUE)
        {
            Sleep(10);
        }

        //Get the values of the third variable and send them to Analysis Console.
        DebugMessage(2, logWarning, L"Warning levels", TRUE,
            *((double*)uValue1.Value),
            *((double*)uValue2.Value),
            *((double*)uValue3.Value),
            *((double*)uValue4.Value));

        //Set Send to TRUE for RT_Project_01 to process the data.
        *((bool*)Send.Value) = TRUE;
    }
  9. After all variables and their values are sent to Analysis Console, we display a message to inform users that all messages are delivered.
  10. Copy
    RtPrintf("DebugMessage ends.\n\n");
    return 0;

Complete code

The complete code should be as follows:

RT_Project_01:

Copy
int LogProject()
{
    RtPrintf("Use user variables between projects.\n\n");
    
    /* Sender and Reader */
    /*This is an example to demonstrate how to pass and use user variables
      between different applications. The instances of the UserVariable
      structure are in the shared memory, so they can be used by KINGSTAR APIs
      and KS applications.
      In this example, RT_Project_01 sends data, RT_Project_01_Reader reads the data
      and sends it to Analysis Console.*/

    /*Declare the instances of UserVariable.
      uTemperature, uVoltage, uWarning: user variables.
      Ready: checks whether RT_Project_01_Reader is running.
      Send: checks whether the data should be sent.
      uValues: the values used in the variables that will be displayed
               in Analysis Console.*/

    UserVariable uTemperature = { 0, L"Temperature", NULL, logDouble };
    UserVariable uVoltage = { 0, L"Voltage", NULL, logDouble };
    UserVariable uWarning = { 0, L"Warning", NULL, logBool };
    UserVariable Ready = { 0, L"Ready", NULL, logBool };
    UserVariable Send = { 0, L"Send", NULL, logBool };
    UserVariable uValue1 = { 0, L"Value1", NULL, logDouble };
    UserVariable uValue2 = { 0, L"Value2", NULL, logDouble };
    UserVariable uValue3 = { 0, L"Value3", NULL, logDouble };
    UserVariable uValue4 = { 0, L"Value4", NULL, logDouble };

    //Add user variables.
    KsError nRet = AddVariable(&uTemperature);
    if (nRet != errNoError)
        RtPrintf("AddVariable failed: %x\n", nRet);

    nRet = AddVariable(&uVoltage);
    if (nRet != errNoError)
        RtPrintf("AddVariable failed: %x\n", nRet);

    nRet = AddVariable(&uWarning);
    if (nRet != errNoError)
        RtPrintf("AddVariable failed: %x\n\n", nRet);

    nRet = AddVariable(&Ready);
    if (nRet != errNoError)
        RtPrintf("AddVariable Ready failed: %x\n", nRet);

    nRet = AddVariable(&Send);
    if (nRet != errNoError)
        RtPrintf("AddVariable Send failed: %x\n", nRet);

    nRet = AddVariable(&uValue1);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue1 failed: %x\n", nRet);

    nRet = AddVariable(&uValue2);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue2 failed: %x\n", nRet);

    nRet = AddVariable(&uValue3);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue3 failed: %x\n", nRet);

    nRet = AddVariable(&uValue4);
    if (nRet != errNoError)
        RtPrintf("AddVariable uValue4 failed: %x\n", nRet);

    //Set default values to user variables.
    *((double*)uTemperature.Value) = 1;
    *((double*)uVoltage.Value) = 1;
    *((BOOL*)uWarning.Value) = FALSE;
    *((BOOL*)Ready.Value) = FALSE;
    *((BOOL*)Send.Value) = TRUE;
    *((double*)uValue1.Value) = 0;
    *((double*)uValue2.Value) = 0;
    *((double*)uValue3.Value) = 0;
    *((double*)uValue4.Value) = 0;

    RtPrintf("Start RT_Project_01_Reader to continue...\n\n");

    //Check whether RT_Project_01_Reader is running.
    while (*((BOOL*)Ready.Value) == FALSE)
    {
        Sleep(10);
    }

    //After RT_Project_01_Reader is run, display the message.
    RtPrintf("The project is ready.\n\n");

    //Send the values of user variables to RT_Project_01_Reader.
    //This loop sends the variables three times.
    for (int i = 0; i < 3; i++)
    {
        //When Send is FALSE, wait RT_Project_01_Reader to read the data.
        while (*((BOOL*)Send.Value) == FALSE)
        {
            Sleep(10);
        }

        //When Send is TRUE, send the data.

        //Add some variation to uWarning.
        if (i % 2 == 0)
            *((BOOL*)uWarning.Value) = FALSE;
        else
            *((BOOL*)uWarning.Value) = TRUE;

        //This loop is to calculate the values for a variable.
        for (int j = 0; j < 3; j++)
        {
            //When Send is FALSE, hold the calculation.
            while (*((BOOL*)Send.Value) == FALSE)
            {
                Sleep(10);
            }

            //When Send is TRUE, reset the values to zero and do the calcuation.

            //Reset uValues.
            *((double*)uValue1.Value) = 0;
            *((double*)uValue2.Value) = 0;
            *((double*)uValue3.Value) = 0;
            *((double*)uValue4.Value) = 0;

            /*To repeatedly use uValues, we use a switch statement to do the trick.
              Each uValue will be reset to zero after the values they contain are sent
              to RT_Project_01_Reader.
              Since the for-i loop is repeated three times, each value is calculated
              three times.*/
            switch (j)
            {
                /*These values are used for demonstration. You should determine your
                  own equation to calculate each value.*/
            case 0:
                *((double*)uValue1.Value) = *((double*)uTemperature.Value) * 1 + i;
                *((double*)uValue2.Value) = *((double*)uTemperature.Value) * 10.5 + i;
                *((double*)uValue3.Value) = *((double*)uTemperature.Value) * 20.7 + i;
                *((double*)uValue4.Value) = *((double*)uTemperature.Value) * 30.6 + i;
                break;

            case 1:
                *((double*)uValue1.Value) = *((double*)uVoltage.Value) * 1 + i;
                *((double*)uValue2.Value) = *((double*)uVoltage.Value) * 5.2 + i;
                *((double*)uValue3.Value) = *((double*)uVoltage.Value) * 10.4 + i;
                *((double*)uValue4.Value) = *((double*)uVoltage.Value) * 15.3 + i;
                break;

            case 2:
                *((double*)uValue1.Value) = *((BOOL*)uWarning.Value);
                *((double*)uValue2.Value) = *((BOOL*)uWarning.Value);
                *((double*)uValue3.Value) = *((BOOL*)uWarning.Value);
                *((double*)uValue4.Value) = *((BOOL*)uWarning.Value);
                break;

            default:
                RtPrintf("The switch statement is not working properly.\n\n");
            }

            //Set Send to FALSE for RT_Project_01_Reader to process the data.
            *((BOOL*)Send.Value) = FALSE;
        }
    }

    return 0;
}

 

RT_Project_01_Reader:

Copy
#include "RT_Project_01_Reader.h"

int _tmain(int argc, _TCHAR * argv[])
{
    //Launch or connect to the KINGSTAR Subsystem process.
    KsError nRet = errNoError;
    nRet = Create(0, 0);
    if (nRet != errNoError)
    {
        RtPrintf("InitializeLink failed: %x\n", nRet);
        return FALSE;
    }

    //Create an instance of the SubsystemStatus structure and get the state from it.
    SubsystemStatus Subsystem = { ecatOffline, ecatOffline, 0, 0, 0, {ecatOffline}, {ecatOffline}, {axisOffline} };
    GetStatus(&Subsystem, NULL);

    //Display the details of the EtherCAT network. These should be the same as RT_Project_01.
    RtPrintf("Number of Devices found: %d\n", Subsystem.SlaveCount);
    RtPrintf("Number of Axes found: %d\n", Subsystem.AxesCount);
    RtPrintf("Number of I/O found: %d\n", Subsystem.IOCount);
    RtPrintf("\n");
 
    //Declare the same instances of UserVariable in RT_Project_01.
    UserVariable uTemperature = { 0, L"Temperature", NULL, logDouble };
    UserVariable uVoltage = { 0, L"Voltage", NULL, logDouble };
    UserVariable uWarning = { 0, L"Warning", NULL, logBool };
    UserVariable Ready = { 0, L"Ready", NULL, logBool };
    UserVariable Send = { 0, L"Send", NULL, logBool };
    UserVariable uValue1 = { 0, L"Value1", NULL, logDouble };
    UserVariable uValue2 = { 0, L"Value2", NULL, logDouble };
    UserVariable uValue3 = { 0, L"Value3", NULL, logDouble };
    UserVariable uValue4 = { 0, L"Value4", NULL, logDouble };

    //Get the address of the user variables.
    /*In Sender application (RT_Project_01), you don't need to use GetVariable because
      you can get the address of a variable after you use AddVariable. But in Reader
      application (RT_Project_01_Reader), you must use GetVariable to access the variables.*/
    GetVariable(&uTemperature);
    GetVariable(&uVoltage);
    GetVariable(&uWarning);
    GetVariable(&uValue1);
    GetVariable(&uValue2);
    GetVariable(&uValue3);
    GetVariable(&uValue4);
    GetVariable(&Ready);
    GetVariable(&Send);

    //By default, we set Ready to TRUE so RT_Project_01 will continue to run.
    *((bool*)Ready.Value) = TRUE;
    *((bool*)Send.Value) = TRUE;

    //Display the logs and their values in Analysis Console.
    //These values are for demonstration.
    for (int i = 0; i < 3; i++)
    {
        //When Send is TRUE, wait RT_Project_01 to send the data.
        while (*((bool*)Send.Value) == TRUE)
        {
            Sleep(10);
        }

        //When Send is FALSE, receive the data.

        //Send the logs to Analysis Console.
        RtPrintf("DebugMessage %d starts.\n\n", i);
     
        //Get the values of the first variable and send them to Analysis Console.
        DebugMessage(0, logInfo, L"Melting temperature of metal", TRUE,
            *((double*)uValue1.Value),
            *((double*)uValue2.Value),
            *((double*)uValue3.Value),
            *((double*)uValue4.Value));

        /*After the first variable is sent, wait RT_Project_01 to reset
          uValues to zero, and calculate the values of the second variable.*/
        *((bool*)Send.Value) = TRUE;

        while (*((bool*)Send.Value) == TRUE)
        {
            Sleep(10);
        }

        //Get the values of the second variable and send them to Analysis Console.
        DebugMessage(1, logInfo, L"Voltage of power", TRUE,
            *((double*)uValue1.Value),
            *((double*)uValue2.Value),
            *((double*)uValue3.Value),
            *((double*)uValue4.Value));

        /*After the first variable is sent, wait RT_Project_01 to reset
          uValues to zero, and calculate the values of the third variable.*/
        *((bool*)Send.Value) = TRUE;

        while (*((bool*)Send.Value) == TRUE)
        {
            Sleep(10);
        }

        //Get the values of the third variable and send them to Analysis Console.
        DebugMessage(2, logWarning, L"Warning levels", TRUE,
            *((double*)uValue1.Value),
            *((double*)uValue2.Value),
            *((double*)uValue3.Value),
            *((double*)uValue4.Value));

        //Set Send to TRUE for RT_Project_01 to process the data.
        *((bool*)Send.Value) = TRUE;
    }

    RtPrintf("DebugMessage ends.\n\n");

    return 0;
}

 

Output:

RT_Project_01:

RT_Project_01_Reader:

Analysis Console: