Tutorial: 2 - Getting Started


WAT provides easy to use API's, through plugins, to interact with hardware. This first part of the getting started tutorial will introduce simple I/O functionality. We will first set up our HTML file, learn how to load plugins and create a simple switch.

To start off the example, we need to create an "index.html" file in a directory within our web server. For this example create a directory called "tutorial" and place an "index.html" file with the code below. When the code below is executed on a WAT device, the console will display an object which can be expanded to show all the object properties.

For a quick-start HelloWorld application to introduce you to HTML and JavaScript, please refer to 1 - Hello World.

<html>
    <head>
    </head>
    <body>
    </body>
    <!-- For best practice, we include scripts here -->
    <script type="text/javascript">
        //to load a hardware object
        if (typeof ($wat) == 'object')
        {
            $hw = $wat.load('hw')[0]; //load our hw object
        }
        //to print out our object decleration
        console.log($hw);
    </script>
</html>


I/O Logic & Variables


Let's take a simple start-stop circuit that controls a pump. Below we can see circuit diagram displaying some simple PLC logic.

Logic

To implement this in JavaScript, we can use the example below. For simplicity, we will first create a sequential logic routine with no asynchronous event handling.

Please note that JavaScript cannot execute scans accurately. Any scan times used throughout examples are approximations and may deviate from the expected scan time.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Arcx - Getting Started Example</title>
</head>
<body>

</body>
<script type="text/javascript">

    if (typeof ($wat) == 'object')
    {
        $hw = $wat.load('hw')[0]; //load our hw object
    }

    var M10 = 0; // PumpON

    var I10 = $hw.digInputs[10]; // Start PB
    var I11 = $hw.digInputs[11]; // Stop PB
    var Q01 = $hw.digOutputs[1]; // Pump On Output

    //using an interval we can "scan" approximately every 100ms
    setInterval(function(){
        // Network 1 : Input
        // if (I10 OR M10) AND I11 is True, set M10 = 1
        // Note in JS 1/0 is the same as True/False
        if ((I10.state || M10) && I11.state) {
            M10 = 1;
        } else {
            M10 = 0;
        }
        //print our state for debugging
        console.log("M10 = " + M10);

        // Network 2 : Output
        if (M10 == 1) {
            Q01.set();
            console.log("Q01 Set");
        } else {
            Q01.clear();
            console.log("Q01 Cleared");
        }

        console.log("Output: " + Q01.state);

    }, 100*10); //100ms*10 scan time

</script>
</html>

This code will be evaluated approximately every 1 second. If we want this code to run as soon as there is any input changes (as interrupts) then we must implement event handlers.

See Signals for more detail on how events work.


Event Based Logic


In the switch above we have 2 inputs connected to a single output. We can handle these events asynchronously using event based logic and latching the 2 inputs to a single output. I1.0 will set the output HIGH while I1.1 will set the output LOW. The code below can now run without any scan time since we are now handling the inputs as interrupts.

<html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
    <title>Arcx - Getting Started Example</title>
    </head>
    <body>

    </body>
    <script type="text/javascript">

    if (typeof ($wat) == 'object')
    {
        $hw = $wat.load('hw')[0]; //load our hw object
    }

    var I10 = $hw.digInputs[10]; // Start PB
    var I11 = $hw.digInputs[11]; // Stop PB
    var Q01 = $hw.digOutputs[1]; // Pump On Output

    //enable edge tracking
    I10.edgeMask = I10.Edge.Rising
    I11.edgeMask = I11.Edge.Rising;

    // we can directly latch inputs to the pump output
    // without the use of temporary memory variables

    //the rising edge of I1.0 will set our pump output to HIGH
    I10.risingEdge.connect(Q01, Q01.set);

    //the rising edge of I1.1 will set our pump output to LOW
    I11.risingEdge.connect(Q01, Q01.clear);

    </script>
</html>

Above we are implementing a lot of meta variables to keep our code in the same style as ladder logic, but these are not required. Below is the same code but much shorter.

<html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
    <title>Arcx - Getting Started Example</title>
    </head>
    <body>

    </body>
    <script type="text/javascript">

    if (typeof ($wat) == 'object')
    {
        $hw = $wat.load('hw')[0]; //load our hw object
    }
    $hw.digInputs[10].edgeMask = $hw.digInputs[10].Edge.Rising
    $hw.digInputs[11].edgeMask = $hw.digInputs[11].Edge.Rising;
    $hw.digInputs[10].risingEdge.connect($hw.digOutputs[1], $hw.digOutputs[1].set);
    $hw.digInputs[11].risingEdge.connect($hw.digOutputs[1], $hw.digOutputs[1].clear);

    </script>
</html>