doc(docs): proofread the docs

This commit is contained in:
Victor Nakoryakov
2017-06-26 16:35:22 +03:00
parent af8e1b7dc5
commit eeee0d709c
9 changed files with 596 additions and 563 deletions

View File

@@ -5,47 +5,46 @@ title: Complex Projects
Complex Projects
================
In past chapters of the tutorial series youve used bare minimum of nodes to
build simple projects. But what if you need to create something more complex?
In the tutorial's past chapters, youve used a bare minimum of nodes to build
simple projects. But what if you need to create something more complex?
The principle of programming will stay the same although you would create
more patches and use more nodes.
The programming principles stay the same even if you create more patches and
use more nodes.
Search for nodes
----------------
Before implementing your own nodes check if there is a ready to use node
that will solve your problem. Visit [library index](/libs/) to browse for
existing nodes.
Before implementing your own nodes, check if there is a ready to use node that
will solve your problem. Visit [library index](/libs/) to browse for existing
nodes.
Interfacing with hardware
-------------------------
If you want to use a sensor or an electronic module that you havent find
support for its quite possible that all you need for it is few standard
nodes like `analog-input` or `digital-output`.
If you want to use a sensor or an electronic module that you havent found
support for, its quite possible that all you need is a few standard nodes
like `analog-input` or `digital-output`.
Refer to the item documentation to understand how you can talk with the
Refer to the item's documentation to understand how you can talk with the
hardware.
Write a native wrapper
----------------------
You can implement a new node not only with XOD, but with C++ as well.
In this case you can even wrap an existing native library to make it
available in XOD.
You can implement new nodes not only in XOD, but also with C++.
You can even wrap an existing native library to make it available in XOD.
See implementation of `analog-input`, `digital-output`, `text-lcd-16x2`
as an example of how to do this.
See the implementation of `analog-input`, `digital-output`, and `text-lcd-16x2`
for examples of how to do this.
Tell us what you need
---------------------
XOD ecosystem is poor since the project is very-very young. If you need
a node for something, [ask for it on our forum](//forum.xod.io). That
would help us to better prioritize our work.
The XOD ecosystem is barebones since the project is very-very young. If you
need a node for something, [ask for it on our forum](//forum.xod.io). That will
help us better prioritize our work.
Dive into details
-----------------
Read [Users guide](/docs/#users-guide) to understand XOD better.
Read the [Users guide](/docs/#users-guide) to understand XOD better.

View File

@@ -1,20 +1,23 @@
---
title: Data Types and Conversions Between Them
title: Data Types and Conversions
---
Data Types and Conversions Between Them
Data Types and Conversions
=======================================
In previous tutorial chapters youve had a deal with pulses and logical values.
In previous tutorial chapters, youve had to deal with pulses and logical
values.
A pulse just denotes the fact something happened and logical values carry
either 0 or 1 value.
The later is called *boolean* data type and its values are called boolean values.
Its just a matter of terminology, but boolean value which corresponds to
1/high/on/enable is called *true*, and 0/low/off/disable value is called *false*.
The latter is called a *boolean* data type, and its values are called boolean
values.
Its just a matter of terminology, but the boolean value that corresponds to
1/high/on/enable is called *true*, and the boolean value corresponding to
0/low/off/disable value is called *false*.
There are more types in XOD to express more than simple flow of boolean values.
Lets get familiar with them.
XOD has other types to express more than a simple flow of boolean values.
Let's get familiar with them.
Number type
-----------
@@ -22,42 +25,45 @@ Number type
42, 3.14159, -2.7… All these are numbers. They can be used to describe values
like temperature, distance, angle, acceleration along an axis, and many more.
Lets use few nodes that employ numbers. We are going to build a simple dimmer
with a potentiometer which would set LED brightness. First of all, we need a
Lets use few nodes that operate on numbers. We are going to build a simple
dimmer with a potentiometer that sets LED brightness. First of all, we need a
circuit:
![Pot and LED circuit](./pot-led.fz.png)
We would like to control LED brightness, so make sure to connect the LED to a
port with PWM feature available. They are marked with tilda (~). And since the
potentiometer provides analog values its port should be capable of reading
analog signals. Ports marked A0 through A5 are good choise for that.
We would like to control LED brightness, so be sure to connect the LED to a
port that supports PWM. They are marked with a tilda (~). Because the
potentiometer provides analog values, its port must be capable of reading
analog signals. Ports marked A0 through A5 are a good choice for that.
Then create new project with main menu: File → New Project. Name it
`pot-led-dimmer` or something like that. Add nodes and links to get a program
that looks like one below:
Then create a new project from the main menu: File → New Project. Name it
`pot-led-dimmer` or something like that. Add nodes and links to create a
program that looks like the one below:
![Pot and LED patch](./pot-led.patch.png)
We use `pwm-output` from `xod/core` to provide PWM signal to our LED.
The `DUTY` input defines duty cycle. Value 0.0 denotes always-low signal
(LED is off), 0.33 is for 33% cycle (third of full brightness), 0.5 is for
50% brightness, etc up to 1.0 for always-high signal when LED is 100% on.
We use `pwm-output` from `xod/core` to provide a PWM signal to our LED. The
`DUTY` input defines the duty cycle. The value 0.0 denotes the always-low
signal (LED is off), 0.33 is for a 33% cycle (one-third of full brightness),
0.5 is for
50% brightness, etc. up to 1.0 for the always-high signal when the LED is 100%
on.
Make sure to set `PORT` input value to 3 with Inspector.
Be sure to set the `PORT` input value to 3 with Inspector.
Next, we use `analog-input` from `xod/core` to read values from potentiometer.
Read values are available on its output `SIG` and take value 0.0 for one edge
point of potentiometer, 1.0 for another, and fractional values for anything
Next we use `analog-input` from `xod/core` to read values from the
potentiometer. Read values are available on its output `SIG` and take the value
0.0 for one of the potentiometer's limits, 1.0 for the other, and fractional
values for anything
between them.
For `PORT` value of `analog-input` use value 14 which corresponds to pin A0
on the board.
For the `PORT` value on the `analog-input`, use value 14 which corresponds to
pin A0 on the board.
<div class="ui segment">
<p>
<span class="ui ribbon label">XOD T0D0</span>
Currently ports are represented as simple numbers. So you cant enter value
Ports are currently represented as simple numbers. So you cant enter a value
like `A0` directly. Just remember that A0 is 14 behind the scenes, A1 is 15,
A2 is 16, etc.
</p>
@@ -65,90 +71,100 @@ A2 is 16, etc.
<p>This inconvenience will be fixed in future versions of XOD.</p>
</div>
We need some source of pulses that would kick `analog-input` to update readings.
Again, `clock` would help. Set its `IVAL` to 0.02 seconds. That would give us
50 Hertz refresh rate.
We need some source of pulses that will kick `analog-input` to update its
readings.
The `clock` node will help here. Set its `IVAL` to 0.02 seconds. That would
give us a 50 Hertz refresh rate.
Now note that we have `SIG` output of our potentiometer linked to `DUTY` input
of our LED. They both operate on *number type* in range from 0.0 to 1.0, so no
Now note that we have the `SIG` output of our potentiometer linked to the
`DUTY` input of our LED. They both operate on a *number type* in the range from
0.0 to 1.0, so no
conversions are necessary and we link them directly.
Finally, our program reads like this:
Our program now runs like this:
- On boot the clock is set up;
- Every 20 ms the clock kicks the analog input with potentiometer causing it
to read value again;
- The value is feed to PWM output with LED causing it to update its brightness.
- On boot, the clock is set up;
- Every 20 ms the clock kicks the analog input with the potentiometer, causing
it to read the value again;
- The value is fed to the PWM output with the LED, causing it to update its
brightness.
Upload the program to your board and checkout the result.
Upload the program to your board and check out the result.
Compare to convert between numbers and booleans
-----------------------------------------------
Lets modify our device a bit so that it would work as a smart light. It should
turn on when its too dark and turn off when its bright enough. For this were
going to replace the potentiometer with simple LDR-based voltage divider:
Lets slightly modify our device to make a smart light. It should turn on
when its too dark and turn off when its bright enough. To do this,
were going to replace the potentiometer with a simple LDR-based voltage
divider:
![LDR and LED circuit](./ldr-led.fz.png)
Now our A0 port provides number values which correspond to ambient light
brightness. We should define a threshold value and if the value is under it, the
LED should be on, otherwise it should be off. So we should map a number value to
a boolean value somehow.
Now our A0 port provides number values that correspond to the brightness of the
ambient light. We should define a threshold value: if the value is under the
threshold, the
LED should be on; otherwise it should be off. So we need to somehow map a
number value to a boolean value.
A common way to do this is using comparison nodes `less`, `greater`, `equal` from
`xod/core`. Lets do it:
This is commonly done using the comparison nodes `less`, `greater`, `equal`
from `xod/core`. Lets do it:
![LDR and LED patch](./ldr-led.patch.png)
The `less` node compares two numbers on left hand side (`LHS`) and right hand side
(`RHS`) and outputs true iff `LHS` < `RHS`. Set `RHS` to a constant value using
Inspector. An exact value depends on characteristics of the resistors and desired
darkness threshold. You could experiment a bit with it. 0.5 could work fine as a
start value.
The `less` node compares the two numbers on the left hand side (`LHS`) and the
right hand side (`RHS`) and outputs true iff `LHS` < `RHS`. Set `RHS` to a
constant value using
Inspector. The exact value depends on characteristics of the resistors and
desired darkness threshold. You could experiment a bit with it. 0.5 should work
fine as a
starting value.
Upload the program. Make sure the LED is off when device starts. If not, adjust the
threshold value. Then cover the LDR with your hand to simulate darkness, the LED
Upload the program. Make sure the LED is off when the device starts. If not,
adjust the threshold value. Then cover the LDR with your hand to simulate
darkness. The LED
should turn on.
Look at the program again. Notice that we dont tell our LED to turn off if
some condition met, then turn off if another computation gave us some value.
Instead we hard-wire pins of our nodes making the behavior explicit and easy
to reason about. Thats what differentiates functional/reactive paradigm of XOD
some condition met and then turn off against based on another computation.
Instead, we hard-wire our node's pins, making the behavior explicit and easy
to understand. Thats what differentiates XOD's functional/reactive paradigm
from conventional programming like C.
String type
-----------
Now you are familiar with pulses, booleans, and numbers. XOD also provides string
type. Strings are used to represent pieces of textual data. They could represent
single or multiple lines, or they could even be empty.
Now you are familiar with pulses, booleans, and numbers. XOD also provides a
string type. Strings are used to represent pieces of textual data. They may
represent single or multiple lines, and can even be empty.
`"Hello world!"` is a string, `""` is an empty string, `"0.42"` is a string too,
although it contains only numeric characters and looks like a number at a first sight.
`"Hello world!"` is a string. `""` is an empty string. `"0.42"` is a string
too, though it contains only numeric characters and looks like a number at a
first sight.
Lets improve our device to show the lightness level on LCD screen. Use any
widespread text LCD to build circuit like one below:
Lets improve our device to show the lightness level on an LCD screen. Use
any popular text LCD to build a circuit like one below:
![LDR, LED, and LCD circuit](./ldr-led-lcd.fz.png)
Add `text-lcd-16x2` node from `xod/common-hardware`. And give it the value of
`analog-input` as an input for the first line (`L1`). Link output of the `less` node
Add the `text-lcd-16x2` node from `xod/common-hardware` and give it the value
of `analog-input` as an input for the first line (`L1`). Link the output of the
`less` node
to the `L2` input.
![LDR, LED, and LCD patch](./ldr-led-lcd.patch.png)
Now upload the program to the board. See how the data is displayed and updated as
you cover the sensor.
Now upload the program to the board. See how the data is displayed and updated
as you cover the sensor.
Note that `L1` and `L2` inputs of the LCD expect string type values. And we linked
number and boolean values to them. This is possible because automatic conversion
from any type to string is possible. Although the inverse isnt true.
Note that the LCD's `L1` and `L2` inputs expect string values, but we linked
number and boolean values to them. This is possible because any type can be
automatically converted to a string. The reverse isnt true.
Whats next
-----------
If youre going to build a project that is more complex than trivial, the program
created on a single pane would be too complicated. There is a mechanism in XOD that
allows you to easily create your own nodes from existing. Learn how to do it
in [Patch Nodes](../patch-nodes/) chapter.
If youre going to build a project that is more complex than trivial, a
program created on a single patch would be too complicated. XOD has a mechanism
that lets you easily create your own nodes from existing nodes. Learn how to do
it in the [Patch Nodes](../patch-nodes/) chapter.

View File

@@ -5,82 +5,85 @@ title: Installing and Running XOD
Installing and Running XOD
==========================
To work with XOD you would use XOD integrated development environment
(IDE for short). It comes in two flavors: browser-based version and
desktop version.
To work with XOD, you use the XOD integrated development environment (IDE for
short), which comes in two flavors: browser-based and desktop version.
Browser-based IDE
-----------------
You can start [browser-based XOD IDE](/ide/) just by visiting the link.
However, since browser has few access permissions to computers file system and
You can start the [browser-based XOD IDE](/ide/) simply by visiting the link.
However, because the browser has relatively few permissions to access the
computers file system and
USB-ports, its capabilities are quite limited.
Notably you cant upload your program directly to the board from within browser
and you wouldnt get convenient save/load functionality.
Notably, you cant upload your program directly to the board from within your
browser and you won't get the convenient save/load functionality.
Although, you can import/export your programs as a single file (so called xodball)
and generate source code that you could copy and paste into Arduino IDE and then
upload it to the board via Arduino IDE.
However, you can import/export your programs as a single file (known as a
xodball), generate source code that you could copy and paste into an Arduino
IDE, and then upload it to the board via the Arduino IDE.
Desktop IDE
-----------
XOD IDE for desktop requires installing but provides all features. It works on
Windows, macOS, and Linux. Find a distributive for your system on
XOD IDE for desktop requires installing, but provides all features. It works on
Windows, macOS, and Linux. Find a distribution package for your system on
[downloads page](/downloads/).
Upload your first program
-------------------------
Once you start XOD IDE youll see `welcome-to-xod` project open. Its a primitive
demo project that—yes, you guess it—blinks a LED on the board.
Once you start XOD IDE, youll see the `welcome-to-xod` project open. Its
a primitive demo project that—yes, you guessed it—blinks a LED on the board.
![XOD main window](./main-window.png)
Lets try to upload the program to your Arduino.
Let's try to upload the program to your Arduino IDE.
In main menu go to Deploy → Show Code for Arduino. Youll see much of C++ source code
that once compiled and uploaded to the board would blink built-in LED. If you have
Arduino IDE installed, try it, copy-paste the code to Arduino IDE and click Upload.
In the main menu, go to Deploy → Show Code for Arduino. Youll see much of
C++ source code that once compiled and uploaded to the board will blink the
built-in LED. If you have the Arduino IDE installed, try it. Copy and paste the
code to the Arduino IDE and click Upload.
<div class="ui segment">
<span class="ui ribbon label">Note</span>
If youve previously seen what code to blink a LED looks like for Arduino, you could
be astonished looking at the amount of code given by XOD. Dont worry, most of it is
a code of XOD runtime environment which actually give little overhead after compilation.
And you havent to understand how it actually works. For now think about it as
of black box.
If youve previously seen what code to blink an LED looks like for Arduino,
you might be astonished looking at the amount of code produced by XOD. Dont
worry - most of it is code for the XOD runtime environment, which actually
creates little overhead after compilation.
You don't need to understand how it actually works. For now, think of it as a
black box.
</div>
Upload directly from within XOD IDE
Upload directly from within the XOD IDE
-----------------------------------
The feature is only available in desktop version. Go to Deploy → Upload to Arduino.
Select your board model and serial port it is connected to:
This feature is only available in the desktop version. Go to Deploy → Upload
to Arduino. Select your board model and the serial port it is connected to:
![XOD model/port dialog](./board-selection.png)
Click Upload. Hold on.
Click Upload and wait.
Behind the scenes XOD uses Arduino IDE to compile and upload programs. So if
you have no Arduino IDE installed yet, youll be asked to download and install
it. Arduino IDE itself has package system to support various boards. If a package
to support your board is not installed yet, it would be automatically installed
as well.
Behind the scenes, XOD uses the Arduino IDE to compile and upload programs. So
if you have no Arduino IDE installed yet, youll be asked to download and
install it. The Arduino IDE itself has a package system to support various
boards. If a package supporting your board is not installed yet, it will also
be automatically installed.
If upload succeeds youll see 100% progress and a message from compiler:
If the upload succeeds, youll see 100% progress and a compiler message:
![XOD upload window](./upload.png)
<Feedback>
If you have a problem with upload, please report about it on our
[forum](//forum.xod.io). Describe what you do, what you expect to get, and
what you actually get. We will help.
</Feedback>
<div class="ui segment">
<span class="ui ribbon label">Feedback</span>
If you have a problem with uploading, please report it on our
[forum](//forum.xod.io). Describe what you're doing, what you expect to get,
and what you actually get. We will help.
</div>
Whats next
-----------
Now, when you can run IDE and upload programs, lets try to understand how and
why they work. Follow to [Nodes and Links](../nodes-and-links/) chapter.
Now that you can run the IDE and upload programs, let's try to understand how
and why they work. Go to the [Nodes and Links](../nodes-and-links/) chapter.

View File

@@ -5,9 +5,9 @@ title: Nodes and Links
Nodes and Links
===============
Now lets look closely on the demo project which opened up on IDE start. It
blinks the LED connected to pin 13 of your board. Although many boards have
a built-in LED on that pin, lets make it more visible by building a simple
Now lets look closely at the demo project that opened up when you started
the IDE. It blinks the LED connected to pin 13 of your board. Many boards have
a built-in LED on that pin, but lets make it more clear by building a simple
circuit:
![LED on pin 13](./led-on-pin-13.fz.png)
@@ -20,9 +20,9 @@ Why does it blink?
The nodes
---------
You see four *nodes* linked together in a chain to make this possible.
Nodes are basic building blocks in XOD. Each of them make a tiny portion
of work and communicate to others.
You see four *nodes* linked together in a chain to implement the blinking.
Nodes are basic building blocks in XOD. Each of them handles a tiny portion of
work and communicates with other nodes.
![Blink patch](./blink.patch.png)
@@ -30,83 +30,84 @@ Lets talk about each node one by one from bottom to top.
### digital-output
This node represents a single physical pin on the board that is used
as an output, and can be either in high (enabled) or low (disabled)
state. We use it to switch our LED on and off.
This node represents a single physical output pin on the board. It can be
either in a high (enabled) or low (disabled) state. We use it to switch our LED
on and off.
The node has three *inputs*. They are `PORT`, `SIG`, and `UPD`.
The `PORT` defines what physical pin corresponds to the node. Select
the node by clicking on it. Youll see *Inspector* sidebar with
properties related to the selected node, i.e. our `digital-output`.
The `PORT` defines what physical pin corresponds to the node. Select the node
by clicking on it. Youll see the *Inspector* sidebar with the properties of
the selected node, i.e. our `digital-output`.
![Inspector](./inspector.png)
Note that `PORT` value is set to 13th pin.
Note that the `PORT` value is set to 13th pin.
Value on `SIG` input defines wether the digital output port should
go high or low state. In Inspector you see its value disabled with
placeholder “linked”. Thats fine because the value is defined by
an upstream node it is linked to. More on that later.
The value on the `SIG` input defines whether the digital output port should go
into a high or low state. In the Inspector, you see its value is disabled and
has the placeholder “linked”. Thats fine, because the value is defined
by a linked upstream node. More on that later.
Input `UPD` listens for *pulses* and used to actually update the signal and
physically update the physical pin according to `SIG` value. In other
words updating `SIG` value alone is not enough and wouldnt lead to any
The `UPD` input listens for *pulses*, uses them to actually update the signal,
and physically updates the physical pin according to the `SIG` value. In other
words, updating the `SIG` value alone is not enough and wouldnt lead to any
visible results.
<div class="ui segment">
<span class="ui ribbon label">Note</span>
<p>Although it could look excessive and strange at first, but <em>any</em> update in
the XOD program is accompanied by pulses. Theyre like heartbeat which delivers
all updates to their destinations. No pulses, no observable effects.</p>
<p>Although it might seem excessive and strange at first, <em>any</em> update
in a XOD program is accompanied by pulses. Theyre like a heartbeat that
delivers all updates to their destinations. No pulses, no observable
effects.</p>
<p>Splitting actual values and pulses helps to understand what and when could
ever happen. That makes programs more explicit and reliable.</p>
<p>Keeping actual values and pulses separate makes it easier to understand what
may happen and when. It makes programs more explicit and reliable.</p>
</div>
Finally, the `digital-output` node listens for pulses on its `UPD` pin and
once it get a pulse, it sets physical port 13 (`PORT`) to a state defined
by a value on the pin `SIG` at the moment when the pulse was recieved.
Finally, the `digital-output` node listens for pulses on its `UPD` pin. Once it
get a pulse, it sets physical port 13 (`PORT`) to a state defined by the value
on the `SIG` pin at the moment when the pulse was received.
### flip-flop
This node is like a virtual light switch that could be turned on (`SET`),
turned off (`RST`) or inverted to an opposite state (`TGL`).
This node is like a virtual light switch that can be turned on (`SET`), turned
off (`RST`) or toggled (`TGL`).
In addition to its inputs the `flip-flop` has two *outputs*. They are
`MEM` which provides current state (high or low) and `CHNG` which sends a
pulse right when value of `MEM` changes.
In addition to its inputs, the `flip-flop` node has two *outputs*. They are
`MEM`, which provides the current state (high or low), and `CHNG`, which sends
a pulse when the value of `MEM` changes.
### clock
The `clock` node emits a pulse on `TICK` output over equal periods of time.
The period is defined by the value of `IVAL` input.
The `clock` node emits a pulse on its `TICK` output at equal time intervals.
The interval is defined by the value of the `IVAL` input.
Select the `clock` node and note the value set for `IVAL` in Inspector.
The interval is set up in seconds.
The interval is expressed in seconds.
The second input `RST` accepts pulses. On pulse the clock accept new interval
value and start counting from scratch.
The second input, `RST`, accepts pulses. On each pulse, the clock accept a new
interval value and starts counting from zero.
Clock is a very usual source of pulses. Youd use it quite often to drive
updates in your programs.
The clock node is a very common source of pulses. Youll use it quite often
to drive updates in your programs.
### boot
The `boot` node is very simple. It sends a single pulse when program starts,
i.e. when the board gets powered on, resetted or reflashed.
The `boot` node is very simple. It sends a single pulse when the program
starts, i.e. when the board gets powered on, reset, or flashed.
<div class="ui segment">
<span class="ui ribbon label">Hint</span>
<p>If pulses are heartbeats, then the clock is a heart. And the boot is a
<p>If pulses are heartbeats, then the clock is a heart. And the boot node is a
defibrillator that starts the clock-heart.</p>
</div>
The links
---------
You see that inputs and outputs of the nodes are connected together with lines.
These lines are called *links* in XOD.
You see that nodes' inputs and outputs are connected together with lines. These
lines are called *links* in XOD.
![Blink patch](./blink.patch.png)
@@ -115,13 +116,13 @@ values and downstream nodes consume that values.
What happens in our blink program? Take a look:
1. The `boot` node emits a pulse on program start
1. The `boot` node emits a pulse when the program starts.
2. The pulse goes to the `clock` node which start to tick at regular intervals
3. Each tick pulse goes to the `flip-flop` and toggles its state
4. The `flip-flop` provides its state value to the `digital-output` and asks
it to actually update by sending a pulse on each state update.
4. The `flip-flop` provides its state value to the `digital-output` and asks it
to update by sending a pulse each time the `flip-flop` changes state.
As a final result we see the LED blinking.
As a result, we see the LED blinking.
Tweaking the program
@@ -129,35 +130,37 @@ Tweaking the program
Try to change something.
Select the `clock` node and set another `IVAL` value. Say, set it to 1.0 seconds,
Select the `clock` node and set a different `IVAL` value, e.g. 1.0 second,
upload the updated program and observe the result.
Thats not too interesting. Lets add another LED. Improve your circuit:
![LED on pin 13 and 12](./led-on-pin-13-and-12.fz.png)
Place new node of type `digital-output`. To do this use Project Browser sidebar.
The `digital-output` is available in `xod/core` library. Hover the cursor over
the item and click on (+).
Place a new `digital-output` node. To do this, use the Project Browser sidebar.
The `digital-output` node is available in the `xod/core` library. Hover the
cursor over the item and click the (+).
![Project Browser](./project-browser.png)
Youll see new node appeared in the main work area. Drag it to a slot you want.
The one next to existing `digital-output` would be fine. In Inspector set `PORT`
for the new node to 12 since it should control our new LED.
Youll see a new node appear in the main workspace. Drag it to the slot you
want. The one next to the existing `digital-output` would be fine. In
Inspector, set the `PORT` for the new node to 12, since it will control our new
LED.
Now we need to provide the new node with data. Link its `SIG` and `UPD` pins to
`flip-flop` outputs:
the `flip-flop` outputs:
![Blink two LEDs](./blink-two-leds.patch.png)
Upload the updated program to the board. Whoa! Both LEDs are blinking.
Now lets improve our program another bit and make the lights opposite. To do
this we should cut signal inversion into either of `digital-output` `SIG` links.
Node `not` under `xod/core` does exactly that. Delete existing link, place `not`
node and add new links so that signal from our `flip-flop` to `digital-output`
goes through it:
Now lets improve our program some more and make the lights blink
alternately. To do this, we need to add a signal inversion into either the
`digital-output` or `SIG` links.
The `not` node under `xod/core` does exactly that. Delete the existing link,
place a `not` node, and add new links so that the signal from our `flip-flop`
to the `digital-output` goes through it:
![Blink two LEDs with inversion](./blink-two-leds-inv.patch.png)
@@ -166,21 +169,22 @@ Upload the new version to the board. See the result?
Disjoint graphs and independent tasks
-------------------------------------
In XOD nodes are not required to be connected in a single network. You can build
In XOD, nodes do not have to be connected in a single circuit. You can build
two or more disjoint clusters of nodes to perform several tasks simultaneously.
Try to add yet another LED with absolutely independent blink interval and state:
Try adding yet another LED with an absolutely independent blink interval and
state:
![Blink with disjoint clusters](./blink-disjoint.patch.png)
Now we have three `digital-output`s. It could be hard to understand which one
corresponds to what LED so it would be better to give them clear labels. To set
a custom label for a node select it and provide the label via Inspector:
Now we have three `digital-output` nodes. It can be hard to understand which
node corresponds to each LED, so it would be better to give them clear labels.
To set
a custom label for a node, select it and provide the label via Inspector:
![Edit label with Inspector](./inspector-label.png)
You can provide a custom label for any node. Now the program could look more
clear:
You can provide a custom label for any node. Now the program looks clearer:
![Labeled nodes](./blink-disjoint-labeled.patch.png)
@@ -189,5 +193,6 @@ Whats next
Youve seen pins and links that carry values of different types. Some provide
logical values and some transmit pulses. They are differentiated by colors.
There are more data types in XOD. Follow to [Types and
Conversions](../data-types-and-conversions/) chapter to learn more on this topic.
XOD has even more data types. Go to the [Types and
Conversions](../data-types-and-conversions/) chapter to learn more on this
topic.

View File

@@ -5,109 +5,114 @@ title: Patch Nodes
Patch Nodes
===========
What you see in a tab of main work area is called a *patch*. In other
programming languages a XOD patch corresponds to a single source file or
module.
What you see on the tab in the main workspace is called a *patch*. A XOD patch
corresponds to a single source file or module in other programming languages.
Until now youve created single-patch programs and the patch was given name
`main` automatically for you. Creating a whole project on a single patch would
become messy once number of nodes and links will pass some limit. In many cases
it is a good idea to split complex patches into several that are easier to
understand and change.
Until now, youve created single-patch programs and the patch was
automatically named `main`. Creating a whole project in a single patch would
become messy once the number of nodes and links passed some limit. It is often
a good idea to split complex patches into several simpler patches that are
easier to understand and edit.
Furthermore, you can reuse a patch several times in your project with slightly
different parameters and in such way avoid nodes duplication.
Furthermore, you can reuse patches several times in your project with slightly
different parameters, thus avoiding node duplication.
The mechanism which lets you use one patches as nodes on other patches is
called *patch nodes*.
When you use one patch as a node in other patches it is called a *patch node*.
In this chapter were going to build simple watering station for two plants.
The idea is to water a plat if its soil became too dry and constantly show current
soil measurements on text LCD screen.
In this chapter, were going to build a simple watering station for two
plants. The idea is to water a plant if its soil became too dry and constantly
show the current
soil measurements on an LCD screen.
Single plant station on a single patch
--------------------------------------
To start lets build a device that will work with a single plant. Well use single
patch `main` as in previous chapters.
To start, let's build a device that will work with a single plant. Well use
a single patch called `main`, as in previous chapters.
Create new project `water-station` and wire up your circuit:
Create a new project called `water-station` and wire up your circuit:
![Single plant circuit](./single-plant.fz.png)
Now make a following patch to control the device:
Now make the following patch to control the device:
![Single plant patch](./single-plant.patch.png)
Make sure to properly set port values for all hardware nodes.
Be sure to set port values properly for all hardware nodes.
You may noticed it is very similar to previously implemented smart light project.
All things weve changed is the sensor and the actuator. Moisture sensor replaced
the light sensor and the pump replaced the LED.
You may have noticed it is very similar to the previously implemented smart
light project. We've only changed the sensor and the actuator. The moisture
sensor replaced the light sensor, and the pump replaced the LED.
Upload the program to your board and test the device. Put the sensor into a glass
of water and take it out. See how the relay reacts. Observe the text shown on LCD.
Upload the program to your board and test the device. Put the sensor into a
glass of water and take it out. See how the relay reacts. Observe the text
shown on the LCD.
Lets improve the program a bit and add pretty formatting to the messages. So that
instead of `"0.42"` the LCD would show something like `"Cactus: 42%"`. We achieve
this by adding two nodes. First one `to-percent` would convert number from sensor
to a string like `"42%"`. Second one `concat` would concatenate a constant prefix
`"Cactus: "` with the percent string:
Lets improve the program a bit by adding pretty formatting to the messages
so that instead of `"0.42"`, the LCD would show something like `"Cactus: 42%"`.
We achieve this by adding two nodes. First, a `to-percent` node will convert a
number from the sensor to a string like `"42%"`. Second, the `concat` node will
concatenate the constant prefix `"Cactus: "` with the percent string:
![Single plant patch with percents](./single-plant-percent.patch.png)
Extracting plant logic to a separate patch
------------------------------------------
So far, so good. Now consider we want to extend the device to handle two plants
at once. We have another sensor, yet another relay, and pump. What we want to
share is LCD. Each plants message should be shown on its own line.
So far, so good. Now consider that we want to extend the device to handle two
plants at once. We have another sensor, yet another relay, and a pump. What we
want to
share is the LCD. Each plants message should be shown on its own line.
The very staightforward way to do it would be duplicate most of nodes related to
reading data, comparing it and formatting the result. But it would quickly became
unmanagable and error prone. Changes in one place would always require mirroring
the changes in other places by hand.
The very staightforward way to do it would be to duplicate most of nodes
related to reading and comparing data, and formatting the result. But it would
quickly become unmanagable and error prone. Changes in one place would always
require manually mirroring those changes in other places.
Patch nodes to the rescue. What do we have in common between different plants and
what differs? The logic is common, but the name of the plant, its watering threshold
value differs. Ports used to connect the sensor and the relay differs too. So
these things should be provided as parameters to our patch.
Patch nodes to the rescue. What do the different plants have in common? And
what is different? The logic is common, but the name of the plant and its
watering threshold value differ. The ports used to connect the sensor and the
relay are also different. So these things need to be provided as parameters to
our patch.
What the patch could output to the outside world? It could be a status message
string and a pulse that denotes that update is completed.
What might the patch output to the outside world? It could be a status message
string and a pulse that denotes that an update is complete.
Create new patch with File → New Patch and name it `plant`. Look at Project Browser
youll see that `plant` patch has appeared next to our `main`.
Create a new patch with File → New Patch, and name it `plant`. Look at
Project Browser. Youll see that a `plant` patch has appeared next to our
`main`.
First of all were going to define its inputs and outputs. Expand
First of all, were going to define its inputs and outputs. Expand
`xod/patch-nodes` in Project Browser and notice nodes with names like
`input-xxx` and `output-xxx`. They are called *terminals* and define patch
input and output pins. Place few inputs and outputs according to what weve
`input-xxx` and `output-xxx`. They are called *terminals*, and define the
patch's
input and output pins. Place a few inputs and outputs according to what weve
planned to parametrize:
![Plant patch terminals](./plant-terminals.patch.png)
Now give the terminal nodes informative labels so that we can remember which one means
what:
Now give the terminal nodes informative labels so we can remember which one
means what:
![Plant patch terminals with labels](./plant-terminals-labeled.patch.png)
Switch back to the `main` patch. And try to add two nodes of our newly created type
`plant`:
Switch back to the `main` patch and try to add two nodes of our newly created
type `plant`:
![Patch nodes](./single-plant-with-patch-nodes.patch.png)
Were going to use these two nodes to manage plants and move existing logic to the
shared `plant` patch. Lets do it.
Were going to use these two nodes to manage plants and move the existing
logic to the shared `plant` patch. Lets do it.
<div class="ui segment">
<p><span class="ui ribbon label">XOD T0D0</span>
Currently there is no cut/copy/paste in XOD. Yes, thats a pain. Well implement it
in future versions. If you would like to give the feature more priority we welcome you to
<a href="//forum.xod.io">share your opinion on our forum</a>.</p>
Currently there is no cut/copy/paste in XOD. Yes, thats a pain. Well
implement it in future versions. If you would like to give the feature more
priority, we welcome you to <a href="//forum.xod.io">share your opinion on our
forum</a>.</p>
</div>
Here is final `main` patch:
Here is the final `main` patch:
![Main patch for two plants](./two-plants-main.patch.png)
@@ -119,12 +124,12 @@ Wire up the circuit:
![Single plant circuit](./two-plants.fz.png)
Set parameters for your plants with Inspector. Then upload the program and see how
both plants are served simultaneously with a single patch.
Set parameters for your plants with Inspector. Then upload the program and see
how both plants are served simultaneously with a single patch.
Whats next
-----------
Our quick tutorial is almost completed. The last thing to learn is what you can do
to build arbitrary projects with arbitrary hardware.
See [Complex Projects](../complex-projects/) chapter to know more.
Our quick tutorial is almost complete. The last thing to learn is what you can
do to build arbitrary projects with arbitrary hardware. See the [Complex
Projects](../complex-projects/) chapter to learn more.