User Tools

Site Tools


digispark:tutorials:nrfmesh

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
digispark:tutorials:nrfmesh [2015/01/12 22:00]
digistump
digispark:tutorials:nrfmesh [2016/06/09 12:03] (current)
Line 15: Line 15:
  
 For simplicity this implements a data structure in the RF24 payload. That structure is defined in the example as: For simplicity this implements a data structure in the RF24 payload. That structure is defined in the example as:
-<​code>​+<​code ​arduino>
 struct ​ struct ​
 { {
Line 42: Line 42:
 These two main functions are well commented and cover most of how this works on the code level: These two main functions are well commented and cover most of how this works on the code level:
  
-<​code>​+<​code ​arduino>
 void sendToMesh(uint8_t toAddress, long data){ void sendToMesh(uint8_t toAddress, long data){
   if(sequence[NODE_ADDRESS]<​255)   if(sequence[NODE_ADDRESS]<​255)
Line 58: Line 58:
 </​code>​ </​code>​
  
-<​code>​+<​code ​arduino>
 bool readAndRepeat(){ bool readAndRepeat(){
   if(radio.read(&​msg,​ sizeof(msg))){ //if we have incoming data   if(radio.read(&​msg,​ sizeof(msg))){ //if we have incoming data
Line 83: Line 83:
 **Topography:​** **Topography:​**
  
-This mesh layer+This mesh layer can be used with many different topographies - such as:
  
 +Master and Nodes - One Node is the master connected to a screen/​computer/​etc (think of it as the server) the rest are just nodes sending data back to the master and repeating each others data so that it can get to the master. Example: whole house temperature monitors with the master connected to the internet. This is the most common setup and what our example below uses.
  
-<​code>​+Ad hoc Nodes - Each node reports different things addressed to different nodes - say you have node A, B and C. Node A reports the temperature to C. B reports the voltage it sees to C and A and C reports its switch input state to B. Example: Machines in a factory where they need to react to what other machines are doing/​reading,​ but each differently to different values. This is less common but really neat! 
 + 
 +Multi master - multi node: A mix of the two - say you have A,B,C, and D - maybe all report their temperature to A including D, but they all (including A) report their voltage to D. 
 + 
 +Obviously the mix of topographies is endless - this should support most of them because it does not apply any limits to topography (at the expense of optimization)  
 + 
 +===== Generic Example Code: ===== 
 + 
 +Note: This is generic example code that must be edited to work with your setup and desired function - see the example below this for a guided working example.  
 + 
 +  
 +<​code ​arduino>
 #include <​SPI.h>​ #include <​SPI.h>​
 #include "​nRF24L01.h"​ #include "​nRF24L01.h"​
Line 154: Line 166:
     //​sendToMesh(0,​ analogRead(A5));​ //send to node 0 the analog read value of pin 5 - could also send a temp sensor value, etc ,etc      //​sendToMesh(0,​ analogRead(A5));​ //send to node 0 the analog read value of pin 5 - could also send a temp sensor value, etc ,etc 
     //​sendToMesh(255,​ analogRead(A5));​ //send to all nodes (255 is the broadcast address) the analog read value of pin 5     //​sendToMesh(255,​ analogRead(A5));​ //send to all nodes (255 is the broadcast address) the analog read value of pin 5
 +  }
 + 
 +}
 + 
 + 
 +void sendToMesh(uint8_t toAddress, long data){
 +  if(sequence[NODE_ADDRESS]<​255)
 +    sequence[NODE_ADDRESS]++;​ //increment sequence count for this device
 +  else
 +    sequence[NODE_ADDRESS] = 0; //set to zero if last was 255 so we don't overflow - logic for read is built to handle this too
 +    ​
 +  msg.toAddress = toAddress; //set the address of the destination node
 +  msg.fromAddress = NODE_ADDRESS;​ //set the from as this node - of course
 +  msg.fromSequence = sequence[NODE_ADDRESS];​ //set it to the sequence number we just implemented which should be greater than any the nodes have received ​
 +  radio.stopListening();​ //turn of recv so we can transmit
 +  radio.write(&​msg,​ sizeof(msg));​
 +  radio.startListening();​ //turn recv back on
 +}
 +
 +bool readAndRepeat(){
 +  if(radio.read(&​msg,​ sizeof(msg))){ //if we have incoming data
 +    if(msg.fromAddress!=NODE_ADDRESS){ //make sure this node didn't send it
 +      if(sequence[msg.fromAddress] < msg.fromSequence || (sequence[msg.fromAddress] == 255 && msg.fromSequence == 0)){ //make sure we haven'​t already repeated it or received it
 +          //increment sequence for that address so we don't repeat it twice from this node or receive it twice
 +          sequence[msg.fromAddress] = msg.fromSequence;​
 +          if(msg.toAddress==NODE_ADDRESS){ //is it for this node? if so return true so we can use it!
 +            return true;
 +          }
 +          //otherwise repeat it - send it back out
 +          radio.write(&​msg,​ sizeof(msg));​
 +          if(msg.toAddress == 255){ //it was a broadcast so return true so we do something with it
 +            return true;
 +          }
 +      }
 +    }
 +  }
 +  return false;
 +}
 +
 +
 +
 +</​code>​
 +
 +===== Master and Nodes Example: =====
 +
 +This example uses 3 Nodes - We will call them Node 0, 1, and 2 - Node 0 is the master and should be connected to a computer - it will use the USB keyboard library to type out any messages it receives.
 +
 +Node 1 and 2 send messages every 10 seconds of the analog Read value of their Pin 5 - they repeat messages for each other - that is all they do. They do not need to be attached to a computer once programmed - just powered on with at least one in range of the master.
 +
 +Put this code on Node 0 which will be the master:
 +
 +<code arduino>
 +#include <​SPI.h>​
 +#include "​nRF24L01.h"​
 +#include "​RF24.h"​
 +
 +//THESE MUST BE SET! CHANGE ADDRESS AS YOU UPLOAD TO EACH NODE!
 +#define TOTAL_NODES 3 //TOTAL NUMBER OF NODES IN MESH
 +#define NODE_ADDRESS 0 //the sero indexed address of this node - nodes must be numbered 0 thru TOTAL_NODES-1 //also note 255 is broadcast address
 +
 +//hold the seuqnce numbers to avoid repeating the same messages
 +uint8_t ​ sequence[TOTAL_NODES];​
 +
 +//setup radio module
 +RF24 radio(9,​12);​
 +
 +//message format - adjust data as needed ​ - the rest is madatory for this mesh to work
 +struct ​
 +{
 + char toAddress;
 + char fromAddress;​
 + char fromSequence;​
 + long data;
 +} msg;
 + 
 +//​don'​t change! read is same for all nodes, write is automatically calculated here
 +const uint64_t writePipe = 0xF0F0F0F00LL + NODE_ADDRESS;​
 +const uint64_t readPipe = 0xF0F0F0F0D2LL;​
 + 
 + 
 +void setup() {
 +  // put your setup code here, to run once:
 +  radio.begin();​
 +  radio.setDataRate(RF24_250KBPS);​ //lowest speed = most range
 +  radio.setAutoAck(false);​ //this is a mesh so we don't want ACKs!
 +  radio.setRetries(15,​ 15);
 +  radio.setPayloadSize(sizeof(msg));​
 +  radio.openWritingPipe(writePipe);​
 +  radio.openReadingPipe(1,​ readPipe);
 +  radio.startListening();​
 +}
 +
 +long now = 0;
 + 
 +void loop() {
 +  ​
 +
 +  ​
 +  if(readAndRepeat()){ //will repeat messages as needed and return false unless there is packet for this node - CALL FREQUENTLY!
 +    //if this does not return false then we have a packet for THIS node!
 +    //​msg.fromAddress is the node that sent it
 +    //msg.data is the data itself
 +    //Do something with it!
 +    //For example type out the packets coming to this node
 +    DigiKeyboard.println(msg.fromAddress);​
 +    DigiKeyboard.println(msg.data);​
 +
 +  }
 +  ​
 +  /
 +  /*
 +  We don't do any sending because this node is the master and just receives things!
 +   ​if(millis() - now > 10000){ //send a packet from this node to the mesh every 10 seconds but wait in a non-blocking ​  way so that we can still run this loop and repeat things
 +    now = millis(); //set now to millis so we wait another 10 seconds before sending again
 +    //​sendToMesh(To_Address,​Data_To_Send);​
 +    //​sendToMesh(0,​ analogRead(A5));​ //send to node 0 the analog read value of pin 5 - could also send a temp sensor value, etc ,etc 
 +    //​sendToMesh(255,​ analogRead(A5));​ //send to all nodes (255 is the broadcast address) the analog read value of pin 5
 +  }
 +  */
 +  ​
 +  DigiKeyboard.delay(100);//​give the usb some time to poll
 + 
 +}
 + 
 + 
 +void sendToMesh(uint8_t toAddress, long data){
 +  if(sequence[NODE_ADDRESS]<​255)
 +    sequence[NODE_ADDRESS]++;​ //increment sequence count for this device
 +  else
 +    sequence[NODE_ADDRESS] = 0; //set to zero if last was 255 so we don't overflow - logic for read is built to handle this too
 +    ​
 +  msg.toAddress = toAddress; //set the address of the destination node
 +  msg.fromAddress = NODE_ADDRESS;​ //set the from as this node - of course
 +  msg.fromSequence = sequence[NODE_ADDRESS];​ //set it to the sequence number we just implemented which should be greater than any the nodes have received ​
 +  radio.stopListening();​ //turn of recv so we can transmit
 +  radio.write(&​msg,​ sizeof(msg));​
 +  radio.startListening();​ //turn recv back on
 +}
 +
 +bool readAndRepeat(){
 +  if(radio.read(&​msg,​ sizeof(msg))){ //if we have incoming data
 +    if(msg.fromAddress!=NODE_ADDRESS){ //make sure this node didn't send it
 +      if(sequence[msg.fromAddress] < msg.fromSequence || (sequence[msg.fromAddress] == 255 && msg.fromSequence == 0)){ //make sure we haven'​t already repeated it or received it
 +          //increment sequence for that address so we don't repeat it twice from this node or receive it twice
 +          sequence[msg.fromAddress] = msg.fromSequence;​
 +          if(msg.toAddress==NODE_ADDRESS){ //is it for this node? if so return true so we can use it!
 +            return true;
 +          }
 +          //otherwise repeat it - send it back out
 +          radio.write(&​msg,​ sizeof(msg));​
 +          if(msg.toAddress == 255){ //it was a broadcast so return true so we do something with it
 +            return true;
 +          }
 +      }
 +    }
 +  }
 +  return false;
 +}
 +
 +
 +
 +</​code>​
 +
 +**Nodes 1 and 2:** These are the sending nodes. They send the analog value of Pin 5. Load this on to the other two Nodes changing NODE_ADDRESS to 2 for the 3rd node (which is node #2 because the addresses are zero indexed)
 +
 +<code arduino>
 +#include <​SPI.h>​
 +#include "​nRF24L01.h"​
 +#include "​RF24.h"​
 +
 +//THESE MUST BE SET! CHANGE ADDRESS AS YOU UPLOAD TO EACH NODE!
 +#define TOTAL_NODES 3 //TOTAL NUMBER OF NODES IN MESH
 +#define NODE_ADDRESS 1 //the sero indexed address of this node - nodes must be numbered 0 thru TOTAL_NODES-1 //also note 255 is broadcast address
 +
 +//hold the seuqnce numbers to avoid repeating the same messages
 +uint8_t ​ sequence[TOTAL_NODES];​
 +
 +//setup radio module
 +RF24 radio(9,​12);​
 +
 +//message format - adjust data as needed ​ - the rest is madatory for this mesh to work
 +struct ​
 +{
 + char toAddress;
 + char fromAddress;​
 + char fromSequence;​
 + long data;
 +} msg;
 + 
 +//​don'​t change! read is same for all nodes, write is automatically calculated here
 +const uint64_t writePipe = 0xF0F0F0F00LL + NODE_ADDRESS;​
 +const uint64_t readPipe = 0xF0F0F0F0D2LL;​
 + 
 + 
 +void setup() {
 +  // put your setup code here, to run once:
 +  radio.begin();​
 +  radio.setDataRate(RF24_250KBPS);​ //lowest speed = most range
 +  radio.setAutoAck(false);​ //this is a mesh so we don't want ACKs!
 +  radio.setRetries(15,​ 15);
 +  radio.setPayloadSize(sizeof(msg));​
 +  radio.openWritingPipe(writePipe);​
 +  radio.openReadingPipe(1,​ readPipe);
 +  radio.startListening();​
 +}
 +
 +long now = 0;
 + 
 +void loop() {
 +  ​
 +
 +  ​
 +  if(readAndRepeat()){ //will repeat messages as needed and return false unless there is packet for this node - CALL FREQUENTLY!
 +    //if this does not return false then we have a packet for THIS node!
 +    //​msg.fromAddress is the node that sent it
 +    //msg.data is the data itself
 +    /*
 +       These nodes just send data so we don't do anything here for this example
 +       we still need to call readAndRepeat though because we still need to repeat ​
 +       ​packets for other nodes!
 +    */
 +  }
 +  ​
 +  if(millis() - now > 10000){ //send a packet from this node to the mesh every 10 seconds but wait in a non-blocking way so that we can still run this loop and repeat things
 +    now = millis(); //set now to millis so we wait another 10 seconds before sending again
 +    //​sendToMesh(To_Address,​Data_To_Send);​
 +    sendToMesh(0,​ analogRead(A5));​ //send to node 0 the analog read value of pin 5 - could also send a temp sensor value, etc ,etc 
   }   }
    
digispark/tutorials/nrfmesh.txt · Last modified: 2016/06/09 12:03 (external edit)