mirror of
https://github.com/xodio/xod.git
synced 2026-03-22 00:26:54 +01:00
doc(docs): proofread the docs
This commit is contained in:
@@ -5,63 +5,64 @@ title: Data Types
|
||||
Data Types
|
||||
==========
|
||||
|
||||
In XOD any pin have a data type. Data values are transfered along links
|
||||
between nodes allowing them to work together on a whole job.
|
||||
In XOD, every pin has a data type. Data values are transfered along links
|
||||
between nodes, allowing them to work together to a perform a job.
|
||||
|
||||
This is very much like signals of ICs in electronics. Although signals in
|
||||
hardware are quite limited in the sense what data they could carry. They are
|
||||
simply voltage with a value somewhere between zero volts and few volts. To
|
||||
express meaningful values like numbers various tricks are used. For example,
|
||||
one could map voltage to a value with a logarithmic scale, or consider the
|
||||
voltage a series of 0’s and 1’s arriving at predefined rate, then group them by
|
||||
eight and convert into bytes.
|
||||
This is very much like integrated circuits’ signals in electronics, though
|
||||
hardware signals are quite limited as to what data they can carry. They are
|
||||
simply voltages with a value somewhere between zero volts and few volts.
|
||||
Various tricks are used to express meaningful values like numbers. For example,
|
||||
you could map voltage to a value on a logarithmic scale, or you could interpet
|
||||
the voltage as a series of 0’s and 1’s arriving at a predefined rate, and
|
||||
then convert them into bytes by grouping them into sets of eight.
|
||||
|
||||
In XOD various data types are supported natively. There is no need to use the
|
||||
XOD has native support for various data types — no need to use any
|
||||
tricks. For example, there are data types that hold arbitrary numbers or
|
||||
textual strings.
|
||||
text strings.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui ribbon label">Pro Tip</span>
|
||||
<p>Perhaps you know, there are languages with static typing (C, C++, Java,
|
||||
Haskell) and languages with dynamic typing (JS, Python, Ruby). What’s better
|
||||
is a long flamewar.</p>
|
||||
<p>You may know there are languages with static typing (C, C++, Java,
|
||||
Haskell) and languages with dynamic typing (JS, Python, Ruby). A long flamewar
|
||||
has been waged as to which is better.</p>
|
||||
|
||||
<p>XOD is in static typing camp. I.e. a pin can’t have a number value now, and a
|
||||
textual string value two seconds latter. This gives necessary knowledge to IDE
|
||||
so that it can protect you from silly mistakes.</p>
|
||||
<p>XOD is in the static-typing camp, e.g. a pin can’t have a number value
|
||||
now, and a text string value two seconds later. This lets the IDE protect you
|
||||
from silly mistakes.</p>
|
||||
</div>
|
||||
|
||||
As said above, the data type is a characteristic of a pin. You can say “Node
|
||||
FOO has output pin BAR of number type”. That means that the BAR pin
|
||||
carries a number value at any particular node. You can also say “Node FOO has
|
||||
As mentioned above, a data type is a characteristic of a pin. You can say
|
||||
“Node FOO has output pin BAR of number type”. That means that the BAR pin
|
||||
carries a number value in every FOO node. You can also say “Node FOO has
|
||||
input pin QUX of boolean type”. That means the FOO node always expects 0 or 1
|
||||
value connected to its QUX pin.
|
||||
|
||||
One important division of types in XOD is between a *pulse type* and any other
|
||||
type that are together called *value types*. All them described below.
|
||||
Importantly, XOD types are divided between *pulse types* and all other types,
|
||||
which are collectively known as *value types*. Each type is described below.
|
||||
|
||||
Pulse type
|
||||
----------
|
||||
|
||||
Pulse type is a very special type because it actually don’t carry any data on
|
||||
its own. It is only used to tell about something happened just now or something
|
||||
is required to happen right now.
|
||||
The pulse type is very special, because it doesn't actually carry any data on
|
||||
its own. It is only used to indicate that something has just happened or that
|
||||
something should happen right now.
|
||||
|
||||
Pulses are similar to clock or interrupt signals in digital electronics.
|
||||
All we’re interested in is *moments* when the signal rises to Vcc or falls to
|
||||
ground. They don’t carry any additional useful information in them.
|
||||
All we’re interested in is the *moments* when the signal rises to Vcc or
|
||||
falls to ground. They don’t carry any additional useful information.
|
||||
|
||||
A pulse signal can tell us that we’ve got a new TCP packet from network, that
|
||||
a button was pressed, that some timeout has been past. We would use a pulse
|
||||
signal to trigger SMS send or to adjust motor speed.
|
||||
A pulse signal can tell us that we’ve got a new TCP packet from the network,
|
||||
a button was pressed, or some time interval has passed. We would use a pulse
|
||||
signal to trigger an SMS send command or adjust motor speed.
|
||||
|
||||
Very often pulse signals are accompanied with other value types on neighbour
|
||||
pins. The values describe “what” whereas the pulse describes “when”.
|
||||
Pulse signals are quite often accompanied by other value types on neighboring
|
||||
pins. The values describe the “what”, while the pulse describes the
|
||||
“when”.
|
||||
|
||||
Pulses make your programs live. Without them your device would stay intact.
|
||||
Pulses give life to your programs. Without them, your device won't do anything.
|
||||
Read [Execution Model](../execution-model/) to understand this logic in detail.
|
||||
|
||||
Here are short list of nodes you’ll use a lot working with pulses:
|
||||
Here is a short list of nodes you’ll use a lot in conjunction with pulses:
|
||||
|
||||
* [`boot`](/libs/xod/core/boot/)
|
||||
* [`clock`](/libs/xod/core/clock/)
|
||||
@@ -71,13 +72,14 @@ Here are short list of nodes you’ll use a lot working with pulses:
|
||||
Boolean type
|
||||
------------
|
||||
|
||||
Boolean value can be either *true* or *false*. You can also think of it as a
|
||||
choice between of one/zero, yes/no, on/off, high/low, enabled/disabled.
|
||||
Boolean values can be either *true* or *false*. Alternatively, you can think of
|
||||
them as a choice between of one/zero, yes/no, on/off, high/low, or
|
||||
enabled/disabled.
|
||||
|
||||
Logical values are ubiquitous. They are enough to express values of simple
|
||||
Logical values are ubiquitous. They are adequate to implement simple
|
||||
digital sensors (is a button pressed or not?), control simple actuators (should
|
||||
a relay close?), and carry results of logical operations (is temperature
|
||||
greater than 25°?).
|
||||
a relay close?), and carry the results of logical operations (is the
|
||||
temperature greater than 25°?).
|
||||
|
||||
Here are short list of nodes you’ll use a lot working with logical values:
|
||||
|
||||
@@ -89,20 +91,20 @@ Here are short list of nodes you’ll use a lot working with logical values:
|
||||
Number type
|
||||
-----------
|
||||
|
||||
Numbers are widespread. The numeric data type is used to transfer sensors’
|
||||
measured values, set speed of motors, perform arithmetical computations,
|
||||
comparisons and so on.
|
||||
Numbers are everywhere. The number data type is used to transfer sensor
|
||||
readings, set motor speeds, perform arithmetic computations and
|
||||
comparisons, and so on.
|
||||
|
||||
Number type values in XOD can represent fractional numbers, positive and
|
||||
Number values in XOD can be fractional numbers and positive and
|
||||
negative infinity.
|
||||
|
||||
Precision and most extremal representable values depend on capabilities of a
|
||||
target platform. In any case it would be enough to operate on numbers with
|
||||
six significant digits in range ±10<sup>38</sup>.
|
||||
Precision and the range of representable values depend on the capabilities of
|
||||
the target platform. In any event, the number type is enough to operate on
|
||||
numbers with six significant digits in range ±10<sup>38</sup>.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui ribbon label">Pro Tip</span>
|
||||
The underlying type for numerical values is IEEE 754 floating point with
|
||||
The underlying format for number values is IEEE 754 floating point with
|
||||
single or double precision. It depends on a target platform.
|
||||
</div>
|
||||
|
||||
@@ -120,54 +122,56 @@ Here are some nodes you’ll use to work with numbers:
|
||||
|
||||
### Unit ranges
|
||||
|
||||
Many nodes use numbers in range from 0 to 1. It is handy if the value denote
|
||||
some kind of percentage. For example, a potentiometer node
|
||||
uses 0.0 to denote leftmost washer position, 0.5 to denote middle position,
|
||||
and 1.0 to express rightmost position.
|
||||
Many nodes use numbers in the range from 0 to 1. This is convenient if the
|
||||
value denotes some kind of percentage. For example, a potentiometer node
|
||||
uses 0.0 to denote the leftmost washer position, 0.5 to denote the middle
|
||||
position, and 1.0 to denote the rightmost position.
|
||||
|
||||
Another example is an LED node. 0.0 is used to turn it off, 0.33
|
||||
to emit 33% brightness and 1.0 to turn on at maximum brightness.
|
||||
to emit 33% brightness and 1.0 to turn on it at maximum brightness.
|
||||
|
||||
Some nodes use ranges from -1 to 1. E.g. motor node use -1 for
|
||||
full backward, -0.2 for 20% backward, 0 to stop and 1 to run full forward.
|
||||
Some nodes use ranges from -1 to 1. For example, a motor node use -1 for
|
||||
full backward, -0.2 for 20% backward, 0 to stop, and 1 to run full forward.
|
||||
|
||||
Unit ranges are easy to operate with although they’re purely conventional.
|
||||
It’s up to a node implementation to decide what to do if an input value falls
|
||||
out of the range. Usually they’ll clamp the input to a desired range.
|
||||
Unit ranges are convenient to use, but entirely unnecessary.
|
||||
It’s up to a node's implementation to decide what to do if an input value
|
||||
falls out of the range. A common behavior is to clamp the input to the desired
|
||||
range.
|
||||
|
||||
String type
|
||||
-----------
|
||||
|
||||
Strings represent pieces of text like “Hello World!”.
|
||||
|
||||
Unlike some languages where strings are threated specially in XOD it’s just a
|
||||
list of bytes. Thus it’s up to you to control text encoding. You can choose
|
||||
ASCII, UTF-8 or old-school CP-1252 for storage. What would work best depends
|
||||
on capabilities of hardware modules and data transfer formats you work with.
|
||||
Unlike some languages that give strings special treatment, XOD considers them
|
||||
to be just a list of bytes. Thus it’s up to you to manage text encoding. You
|
||||
can choose ASCII, UTF-8, or old-school CP-1252 for storage. The best choice
|
||||
depends on the hardware modules and data transfer formats you work with.
|
||||
|
||||
Computers don’t like text actually, but humans are. You’ll use text to parse a
|
||||
high-level input like SMS or tweet and to present values back to human on
|
||||
display or via some web-service.
|
||||
Computers don’t actually like text, but humans do. You’ll use text to parse
|
||||
high-level input like an SMS or tweet, and display values to humans, or send
|
||||
them via some web-service.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui red ribbon label">XOD T0D0</span>
|
||||
All types described below are not yet implemented in XOD. For now, it’s just
|
||||
a description of how things <em>could</em> look like in future. We’re welcome you
|
||||
to the <a href="//forum.xod.io">discussion on our forum</a>. Here you can
|
||||
affect the design decisions.
|
||||
The types described below are not yet implemented in XOD. For now, we'll just
|
||||
describe how things <em>could</em> look in future. We invite you
|
||||
to join the <a href="//forum.xod.io">discussion on our forum</a>. You could
|
||||
affect our design decisions.
|
||||
</div>
|
||||
|
||||
Integer type
|
||||
------------
|
||||
|
||||
Although in many cases number type is enough to process numerical values,
|
||||
sometimes it’s more preferrable to work on integer type.
|
||||
Although the number type is often enough to process numeric values,
|
||||
sometimes it’s preferrable to work with an integer type.
|
||||
|
||||
It have no problems with precission loss, operated faster by processors and
|
||||
have much more sense for some functions such as as getting a substring from
|
||||
Integers have no problems with precision loss, are processed faster, and
|
||||
make much more sense for some purposes, such as as getting a substring from
|
||||
a string at a particular index and of a particular length.
|
||||
|
||||
Integer values can represent integral values from rougly ±2 milliards range.
|
||||
The integer type can represent integral values in the range of rougly ±2
|
||||
billion.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui ribbon label">Pro Tip</span>
|
||||
@@ -177,79 +181,79 @@ The underlying type for integer values is a signed 32-bit integer.
|
||||
Byte type
|
||||
---------
|
||||
|
||||
Bytes are fundamental building blocks of low-level computing. Many hardware
|
||||
peripherals send or consume series of bytes to interact with a controller.
|
||||
Bytes are the fundamental building blocks of low-level computing. Many hardware
|
||||
peripherals send or consume a sequence of bytes to interact with a controller.
|
||||
|
||||
In XOD byte is a distinct data type that is used to perform low-level
|
||||
operations. It can’t be interchanged with other types directly. You’ll
|
||||
use some conversion nodes to convert byte values to more useful types and
|
||||
back. They are:
|
||||
In XOD, a byte is a distinct data type that is used to perform low-level
|
||||
operations. It can’t be directly interchanged with other types. You’ll
|
||||
use some conversion nodes to convert byte values to and from more useful types
|
||||
such as:
|
||||
|
||||
Tuples
|
||||
------
|
||||
|
||||
Tuples are simply groups of other values with a predefined order and size.
|
||||
|
||||
Say, `Tuple3 Number Number Number` could be used to denote a point in 3D-space.
|
||||
In that case it would contain X at first position, Y at second, and Z at
|
||||
third.
|
||||
For example, `Tuple3 Number Number Number` could be used to denote a point in
|
||||
3D-space. In that case, it would contain X in the first position, Y in second,
|
||||
and Z in the third.
|
||||
|
||||
Or `Tuple2 Byte Integer` could be used to describe a message for a particular
|
||||
I²C chip.
|
||||
Or `Tuple2 Byte Integer` could be used to encode a message for a particular IC
|
||||
chip.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui ribbon label">Pro Tip</span>
|
||||
If you’re familar with C or Arduino think of tuples as of structs in which
|
||||
If you’re familar with C or Arduino, think of tuples as structs whose
|
||||
members are accessed by their index rather than by their name.
|
||||
</div>
|
||||
|
||||
You can easily pack and unpack single values to or from tuples using following
|
||||
nodes:
|
||||
You can easily pack and unpack single values to and from tuples using the
|
||||
following nodes:
|
||||
|
||||
Lists
|
||||
-----
|
||||
|
||||
Lists are sequences of values of a particular type. Unlike tuples their length
|
||||
is not predefined: they could grow or shrink as program goes. And they can only
|
||||
contain values of a single type.
|
||||
Lists are sequences of values of a particular type. Unlike tuples, their length
|
||||
is not predefined: they can grow or shrink as the program runs. And they can
|
||||
only contain values of a single type.
|
||||
|
||||
For example:
|
||||
- `List Number` can represent a history of temperature readings
|
||||
- `List Byte` can be a packet to send or receive from the network
|
||||
- `List (Tuple Number Number Number)` can represent a trajectory for a robotic
|
||||
hand as a sequence of points in 3D-space.
|
||||
- `List (List Number)` represents a 2D-table of numbers with dynamic size.
|
||||
- `List Byte` might be a packet to send or receive from the network
|
||||
- `List (Tuple Number Number Number)` could represent the trajectory of a
|
||||
robotic hand as a sequence of points in 3D-space.
|
||||
- `List (List Number)` represents a dynamically-sized 2D-table of numbers.
|
||||
|
||||
Common operations on lists include:
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
Error is not an independent type per se. It rather augments other types with
|
||||
special values to denote errors in computations.
|
||||
Error is not an independent type per se. Instead, it augments other types with
|
||||
special values to denote computational errors.
|
||||
|
||||
For example, a division of an integer on zero would result in error value
|
||||
rather than integer value. The same way an attempt to get an element from
|
||||
For example, dividing an integer by zero would result in error value
|
||||
rather than integer value.Similarly, an attempt to get an element from
|
||||
an empty list would result in another error value.
|
||||
|
||||
Error values are viral. Once a functional node gets an error value on one of
|
||||
its inputs all it outputs get error values too.
|
||||
|
||||
There are few nodes that you would use to generate your own errors and
|
||||
to handle potentially error’ish values.
|
||||
There are few nodes that you would use to generate your own errors and handle
|
||||
potential errors.
|
||||
|
||||
Casting rules
|
||||
-------------
|
||||
|
||||
What should happen if a pin of one type is connected to a pin of another
|
||||
type? Some combinations are forbidden and you’ll get an error if try to link
|
||||
two pins of these types. Other combinations are valid and *casting* between two
|
||||
is done behind the scenes.
|
||||
type? Some combinations are forbidden and you’ll get an error if you try to
|
||||
link such pins. Other combinations are valid, and values are *cast* from one
|
||||
type to another.
|
||||
|
||||
In many cases you would like to convert a signal value from one type to
|
||||
another. I.e. to link a pin with one type to a pin of another type.
|
||||
It is often desirable to convert a signal value from one type to
|
||||
another, i.e. to link a pin with one type to a pin of another type.
|
||||
|
||||
For some type pairs this is possible without any intermediate conversion
|
||||
For some type pairs, this is possible without any intermediate conversion
|
||||
nodes:
|
||||
|
||||
<table class="ui definition single line table">
|
||||
@@ -278,7 +282,7 @@ nodes:
|
||||
<td></td>
|
||||
<td class="disabled">use nodes</td>
|
||||
<td class="disabled">use nodes</td>
|
||||
<td>3.14159 →<br/>"3.14"<br/>(two digits<br/>after dot)</td>
|
||||
<td>3.14159 →<br/>"3.14"<br/>(two digits<br/>after decimal)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Integer →</td>
|
||||
@@ -307,7 +311,7 @@ nodes:
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Other convertions can’t always be done unambigously thus are not allowed.
|
||||
Other convertions can’t always be done unambigously and thus are not allowed.
|
||||
Use additional nodes to make casting explicit in such cases:
|
||||
|
||||
* [`format-number`](/libs/xod/core/format-number/)
|
||||
@@ -316,25 +320,25 @@ Use additional nodes to make casting explicit in such cases:
|
||||
### List lifting
|
||||
|
||||
There are times when we have an output of a particular type `T` and an
|
||||
input of corresponding list type `List T`. Or vice versa. Conceptually
|
||||
input of the corresponding list type `List T`. Or vice versa. Conceptually,
|
||||
these are two very different types. However, XOD can make an implicit
|
||||
cast to link them properly. This transformation is known as “lifting”.
|
||||
|
||||
If a value of type `T` is connected to an input of type `List T`, the
|
||||
value is considered to be a single element list with that value on
|
||||
first position. E.g. `42` becomes `[42]`.
|
||||
value is considered to be a single element list with that value in
|
||||
the first position, i.e. `42` becomes `[42]`.
|
||||
|
||||
Vice versa, if a value of type `List T` is connected to an input of type `T` in
|
||||
of a functional node that node *maps* each element of the list and its result
|
||||
value gets list type. E.g. a node [absolute](/libs/xod/core/absolute/) that is
|
||||
usually operate on single numbers given a list `[-1, 2, 3, -4, -5]` would have
|
||||
`[1, 2, 3, 4, 5]` as a result.
|
||||
Conversely, if a value of type `List T` is connected to an input of type `T` in
|
||||
a functional node, the node *maps* each element of the list and the resulting
|
||||
value is a list type. For example, if `[-1, 2, 3, -4, -5]` were passed to an
|
||||
[absolute](/libs/xod/core/absolute/) node, which usually operates on single
|
||||
numbers, the result would be `[1, 2, 3, 4, 5]`.
|
||||
|
||||
If two lists given as values of two inputs of a functional node the computation
|
||||
is done element-wise. E.g. a node [add](/libs/xod/core/add/) given `[1, 2, 3]`
|
||||
for `X` and `[40, 50, 60]`
|
||||
for `Y` would output `[41, 52, 63]`.
|
||||
If two lists are given as the two inputs of a functional node, the node
|
||||
operates element-wise on the lists, i.e. given `[1, 2, 3]` for `X` and `[40,
|
||||
50, 60]` for `Y`, the [add](/libs/xod/core/add/) node would output `[41, 52,
|
||||
63]`.
|
||||
|
||||
When lists’ length differ lifting operation takes a shortest one and acts as
|
||||
all lists have the same shortest length. E.g. “add” node given `[1, 2, 3, 4]`
|
||||
and `[40, 50]` would output `[41, 52]`.
|
||||
If the lists differ in length, the lifting operation treats each of the lists
|
||||
as if it was as short as the shortest list, i.e. given `[1, 2, 3, 4]` and `[40,
|
||||
50]`, the “add” node would output `[41, 52]`.
|
||||
|
||||
@@ -1,61 +1,60 @@
|
||||
---
|
||||
title: Execution Model in Details
|
||||
title: Execution Model in Detail
|
||||
---
|
||||
|
||||
Execution Model in Details
|
||||
===========================
|
||||
Execution Model in Detail
|
||||
=========================
|
||||
|
||||
In contrast to conventional programming, XOD is a data flow language rather
|
||||
than control flow one. That means there is no such thing as an instruction
|
||||
pointer that determines what command will be executed next moment. Instead,
|
||||
updates are done in semi-instant *transactions* where all data is evaluated
|
||||
simultaneously.
|
||||
than a control flow language. That means there is no such thing as an
|
||||
instruction pointer that determines what command will be executed at the next
|
||||
moment. Instead, updates are done in semi-instantaneous *transactions* in which
|
||||
all data is evaluated simultaneously.
|
||||
|
||||
Functional and effect nodes
|
||||
---------------------------
|
||||
|
||||
There is such thing as a *function* in mathematics. Sure, you know many of them:
|
||||
There is such thing as a *function* in mathematics. You know many of them:
|
||||
|
||||
- `f(x) = sin x` is a function of single argument that returns its sine;
|
||||
- `f(r) = π × r²` is a function of single argument that returns square of a
|
||||
- `f(x) = sin x` is a unary (i.e. it takes a single argument) function that
|
||||
returns the sine of its argument;
|
||||
- `f(r) = π × r²` is a unary function that returns the area of a
|
||||
circle with given radius;
|
||||
- `f(x, y) = √(x² + y²)` is a function of two arguments that returns a distance
|
||||
from origin to a point with given coordinates;
|
||||
- `f(v₀, a, t) = v₀ × t + (a × t²) / 2` is a function of
|
||||
three arguments that returns velocity of an object at a particular moment in
|
||||
time.
|
||||
- `f(x, y) = √(x² + y²)` is a binary function (i.e. it takes two arguments)
|
||||
that returns the distance from the origin to the point (x, y);
|
||||
- `f(v₀, a, t) = v₀ × t + (a × t²) / 2` is a ternary (i.e. it takes
|
||||
three arguments) function that returns the velocity of an object at a
|
||||
particular moment in time.
|
||||
|
||||
Functions are great because they have very predictable behavior. E.g. if you’re
|
||||
computing circle square it will be always the same for the same radius. It is a
|
||||
nonsense if the result of computation today would differ from the result of
|
||||
yesterday, or if the result would change depending on other factors like
|
||||
weather outside. Furthermore computing circle square of radius 2 can’t affect
|
||||
a result of another computation, e.g. `sin 2` now or in the future.
|
||||
Functions are great, because they behave very predictably, i.e. if you’re
|
||||
computing the area of a circle, it will always be the same for the same radius.
|
||||
It would be nonsense if the computation today differed from that of yesterday,
|
||||
or if the result changed based on other factors like the weather outside.
|
||||
Furthermore, computing the area of a circle with radius 2 can’t affect the
|
||||
result of another computation, e.g. `sin 2`, now or in the future.
|
||||
|
||||
Functions are intuitive and understandable pieces that don’t involve side
|
||||
effects in computation.
|
||||
Functions are intuitive and understandable pieces that don’t have
|
||||
computational side effects.
|
||||
|
||||
<div class="ui segment">
|
||||
<p><span class="ui ribbon label">Note</span>
|
||||
Experienced programmers say that such functions are referrentially transparent,
|
||||
easy to reason about, stateless, idempotent and pure. They mean the same things
|
||||
and they love’em.
|
||||
easy to reason about, stateless, idempotent, and pure.
|
||||
</div>
|
||||
|
||||
The characteristics of functions make them ideal building blocks to compose
|
||||
complex computations. Input arguments of one function could be results of
|
||||
other functions. They in turn can get arguments from yet other functions, etc.
|
||||
The characteristics of functions make them ideal building blocks for creating
|
||||
complex computations. The results of one function can be the input arguments of
|
||||
another function, which could feed its results into yet another function, etc.
|
||||
|
||||
However, if you’re going to build a program solely from functions it would be a
|
||||
program that always do the same thing and lead to absolutely same result. It
|
||||
would not depend on user input, events in real world, or time. It would not
|
||||
affect outside world and furthermore would have no chance to present
|
||||
computation results. All because functions can’t have side effects. Thus
|
||||
another kind of building block is required.
|
||||
However, a program consisting solely from functions would always do the same
|
||||
thing and produce exactly the same result. It would not depend on user input,
|
||||
real world events, or time. It would not affect the external world or have the
|
||||
ability to display computational results. All because functions can’t have
|
||||
side effects. Thus another kind of building block is required.
|
||||
|
||||
In XOD there are two kinds of nodes available. *Functional nodes* represent
|
||||
functions. And *effect nodes* serve as interfaces to the outside world, time,
|
||||
and memory of past values.
|
||||
In XOD, there are two kinds of nodes available. *Functional nodes* represent
|
||||
functions. *Effect nodes* serve as interfaces to the external world, time, and
|
||||
memory of past values.
|
||||
|
||||
### Functional nodes
|
||||
|
||||
@@ -63,9 +62,9 @@ Functional nodes always have inputs and output pins. All pins have [value
|
||||
types](../data-types/#value). In other words functional nodes *never* have pins
|
||||
of [pulse type](../data-types/#pulse).
|
||||
|
||||
Output values depend only on values of input pins. They can’t depend on time
|
||||
(only if given as an explicit input value), on parameters of outside world, or
|
||||
on results of their past computations. Given the same set of input values they
|
||||
Output values only depend on the values at input pins. They can’t depend on
|
||||
time (unless given as an explicit input value), parameters of the external
|
||||
outside world, or past computations. Given the same set of input values, they
|
||||
always result in the same set of output values.
|
||||
|
||||
Some examples of functional nodes are:
|
||||
@@ -76,27 +75,27 @@ Some examples of functional nodes are:
|
||||
* [`or`](/libs/xod/core/or/)
|
||||
* [`format-number`](/libs/xod/core/format-number/)
|
||||
|
||||
Functional nodes affect nothing but their output values. They can’t change
|
||||
brightness of a LED or speed of a motor on their own.
|
||||
Functional nodes affect nothing but their output values. On their own, they
|
||||
can’t change the brightness of an LED or the speed of a motor.
|
||||
|
||||
<div class="ui segment">
|
||||
<p><span class="ui ribbon label">Note</span>
|
||||
If you’re an advanced Excel user think about functional nodes as of cell
|
||||
If you’re an advanced Excel user, think about functional nodes as cell
|
||||
formulas.
|
||||
</div>
|
||||
|
||||
### Effect nodes
|
||||
|
||||
Effect nodes could have just inputs, just outputs or both at once. They
|
||||
*always* have pins of pulse type. Input pulses is what drives them to perform
|
||||
effects and their output pulses is what tell us about effects that took place.
|
||||
Effect nodes can have just inputs, just outputs, or both. Their pins
|
||||
are *always* the pulse type. Input pulses drive them to perform
|
||||
effects, and output pulses tell us about effects that have taken place.
|
||||
|
||||
A result of hitting an effect node can be arbitrary. It could turn on a lamp,
|
||||
send an SMS, launch a nuke, or memoize a value for future use.
|
||||
The result of activating an effect node can be arbitrary, e.g. turn on a lamp,
|
||||
send an SMS, launch a nuke, or store a value for future use.
|
||||
|
||||
When such node would emit an output pulse is up to node implementation as well.
|
||||
It could pulse on an update from sensor, on SMS received or on timeout event,
|
||||
for example.
|
||||
The node's implementation also decides when to emit an output pulse.
|
||||
For example, a node could pulse when a sensor reading updates, an SMS is
|
||||
received, or a timeout event occurs.
|
||||
|
||||
Some examples of effect nodes are:
|
||||
|
||||
@@ -106,109 +105,110 @@ Some examples of effect nodes are:
|
||||
* [`analog-input`](/libs/xod/core/analog-input/)
|
||||
* [`pwm-output`](/libs/xod/core/pwm-output/)
|
||||
|
||||
Effect nodes is a thing that complements functional land so that your program
|
||||
could interact with a user, the world, and the time.
|
||||
Effect nodes complement functional nodes so your program can interact with
|
||||
users, the world, and time.
|
||||
|
||||
Program life cycle
|
||||
------------------
|
||||
|
||||
In any particular moment a XOD program is either in a transaction or in an idle
|
||||
state.
|
||||
At any particular moment, a XOD program is either in a transaction or in an
|
||||
idle state.
|
||||
|
||||
While being idle the system stays stable, nothing changes. A board can even
|
||||
choose to go sleep to keep battery charge longer. What makes the program go out
|
||||
of idle state is getting a new pulse from an effect node. It could be a pulse
|
||||
from system clock or a sensor, for example.
|
||||
While idle, the system remains stable, nothing changes. A board can even
|
||||
choose to go to sleep to preserve the battery. Receiving a new pulse from an
|
||||
effect node, e.g. a system clock or sensor, is what makes the program leave the
|
||||
idle state.
|
||||
|
||||
A pulse cause the program to enter a new *transaction*. The pulse flows along
|
||||
links downstream and cause nodes it hits to update. Node update process is
|
||||
called *evaluation* in XOD.
|
||||
A pulse causes the program to enter a new *transaction*. The pulse flows
|
||||
downstream along links and causes the nodes it hits to update. The process of
|
||||
updating a node is called *evaluation* in XOD.
|
||||
|
||||
At the moment of pulse emission a node can (and in most cases it would) set new
|
||||
values on its other ouput pins that have value types such as number or boolean.
|
||||
At the moment a pulse is emitted, a node can (and in most cases does) set new
|
||||
values on its other ouput pins with value types such as number or boolean.
|
||||
|
||||
Evaluation of a node hit by a pulse in most cases would require computing
|
||||
actual values on other node’s input pins. That values could depend on values of
|
||||
upstream nodes’ outputs, which in turn depend on values of their upstream
|
||||
nodes, and so on. All these dependencies are resolved by the XOD runtime
|
||||
engine. Final and intermediate values required to evaluate a node are computed
|
||||
atomically in the transaction.
|
||||
Evaluation of a node hit by a pulse usually requires computing
|
||||
actual values on another node’s input pins. The values on these pins could
|
||||
depend on the values of upstream nodes’ outputs, which in turn depend on the
|
||||
values of their upstream nodes, and so on. All these dependencies are resolved
|
||||
by the XOD runtime engine. The final and intermediate values required to
|
||||
evaluate a node are computed atomically in the transaction.
|
||||
|
||||
After all nodes affected by a pulse are evaluated the transaction completes and
|
||||
the system returns to the idle state.
|
||||
After all nodes affected by a pulse are evaluated the transaction is complete
|
||||
and the system returns to the idle state.
|
||||
|
||||
Transaction rules
|
||||
-----------------
|
||||
|
||||
### No external pulses while a transaction is in progress
|
||||
|
||||
Any transaction has a guard that will not allow any external pulse to come half
|
||||
way along the current transaction is in progress. Such pulse will be postponed
|
||||
and would trigger a new transaction after the current one completes.
|
||||
All transaction prevent any external pulses from occuring while the current
|
||||
transaction is in progress. Such a pulse would be postponed and trigger a new
|
||||
transaction after the current transaction is complete.
|
||||
|
||||
To be more precise, external pulses are pushed into a FIFO queue. And once the
|
||||
system is in the idle state a pulse is popped from the queue and a new
|
||||
transaction is initiated. The transaction completes, the system goes idle,
|
||||
takes next pulse from the queue, launches new transaction, and so on until the
|
||||
queue is empty.
|
||||
To be more precise, external pulses are pushed into a FIFO queue. Once the
|
||||
system is idle, a pulse is popped from the queue and a new transaction is
|
||||
initiated. The transaction completes, the system goes idle, takes the next
|
||||
pulse from the queue, launches a new transaction, etc. until the queue is
|
||||
empty.
|
||||
|
||||
### Evaluation order
|
||||
|
||||
During a transaction any particular node will be evaluated only after all nodes
|
||||
it depends on via links would be evaluated in their turn.
|
||||
During a transaction, a node is evaluated only after all nodes
|
||||
it depends on via links have been evaluated.
|
||||
|
||||
Consider following example.
|
||||
Consider the following example.
|
||||
|
||||

|
||||
|
||||
The result node will be only evaluated after both branches are evaluated despite
|
||||
they have node chains of different length. You can’t know the order the branches
|
||||
will be evaluated. It could be M1-M2-M3, M3-M1-M2, M1-M3-M2, or even M1-M2 and
|
||||
M3 in parallel. Furthermore, result node evaluation could be postponed until
|
||||
its values would be actually required (so called “lazy evaluation”). It’s up to
|
||||
target platform to decide.
|
||||
The result node will only be evaluated after both branches are evaluated,
|
||||
despite the fact that they have node chains of different length. You can’t
|
||||
know the order in which the branches will be evaluated. It could be M1-M2-M3,
|
||||
M3-M1-M2, M1-M3-M2, or even M1-M2 and M3 in parallel. Furthermore, evaluation
|
||||
of the result node might be postponed until its values are actually required
|
||||
(so-called “lazy evaluation”). The target platform decides.
|
||||
|
||||
The only thing that does matter is a node will be never evaluated with incomplete
|
||||
data.
|
||||
The only thing that does matter is that a node will be never evaluated with
|
||||
incomplete data.
|
||||
|
||||
That is the reason why inputs can’t have more than one incoming link. In other
|
||||
case the ambiguity will take place when two or more links would try to deliver
|
||||
That is the reason why inputs can’t have more than one incoming link.
|
||||
Otherwise, there would be ambiguity if two or more links tried to deliver
|
||||
different values.
|
||||
|
||||
### Buffering
|
||||
|
||||
Effect nodes’ outputs are *buffered* when changed. In other words the outputs
|
||||
keep most recent value they got. The data is persistent between transactions. So
|
||||
a node will “see” the buffered value from an old transaction via link if it is
|
||||
required to evaluate again due to other input value change.
|
||||
Effect nodes’ outputs are *buffered* when changed. In other words, the
|
||||
outputs keep their most recent value. The data is persistent between
|
||||
transactions. So a node will “see” the buffered value from an old
|
||||
transaction via a link if the node must be evaluated again due to a change in
|
||||
another input's value.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui ribbon label">Pro Tip</span>
|
||||
If you’re familiar with conventional programming think of pins and their
|
||||
buffered values as <em>variables</em>. They hold the program state and evolve over the
|
||||
time.
|
||||
If you’re familiar with conventional programming, think of pins and their
|
||||
buffered values as <em>variables</em>. They hold the program state and evolve
|
||||
over time.
|
||||
</div>
|
||||
|
||||
Whether values on of functional nodes’ pins would be buffered is up to target
|
||||
platform to decide. Since outputs of a functional node depend only on its
|
||||
inputs the decision is just a matter of execution speed vs RAM consumption. It
|
||||
The target platform decides whether the values on functional nodes’ pins will
|
||||
be buffered. Since a functional node's outputs depend only on its
|
||||
inputs, the decision is just a matter of execution speed vs RAM consumption. It
|
||||
has no effect on actual program behavior.
|
||||
|
||||
### Feedback loops handling
|
||||
|
||||
In XOD link cycles that contain only functional nodes are not allowed. They
|
||||
would lead to dead locks and program hangs.
|
||||
In XOD, link cycles that contain only functional nodes are not allowed. They
|
||||
would lead to deadlocks and hangs.
|
||||
|
||||
However it is OK to have a cycle broken by an effect node. In that case
|
||||
new value will be delivered via feedback link but the node will “see” it
|
||||
only once it would receive new incoming pulse.
|
||||
However, cycles broken by effect nodes are OK. In this case, a new value will
|
||||
be delivered via the feedback link, but the node will “see” it only once it has
|
||||
received a new incoming pulse.
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Program life cycle can be looked at as a infinite series of transactions that
|
||||
run whenever an external impact occurs. Pulses drive the program. No pulses, no
|
||||
changes.
|
||||
The program's life cycle can be looked at as a infinite series of transactions
|
||||
that run whenever an external impact occurs. Pulses drive the program. No
|
||||
pulses, no changes.
|
||||
|
||||
Transactions are protected from sudden pulses that could change or make it
|
||||
ambiguous the order of nodes’ evaluation.
|
||||
Transactions are protected from sudden pulses that could change or make
|
||||
ambiguous the order of node evaluation.
|
||||
|
||||
@@ -5,34 +5,34 @@ title: Linking Rules
|
||||
Linking Rules
|
||||
=============
|
||||
|
||||
To make behavior of XOD programs predictable there are some rules on how pins
|
||||
can be linked.
|
||||
To make XOD programs behave predictably, there are some rules on how pins can
|
||||
be linked.
|
||||
|
||||
Outputs and inputs
|
||||
------------------
|
||||
|
||||
You’re are not allowed to link two input pins, neither you’re allowed to link
|
||||
You’re are not allowed to link two input pins, nor are you allowed to link
|
||||
two output pins. It doesn’t makes much sense.
|
||||
|
||||
A link should always connect an output and an input.
|
||||
A link must always connect an output and an input.
|
||||
|
||||
If you want to mirror values, just create multiple links from an output pin.
|
||||
|
||||

|
||||
|
||||
An output can have an arbitrary number of links and an input can have
|
||||
no more than one incoming link.
|
||||
An output can have an arbitrary number of links, but an input can have no more
|
||||
than one incoming link.
|
||||
|
||||
Type matching
|
||||
-------------
|
||||
|
||||
If an input and an output has same [data type](../data-types/) they
|
||||
may be linked as is.
|
||||
If an input and an output have the same [data type](../data-types/), they may
|
||||
be linked as is.
|
||||
|
||||
However if they have different types they are only allowed to be linked if
|
||||
[casting](../data-types/#casting-rules) between their type is possible.
|
||||
However, if they have different types, they can only be linked if the output
|
||||
type can be [cast](../data-types/#casting-rules) into the input type.
|
||||
|
||||
Once you start linking pins that are suitable for other end of the link
|
||||
Once you start linking, pins that are suitable for the other end of the link
|
||||
are highlighted.
|
||||
|
||||
Color code
|
||||
|
||||
@@ -5,20 +5,20 @@ title: Program Structure
|
||||
Program Structure
|
||||
=================
|
||||
|
||||
Programs in XOD are quite similar to electronic circuits. Whereas to build an
|
||||
electronic circuit you use various electronic components and connect them
|
||||
with wires, in a XOD program you use *nodes* and connect them with *links*.
|
||||
XOD programs are quite similar to electronic circuits. To build an
|
||||
electronic circuit, you use various electronic components and connect them
|
||||
with wires. In a XOD program, you use *nodes* and connect them with *links*.
|
||||
|
||||

|
||||
|
||||
Nodes
|
||||
-----
|
||||
|
||||
What a node does depends on its type. Like in reality there are ICs to control
|
||||
motors, amplify audio signals, store data, in XOD there are many types of
|
||||
nodes available. It is easy to create your own as well.
|
||||
What a node does depends on its type. Just as there are ICs in the physical
|
||||
world to control motors, amplify audio signals, and store data, in XOD there
|
||||
are many types of nodes available. You can also easily create your own.
|
||||
|
||||
Some nodes represent physical devices like LED or digital thermometer, other
|
||||
Some nodes represent physical devices like LEDs or digital thermometers. Others
|
||||
are used to transform and filter data. Here are few examples:
|
||||
|
||||
* [`thermometer-tmp36`](/libs/xod/common-hardware/thermometer-tmp36/)
|
||||
@@ -26,80 +26,81 @@ are used to transform and filter data. Here are few examples:
|
||||
* [`add`](/libs/xod/core/add/)
|
||||
* [`to-percent`](/libs/xod/core/to-percent/)
|
||||
|
||||
You place nodes you’ve chosen for your program into slots to be later connected
|
||||
with links.
|
||||
You place the nodes you’ve chosen for your program into slots to be later
|
||||
connected with links.
|
||||
|
||||
Pins, inputs, and outputs
|
||||
-------------------------
|
||||
|
||||
Nodes alone are black boxes. To interact with them they expose *pins*. Think of
|
||||
pins as of sockets, ports, IC legs, jack-connectors.
|
||||
Nodes alone are black boxes. They expose *pins* to support interaction. Think
|
||||
of pins as of sockets, ports, IC legs, and jacks.
|
||||
|
||||
A pin can be either *input* or *output*. Once you feed an input with a new value
|
||||
the node is evaluated. As a reaction it can update values of its output pins or
|
||||
perform some interaction with real world, e.g. change a motor speed.
|
||||
A pin can be either an *input* or an *output*. Once you feed a new value to an
|
||||
input, the node is evaluated. In response, it may update the values on its
|
||||
output pins or interact with the real world in some way, e.g. change a motor's
|
||||
speed.
|
||||
|
||||
Some nodes send an output on their own as a reaction to some external event. For
|
||||
example the [clock](/libs/xod/core/clock/) node sends output with regular time
|
||||
intervals.
|
||||
Some nodes send an output on their own as a reaction to some external event.
|
||||
For example, the [clock](/libs/xod/core/clock/) node sends outputs at regular
|
||||
time intervals.
|
||||
|
||||
Pins are depicted as holes with short labels. Inputs are placed on a darker
|
||||
background and outputs are placed on a lighter background.
|
||||
background, and outputs are placed on a lighter background.
|
||||
|
||||

|
||||
|
||||
Links and values
|
||||
----------------
|
||||
|
||||
Nodes talk to each other by transmitting values over *links*. A link is a
|
||||
kind of wire that you use to connect one node output to another node input.
|
||||
Nodes talk to each other by transmitting values over *links*. A link is a kind
|
||||
of wire that you use to connect one node's output to another node's input.
|
||||
|
||||
Values in XOD are quite similar to electric signals. However unlike their
|
||||
electric counterparts they could carry not only a primitive voltage value, but
|
||||
electric counterparts, they can carry not only raw voltage values, but also
|
||||
more sensible data like arbitrary numbers and text strings. Learn more about
|
||||
values in [Data Types](../data-types/) article.
|
||||
values in the [Data Types](../data-types/) article.
|
||||
|
||||
In digital electronics voltage values are switched discretely and their change
|
||||
usually accompanied by some kind of clock signal. The clock signal is seen as
|
||||
a sequence of “moments” which are defined by observing falling or rising signal
|
||||
edges on the clock line. Interactions and changes actually happen at that
|
||||
moments. I.e. a digital circuit is static until a new clock signal would
|
||||
appear.
|
||||
In digital electronics, voltage values are switched discretely, usually
|
||||
accompanied by some kind of clock signal. The clock signal is seen as a
|
||||
sequence of “moments” defined by the falling or rising signal edges on the
|
||||
clock line. Interactions and changes actually happen at these moments, i.e. a
|
||||
digital circuit is static until a new clock signal appears.
|
||||
|
||||
Behavior of values in XOD is very much similar. Values change and propogate
|
||||
instantly. These cascade updates of values are called *transactions*. And things
|
||||
that play a role of clock signals are called *pulses* in XOD. [Execution
|
||||
Model](../execution-model/) article describes all principles in detail.
|
||||
Values behave very similarly in XOD. They change and propogate
|
||||
instantly. These cascading value updates are called *transactions*. In XOD, the
|
||||
role of clock signals is played by *pulses*. The [Execution
|
||||
Model](../execution-model/) article describes how they work in detail.
|
||||
|
||||
There are few rules that define which pins are allowed to be linked and which
|
||||
are not. They are intuitive enough, although for a formal description you can
|
||||
see [Linking Rules](../linking-rules/).
|
||||
There are a few rules that define which pins are allowed to be linked and which
|
||||
are not. They are intuitive enough, but for a formal description see [Linking
|
||||
Rules](../linking-rules/).
|
||||
|
||||
Patches
|
||||
-------
|
||||
|
||||
Nodes linked together form a *patch*. Patches are like modules, documents, files
|
||||
in other systems.
|
||||
Nodes linked together form a *patch*. Patches are like modules, documents, or
|
||||
files in other programming systems.
|
||||
|
||||
You would have a single patch in a simple project and for complex projects you’d
|
||||
likely to have many.
|
||||
You would have a single patch in a simple project, while you’d likely have
|
||||
many for complex projects.
|
||||
|
||||
What makes a patch pretty interesting is that once you’ve created it you can
|
||||
use it as a new type of node on other patches! That’s the main idea behind XOD
|
||||
What makes a patch interesting is that once you’ve created one you can use it
|
||||
as a new type of node in other patches! That’s the main idea behind XOD
|
||||
extensibility.
|
||||
|
||||
You use special *terminal nodes* to denote input and output pins when the patch
|
||||
You use special *terminal nodes* to denote input and output pins when a patch
|
||||
is used as a node.
|
||||
|
||||
<div class="ui segment">
|
||||
<span class="ui bottom attached label">
|
||||
Photo by <a href="https://www.flickr.com/photos/26735065@N00/">cutwithflourish</a>.
|
||||
Photo by
|
||||
<a href="https://www.flickr.com/photos/26735065@N00/">cutwithflourish</a>.
|
||||
</span>
|
||||
<p>
|
||||
<span class="ui blue ribbon label">Note</span>
|
||||
If you’ve heard of modular synthesizers they are very similar to XOD programs.
|
||||
The nodes are modules, the links are CV cables with banana connectors,
|
||||
the patches are rack chassis for modules.
|
||||
Perhaps you’ve heard of modular synthesizers - they are very similar to XOD
|
||||
programs. Nodes are modules, links are CV cables with banana connectors,
|
||||
and patches are a rack chassis for modules.
|
||||
</p>
|
||||
<div class="ui fluid image">
|
||||
<img src="modular-synth.jpg" alt="Modular synth" />
|
||||
|
||||
@@ -5,47 +5,46 @@ title: Complex Projects
|
||||
Complex Projects
|
||||
================
|
||||
|
||||
In past chapters of the tutorial series you’ve 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, you’ve 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 haven’t find
|
||||
support for it’s 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 haven’t found
|
||||
support for, it’s 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 [User’s guide](/docs/#users-guide) to understand XOD better.
|
||||
Read the [User’s guide](/docs/#users-guide) to understand XOD better.
|
||||
|
||||
@@ -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 you’ve had a deal with pulses and logical values.
|
||||
In previous tutorial chapters, you’ve 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.
|
||||
It’s 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.
|
||||
It’s 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.
|
||||
|
||||
Let’s 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
|
||||
Let’s 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:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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 can’t enter value
|
||||
Ports are currently represented as simple numbers. So you can’t 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
|
||||
-----------------------------------------------
|
||||
|
||||
Let’s modify our device a bit so that it would work as a smart light. It should
|
||||
turn on when it’s too dark and turn off when it’s bright enough. For this we’re
|
||||
going to replace the potentiometer with simple LDR-based voltage divider:
|
||||
Let’s slightly modify our device to make a smart light. It should turn on
|
||||
when it’s too dark and turn off when it’s bright enough. To do this,
|
||||
we’re going to replace the potentiometer with a simple LDR-based voltage
|
||||
divider:
|
||||
|
||||

|
||||
|
||||
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`. Let’s do it:
|
||||
This is commonly done using the comparison nodes `less`, `greater`, `equal`
|
||||
from `xod/core`. Let’s do it:
|
||||
|
||||

|
||||
|
||||
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 don’t 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. That’s 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. That’s 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.
|
||||
|
||||
Let’s improve our device to show the lightness level on LCD screen. Use any
|
||||
widespread text LCD to build circuit like one below:
|
||||
Let’s improve our device to show the lightness level on an LCD screen. Use
|
||||
any popular text LCD to build a circuit like one below:
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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 isn’t 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 isn’t true.
|
||||
|
||||
What’s next
|
||||
-----------
|
||||
|
||||
If you’re 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 you’re 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.
|
||||
|
||||
@@ -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 computer’s 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
|
||||
computer’s file system and
|
||||
USB-ports, its capabilities are quite limited.
|
||||
|
||||
Notably you can’t upload your program directly to the board from within browser
|
||||
and you wouldn’t get convenient save/load functionality.
|
||||
Notably, you can’t 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 you’ll see `welcome-to-xod` project open. It’s a primitive
|
||||
demo project that—yes, you guess it—blinks a LED on the board.
|
||||
Once you start XOD IDE, you’ll see the `welcome-to-xod` project open. It’s
|
||||
a primitive demo project that—yes, you guessed it—blinks a LED on the board.
|
||||
|
||||

|
||||
|
||||
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. You’ll 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. You’ll 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 you’ve 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. Don’t worry, most of it is
|
||||
a code of XOD runtime environment which actually give little overhead after compilation.
|
||||
And you haven’t to understand how it actually works. For now think about it as
|
||||
of black box.
|
||||
If you’ve 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. Don’t
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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, you’ll 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, you’ll 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 you’ll see 100% progress and a message from compiler:
|
||||
If the upload succeeds, you’ll see 100% progress and a compiler message:
|
||||
|
||||

|
||||
|
||||
<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>
|
||||
|
||||
What’s 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.
|
||||
|
||||
@@ -5,9 +5,9 @@ title: Nodes and Links
|
||||
Nodes and Links
|
||||
===============
|
||||
|
||||
Now let’s 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, let’s make it more visible by building a simple
|
||||
Now let’s 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 let’s make it more clear by building a simple
|
||||
circuit:
|
||||
|
||||

|
||||
@@ -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.
|
||||
|
||||

|
||||
|
||||
@@ -30,83 +30,84 @@ Let’s 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. You’ll 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. You’ll see the *Inspector* sidebar with the properties of
|
||||
the selected node, i.e. our `digital-output`.
|
||||
|
||||

|
||||
|
||||
Note that `PORT` value is set to 13’th 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”. That’s 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”. That’s 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 wouldn’t 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 wouldn’t 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. They’re 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. They’re 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. You’d use it quite often to drive
|
||||
updates in your programs.
|
||||
The clock node is a very common source of pulses. You’ll 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.
|
||||
|
||||

|
||||
|
||||
@@ -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.
|
||||
|
||||
That’s not too interesting. Let’s add another LED. Improve your circuit:
|
||||
|
||||

|
||||
|
||||
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 (+).
|
||||
|
||||

|
||||
|
||||
You’ll 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.
|
||||
You’ll 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:
|
||||
|
||||

|
||||
|
||||
Upload the updated program to the board. Whoa! Both LED’s are blinking.
|
||||
|
||||
Now let’s 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 let’s 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:
|
||||
|
||||

|
||||
|
||||
@@ -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:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
@@ -189,5 +193,6 @@ What’s next
|
||||
|
||||
You’ve 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.
|
||||
|
||||
@@ -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 you’ve 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, you’ve 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 we’re going to build simple watering station for two plants.
|
||||
The idea is to water a plat if it’s soil became too dry and constantly show current
|
||||
soil measurements on text LCD screen.
|
||||
In this chapter, we’re 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. We’ll use single
|
||||
patch `main` as in previous chapters.
|
||||
To start, let's build a device that will work with a single plant. We’ll 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:
|
||||
|
||||

|
||||
|
||||
Now make a following patch to control the device:
|
||||
Now make the following patch to control the device:
|
||||
|
||||

|
||||
|
||||
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 we’ve 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.
|
||||
|
||||
Let’s 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:
|
||||
Let’s 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:
|
||||
|
||||

|
||||
|
||||
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 plant’s 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 plant’s 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
|
||||
you’ll 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. You’ll see that a `plant` patch has appeared next to our
|
||||
`main`.
|
||||
|
||||
First of all we’re going to define its inputs and outputs. Expand
|
||||
First of all, we’re 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 we’ve
|
||||
`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 we’ve
|
||||
planned to parametrize:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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`:
|
||||
|
||||

|
||||
|
||||
We’re going to use these two nodes to manage plants and move existing logic to the
|
||||
shared `plant` patch. Let’s do it.
|
||||
We’re going to use these two nodes to manage plants and move the existing
|
||||
logic to the shared `plant` patch. Let’s 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, that’s a pain. We’ll 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, that’s a pain. We’ll
|
||||
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:
|
||||
|
||||

|
||||
|
||||
@@ -119,12 +124,12 @@ Wire up the circuit:
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
What’s 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.
|
||||
|
||||
Reference in New Issue
Block a user