Wednesday, September 26, 2018

Easy Way to Create a Wireless Sensor Network

In this video we look at an easy way with not very much code to setup a wireless network using the nRF24L01 Transceiver and Arduino.



//***************************Master or Receiver code*****************
/*This code was used for a video tutorial on the ForceTronics YouTube Channel
 * This code is free and open for anybody to use and modify at your own risk
*/

#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/

const uint8_t pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const uint8_t pinCSN = 10; //This pin is used for SPI comm chip select
RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI) 
const uint64_t rAddress = 0xB00B1E50C3LL;  //Create pipe address for the network and notice I spelled boobies because I am mature, the "LL" is for LongLong type
const uint8_t rFChan = 89; //Set channel frequency default (chan 84 is 2.484GHz to 2.489GHz)

//Create a structure to hold fake sensor data and channel data
struct PayLoad {
  uint8_t chan;
  uint8_t sensor;
};

PayLoad payload; //create struct object

void setup() {
  wirelessSPI.begin();  //Start the nRF24 module
  wirelessSPI.setChannel(rFChan); //set communication frequency channel
  wirelessSPI.openReadingPipe(1,rAddress);  //This is receiver or master so we need to be ready to read data from transmitters
  wirelessSPI.startListening();    // Start listening for messages
  Serial.begin(115200);  //serial port to display received data
  Serial.println("Network master is online...");
}

void loop() {
  if(wirelessSPI.available()){ //Check if recieved data
     wirelessSPI.read(&payload, sizeof(payload)); //read packet of data and store it in struct object
     Serial.print("Received data packet from node: ");
     Serial.println(payload.chan); //print node number or channel
     Serial.print("Node sensor value is: ");
     Serial.println(payload.sensor); //print node's sensor value
     Serial.println(); 
  }
}

//***************************Node or Transmitter code*****************
/*This code was used for a video tutorial on the ForceTronics YouTube Channel
 * This code is free and open for anybody to use and modify at your own risk
*/

#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/

const uint8_t pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const uint8_t pinCSN = 10; //This pin is used to tell the nRF24 whether the SPI communication is a command
RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI) 
const uint64_t wAddress = 0xB00B1E50C3LL;  //Create pipe address to send data, the "LL" is for LongLong type
const uint8_t rFChan = 89; //Set channel default (chan 84 is 2.484GHz to 2.489GHz)
const uint8_t rDelay = 7; //this is based on 250us increments, 0 is 250us so 7 is 2 ms
const uint8_t rNum = 5; //number of retries that will be attempted 
const uint8_t chan1 = 2; //D2 pin for node channel check
const uint8_t chan2 = 3; //D3 pin for node channel check
const uint8_t chan3 = 4; //D4 pin for node channel check

//stuct of payload to send fake sensor data and node channel
struct PayLoad {
  uint8_t chan;
  uint8_t sensor;
};

PayLoad payload; //create struct object

void setup() {
  pinMode(chan1,INPUT_PULLUP); //set channel select digital pins to input pullup
  pinMode(chan2,INPUT_PULLUP);
  pinMode(chan3,INPUT_PULLUP);
  wirelessSPI.begin();  //Start the nRF24 module
  wirelessSPI.setChannel(rFChan); 
  wirelessSPI.setRetries(rDelay,rNum); //if a transmit fails to reach receiver (no ack packet) then this sets retry attempts and delay between retries   
  wirelessSPI.openWritingPipe(wAddress); //open writing or transmit pipe
  wirelessSPI.stopListening(); //go into transmit mode
  randomSeed(analogRead(0)); //set random seed for fake sensor data
  setChannel();  //checks current channel setting for transceiver
}

void loop() {
  delay(3000); //send data every 3 seconds
  payload.sensor = random(0,255); //get made up sensor value
  if (!wirelessSPI.write(&payload, sizeof(payload))){  //send data and remember it will retry if it fails
    delay(random(5,20)); //as another back up, delay for a random amount of time and try again
    if (!wirelessSPI.write(&payload, sizeof(payload))){
      //set error flag if it fails again
    }
  }

}

//check for low digital pin to set node address
void setChannel() {
  if(!digitalRead(chan1)) payload.chan = 1;
  else if(!digitalRead(chan2)) payload.chan = 2;
  else if(!digitalRead(chan3)) payload.chan = 3;
  else payload.chan = 0;
}

2 comments:

  1. That's interesting. But what if I need a very fast, low latency data transfer ?
    I have a setup where I need to send & receive the value of a sensor - ie variable resistor - (from an animal to a machine) - (no bad animal treatment in my experience !). Ideally, the latency should be <10ms and should be constant. And the "poll" (as MaxMSP says) or update should be every 2-3ms...
    I thought of using audio transmitters, the ones we use in cinema, because they're fast (reach 20KHz !) and reliable, but super expensive as well...
    The config would be : sensor > arduino > dac > audio transmitter
    Do you think a nRF24L01 could achieve this ?
    Thanks for your tutorials btw !!
    Nico

    ReplyDelete
  2. Im at work and don't have the code on hand but long story short I am sending sensor value in a

    struc {

    int sensor1;
    int sensor 2;

    }


    The RX and and 2 Tx have the same struc.

    TX1

    struc {

    int sensor1= sensors.getTempCByIndex(0);
    int sensor2;
    };

    TX2
    struc{

    int sensor1;
    int sensor2=sensors.getTempCByIndex(0);

    };



    The values are making it to the RX but every other time that it prints one the senor values the other is 0.

    My question is how do I keep that from happening or keep Tx from sending a value of 0 for (int sensor 2) and Tx2 from sending a value of zero for (int sensor 1)

    I have tried a few different ways not a big programmer but learning.

    When I get home I do screen shots and send entire exact code and serial monitor. Just thought I would ask

    Just a point in the right direction

    ReplyDelete