{{pfw:banner.png}}
====== Mesh network ======
{{https://user-images.githubusercontent.com/11397265/157903902-66324963-a68f-43bf-bdf6-fc22b96b761f.jpg|mesh in action}}\\
**Three Egel-kits communicating**
===== The idea =====
Using standard wireless transceivers to form a self constructing mesh network. Basically each node has the same structure, the only difference is the node address.\\
The transceiver used here is the nRF24L01 or the Chinese clone named [[https://datasheet.lcsc.com/lcsc/2202241830_Nanjing-Zhongke-Microelectronics-Si24R1_C14436.pdf|SI24R1]].
===== Built on top =====
The basis for this example are these files: [[en:pfw:spi|SPI]], [[:nrf24l01_basic_2024l01dn_20g2553-01a.f|Basic 24L01dn]] file and the [[en:pfw:bit-array|bit array]], these are used for the driver of the network layer. This driver uses **dynamic payload** to optimise the troughput of the network.
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/Generic-Forth|Generic Forth]], version of the mesh network\\
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/G2553-&-F149|G2553 & F149]], noForth mesh network version\\
* [[https://github.com/project-forth-works/project-forth-works/tree/main/Communication-Protocols/Wireless-Communication/Mesh-network/GD32VF103|GD32VF103]], noForth mesh network version\\
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/FR59xx|MSP430FR5949]], noForth mesh network version
==== Files required to build a working node ====
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/SPI/GD32VF/noForth/SPI0%20v100.f|An SPI driver for your CPU]], the example link goes to the GD32VF103 driver
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/nRf24L01%2B/GD32VF/noForth/basic%2024L01dn%20GD32VF-01a.f|A driver for the used transceiver]], again for the GD32 Risc-V MPU and some tools
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/GD32VF103/mesh%20node%20v4.1rf%20GD32dn-01a.f|Then the mesh network layer]], and we should have a functioning node
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/GD32VF103/Tools|Finally you may add some tools]], a network build routine, PING, etc.
For noForth and especially for the [[https://www.tindie.com/products/Willem_O/egel-kit-board-set-for-msp430g2553-no-parts/|Egel-kit]] you are ready now. The photo on top shows you three Egel-kits communicating :)\\
When you use another MPU and/or Forth system you may adapt the [[https://github.com/project-forth-works/project-forth-works/tree/main/Communication-Protocols/Wireless-Communication/Mesh-network/Generic-Forth|generic version]] to your needs.
===== Flexible RF settings =====
The most important RF setting are build into the word ''%%SETRF%%'' this word sets the following parameters:
* RF-channel number; 0 to 125
* Scan transmit power; -18db to 0db
* Transmit power during normal use; -18db to 0db
* Communication bitrate; 250 Kbit, 1 Mbit or 2 Mbit
* Unique node address; 0 to max. node number (15 in this example)
===== Payload structure =====
The **Dynamic payload** format is 1 to 32 bytes. For this implementation the minimum payload size is 3 bytes (the command, destination & origin). This is because the node handler does a check on the destination before accepting a command. The complete payload is described in the table below.
^ 0 ^ 1 ^ 2 ^ 3 ^ 4 ^ 5 to 31 ^
| Command | Dest. | Orig. | Sub node | Admin | d00 to d1A |
0 pay> = Command for destination 1 pay> = Destination node
2 pay> = Origin node 3 pay> = Address of sub node
4 pay> = Administration byte 5 to 31 pay> = Data 0x1A (#26) bytes
===== Time out on network commands =====
Since network commands can be lost, a time-out on the response to the transmitted command is necessary. This time-out can be constructed with a built-in timer, or alternatively by using a built-in cycle counter.\\
This code example is for the GD32VF103 Risc-V microcontroller:
hex
code TICK ( -- u ) \ Read half (low 32-bits) of 64-bit rdcycle counter
sp -) tos .mov
tos B00 zero csrrs \ Read low counter
next
end-code
decimal
: MS ( ms -- )
104000 * \ Convert MS to CPU ticks (CPU-clock/1000)
tick >r \ Save tick counter
begin
tick r@ - \ Calc. ticks passed
over u< 0= until \ Larger or equal to given ticks?
r> 2drop ; \ Yes ready
This structure is used in the word ''%%%%'' this word catches the response from the addressed node but only within the given time period.\\
An example: ''%%: ON ( node -- ) ch * >node 40 ; \ Send power on command%%''
===== Node command interpreter =====
Here is a complete list of the commands of the node command interpreter. It is also known as //the handler// within this code example.
^ Token ^Function ^
| ''F'' |Execute Forth command string |
| ''|'' |Stop free running program |
| | |
| ''*'' |Power output on |
| ''_'' |Power output off |
| | |
| ''I'' |Give node info |
| ''H'' |Give node connection info |
| ''P'' |Respond on a ping |
| ''N'' |Give free node number |
| | |
| ''s'' |Scan and note any node within reach |
| ''i'' |Gather node type info from other nodes |
| ''h'' |Gather network connection data |
| | |
| ''^'' |Receive hop data from other node |
| ''@'' |Receive type info from node |
| ''R'' |Register a new node to the network |
| ''}'' |Answer when an external command is finished|
| ''#'' |Receive free node number from network |
===== Interactive node =====
The node command interpreter is integrated in a the word ''%%NODE%%''. A sample implementation is shown here. The word ''%%GET?%%'' is a primitive outer interpreter as is commonly used in many Forth systems. It reads and stores characters when a key was hit. With the escape key we are leaving this node interpreter loop. A backspace removes typos, after the enter key the string is evaluated, an error leaves this loop too.
=== Example code ===
hex 0 value NR create BUF 20 allot
: GET? ( -- 0|1B )
0 key? if \ Key pressed?
key dup 1B = if or exit then \ Yes, exit on escape char!
dup 0D = if \ Is it ENTER?
drop space buf nr evaluate \ Yes, interpret string
0 to nr cr \ New line
t? 0= if ." N>" then \ Display prompt when tracer is off
else
dup 8 = if \ Is it backspace?
emit bl emit 8 emit -1 \ Yes, remove char
else
dup emit buf nr + c! 1 \ Normal char, show & save
then
+to nr \ Adjust number of chars
then
then ;
: NODE ( -- )
startnode ( tron ) troff 0 to nr
begin begin handler? until get? until ;
This program is originally written in noForth. In noForth the serial input and output is vectored. Replacing the key vector does the same as the ''%%NODE%%''program.
: XKEY) ( -- c ) begin handler? until key) ;
The last line in the word ''%%STARTNODE%%'' contains this line, so after startnode is executed the interactive node is ready.
['] xkey) to 'key \ Add KEY & node handler to KEY
===== NODE command set =====
If you want to try out this mesh network implementation, these are the words to play with. Note that each node also contains a primitive event handler. This handler uses a pin as input for a switch to ground. This switch alternately activates the words ''%%ALL-ON%%'' or ''%%ALL-OFF%%''.
^Word ^Stack ^Description ^
|''%%.STATUS%%'' |( -- ) |Show most important RF data |
|''%%.ALL%%'' |( -- ) |Show network connection data |
|''%%REGISTER%%''|( -- ) |Connect myself to an existing network |
|''%%ON%%'' |( +n -- ) |Activate power output on node +n |
|''%%OFF%%'' |( +n -- ) |Deactivate power output on node +n |
|''%%ALL-ON%%'' |( -- ) |Activate all outputs on the network |
|''%%ALL-OFF%%'' |( -- ) |Deactivate all outputs on the network |
|''%%STOP%%'' |( +n -- ) |Halt any free running program on node +n|
|''%%>F%%'' |( +n ccc -- )|Execute the forth word ccc on node +n |
|''%%SCANX%%'' |( -- ) |Scan & note direct accessible nodes |
----
{{https://user-images.githubusercontent.com/11397265/157905223-70621a30-4d84-4d40-b706-f30acef52bed.jpg|scanx}}\\
**SCANX result**
===== Network tools =====
The mesh network code adds some additional words for constructing new functions above the basic node command interpreter. These are:
^ Word ^ Stack ^ Function ^
| ''%%ALL%%'' | ( -- a ) | Address of a BIT-table with all found nodes |
| ''%%DIRECT%%'' | ( -- a ) | Address of a BIT-table with direct accessable nodes |
|''%%INDIRECT%%''|( -- a ) |Address of a BIT-table with indirect accessable nodes |
|''%%#MAP%%'' |( -- +n ) |Leave the size of a bitmap |
|''%%GET*%%'' |( u a -- 0/b ) |Check if node +n present in bit-array a? |
|''%%*CLR%%'' |( u a -- ) |Remove node +n from bit-array a |
|''%%*COUNT%%'' |( a -- +n ) |Leave number of nodes found in bitmap a |
|''%%>USER%%'' |( a -- ) |Copy nodes to node accu for app programmer |
|''%%>WORK%%'' |( a -- ) |Copy nodes to node accu for internal functions |
|''%%NEXT?%%'' |( a -- 0/u -1 )|Leave node number of the first used node in bitmap a & erase the bit |
|''%%RUN%%'' |( -- ) |Allow a program to run free |
|''%%HALT?%%'' |( -- f ) |Alternative KEY? to stop node programs |
|''%%%%'' |( u -- ) |Wait +n milliseconds & respond to external network commands, leave after an } was received|
|''%%>OTHERS%%'' |( c -- ) |Send node command c to all nodes noted in WORK with a timeout of 1024 ms |
|''%%FINISH%%'' |( -- ) |End network buildup with adding node type information |
=== Generic forth example code ===
hex
: RUN-FORW ( -- ) \ Running light on all outputs in my network
run begin \ Reset stop flag
all >user \ Copy all nodes table to user table
begin user next? while \ Get next available node number
dup on 100 \ Activate output on that node shortly
off 30 repeat
halt? until ; \ Until a key is pressed or a STOP command was received
----
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/Generic-Forth/Tools/Build%20(3.9d).f|BUILD]], constructs a (hopping) mesh network
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/Generic-Forth/Tools/Ping-2.f|PING]], check node connection/availability
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/Generic-Forth/Tools/Mesh-demos.f|DEMO's]], that activate the node outputs in different ways
* [[https://github.com/project-forth-works/project-forth-works/blob/main/Communication-Protocols/Wireless-Communication/Mesh-network/Generic-Forth/Tools/automesh.f|Simple demo]], primitive network build routine & running light demo
----
**All steps taken by the ''%%BUILD%%'' routine**\\
{{https://user-images.githubusercontent.com/11397265/157910410-addf6e4d-2e14-478c-8426-47e8435576b7.jpg|Build done color}}