| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| en:pfw:wireless_communication_mesh-network [2023-09-04 18:23] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | en:pfw:wireless_communication_mesh-network [2023-09-04 18:23] (current) – ↷ Links angepasst, weil Seiten im Wiki verschoben wurden uho |
|---|
| | {{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 | |
| | |
| | <code> |
| | 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 |
| | </code> |
| | |
| | ===== 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: |
| | |
| | <code forth> |
| | 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 |
| | </code> |
| | |
| | This structure is used in the word ''%%<WAIT>%%'' this word catches the response from the addressed node but only within the given time period.\\ |
| | An example: ''%%: ON ( node -- ) ch * >node 40 <wait> ; \ 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 === |
| | |
| | <code forth> |
| | 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 ; |
| | </code> |
| | |
| | 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. |
| | |
| | <code forth> |
| | : XKEY) ( -- c ) begin handler? until key) ; |
| | </code> |
| | |
| | The last line in the word ''%%STARTNODE%%'' contains this line, so after startnode is executed the interactive node is ready. |
| | |
| | <code forth> |
| | ['] xkey) to 'key \ Add KEY & node handler to KEY |
| | </code> |
| | |
| | ===== 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 | |
| | |''%%<WAIT>%%'' |( 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 === |
| | |
| | <code forth> |
| | 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 <wait> \ Activate output on that node shortly |
| | off 30 <wait> repeat |
| | halt? until ; \ Until a key is pressed or a STOP command was received |
| | </code> |
| | |
| | |
| | ---- |
| | |
| | <HTML><ul></HTML> |
| | <HTML><li></HTML><HTML><p></HTML>[[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 |
| | <HTML></p></HTML><HTML></li></HTML> |
| | <HTML><li></HTML><HTML><p></HTML>[[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 |
| | <HTML></p></HTML><HTML></li></HTML> |
| | <HTML><li></HTML><HTML><p></HTML>[[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 |
| | <HTML></p></HTML><HTML></li></HTML> |
| | <HTML><li></HTML><HTML><p></HTML>[[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<HTML></p></HTML> |
| | |
| | ---- |
| | <HTML></li></HTML><HTML></ul></HTML> |
| | |
| | **All steps taken by the ''%%BUILD%%'' routine**\\ |
| | {{https://user-images.githubusercontent.com/11397265/157910410-addf6e4d-2e14-478c-8426-47e8435576b7.jpg|Build done color}} |
| |