Hi,
Right from my childhood I wanted to control appliances and had an eye for Automation
may be I'm just too lazy , two years back I wrote the software for this !
Video of my WSN NRF24L01+Arduino
code is somewhat like this .
NRF24L01 packet
class packet {
public :
unsigned char frame_type; // data or synchronization
unsigned short int to_add; // packet destination address
unsigned short int from_add; // packet origin address
unsigned short int h_from_add; // packet immediate hopped address
unsigned short int frame; // packet send on frame
unsigned long data1; // data holder
};
Arduino setup function , here were are setting up nrf24l01/serial/ZCD .
void setup()
{
if ( cid == 0 ) {
pinMode(2, OUTPUT);
} else {
pinMode(2,INPUT);
}
  
pinMode(DETECT, INPUT); //zero cross detect
digitalWrite(DETECT, HIGH); //enable pull-up resistor
pinMode(GATE, OUTPUT); //triac gate control
Serial.begin(57600);
while (!Serial) ;
Serial.println("start ");
if (!nrf24.init())
Serial.println("NRF24 init failed");
    
if (!nrf24.setChannel(B_Freq))
Serial.println("setChannel failed");
  
mask1 = mask | cid;
if (!nrf24.setThisAddress((uint8_t*)(&mask1), 5))
Serial.println("setThisAddress failed");
if (!nrf24.setPayloadSize(len))
Serial.println("setPayloadSize failed");
 
if (!nrf24.setRF(NRF24::NRF24DataRate2Mbps, NRF24::NRF24TransmitPower0dBm))
Serial.println("setRF failed");
 
ping_s = 0;
cnt =0;
frame = 150;
route_packet = 0;
route_pac_delay = 0;
num_retries = 0 ;
b_cnt = 0;
data.h_from_add = cid ;
data.frame_type = 0;
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 30000; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS11); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
    
if ( cid == 0 ) {
is_sync = 1;
} else {
is_sync = 0;
}
randomSeed(cid*10);
b_cnt = random(200,500);
    
ping_timeout=random(200,500);
ping_retries=0;
    
Serial.print("Curr ID ");
Serial.println(data.h_from_add,DEC);
attachInterrupt(1,zeroCrossingInterrupt, CHANGE );
}
      
                
        
       
        
          
        
   
          
        
        
  
 
 
 
     
Right from my childhood I wanted to control appliances and had an eye for Automation
may be I'm just too lazy , two years back I wrote the software for this !
Video of my WSN NRF24L01+Arduino
code is somewhat like this .
NRF24L01 packet
class packet {
public :
unsigned char frame_type; // data or synchronization
unsigned short int to_add; // packet destination address
unsigned short int from_add; // packet origin address
unsigned short int h_from_add; // packet immediate hopped address
unsigned short int frame; // packet send on frame
unsigned long data1; // data holder
};
Arduino setup function , here were are setting up nrf24l01/serial/ZCD .
void setup()
{
if ( cid == 0 ) {
pinMode(2, OUTPUT);
} else {
pinMode(2,INPUT);
}
pinMode(DETECT, INPUT); //zero cross detect
digitalWrite(DETECT, HIGH); //enable pull-up resistor
pinMode(GATE, OUTPUT); //triac gate control
Serial.begin(57600);
while (!Serial) ;
Serial.println("start ");
if (!nrf24.init())
Serial.println("NRF24 init failed");
if (!nrf24.setChannel(B_Freq))
Serial.println("setChannel failed");
mask1 = mask | cid;
if (!nrf24.setThisAddress((uint8_t*)(&mask1), 5))
Serial.println("setThisAddress failed");
if (!nrf24.setPayloadSize(len))
Serial.println("setPayloadSize failed");
if (!nrf24.setRF(NRF24::NRF24DataRate2Mbps, NRF24::NRF24TransmitPower0dBm))
Serial.println("setRF failed");
ping_s = 0;
cnt =0;
frame = 150;
route_packet = 0;
route_pac_delay = 0;
num_retries = 0 ;
b_cnt = 0;
data.h_from_add = cid ;
data.frame_type = 0;
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 30000; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS11); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
if ( cid == 0 ) {
is_sync = 1;
} else {
is_sync = 0;
}
randomSeed(cid*10);
b_cnt = random(200,500);
ping_timeout=random(200,500);
ping_retries=0;
Serial.print("Curr ID ");
Serial.println(data.h_from_add,DEC);
attachInterrupt(1,zeroCrossingInterrupt, CHANGE );
}
Below Function will send data to next hop address based on routing table .
bool route_data () {
    routed = 0 ;
    for ( cnt = 0 ; cnt <= luk_len ; cnt ++ ) {
  if ( (data.to_add >= luk_tab[cnt][0] && data.to_add <= luk_tab[cnt][1] ) ) {
                       routed = 1;
   if ( cnt == luk_len ) {
    send_to(up_link);
   } else {
           send_to(luk_tab[cnt][0]);
   }
                        break ;
   if ( routed == 1 ) {
    break ;
   }      
        }
   }
   if ( routed == 0 || routed != 1 ) {
 // NOT ABLE TO SEND THE data .
   }
   return (routed==1) ;
}
Actual function which will send data via NRF24L01 , it will also select frequency based on to_address and frame number .
bool send_to (unsigned short int to_addr ) {
        if ( b_flag == 0 ) {
         f  = to_addr * 11117 + ( frame *31 ) ;
           f = (f/13) % 11 ;
                f = (f * 10) +1 ;
        } else {
                f = B_Freq;
        }
        if (!nrf24.setChannel(f))
          Serial.println("setChannel failed");
 mask1 = mask | to_addr ;
   if (!nrf24.setTransmitAddress((uint8_t*)(&mask1), 5)) {
    Serial.println("setTransmitAddress failed");
  routed = 2; 
 }
        delayMicroseconds(700);
        if ( b_flag == 1 ) {
          data.frame = frame;
          rtt = TCNT1;
          data.data1 = rtt + 1700 ;
          data.frame_type = 3;
        }
        data.h_from_add = cid;       
        if ( debug == 1 && data.frame_type == 2) {
          Serial.print(to_addr,DEC);
          Serial.print(" to add ,S'dg ");
          Serial.print(data.data1,DEC);
          Serial.print(" frame is ");
          Serial.println(frame,DEC);
        }
        if (!nrf24.send((uint8_t*)&data, sizeof(data),b_flag)) {
            Serial.println("E4"); 
     routed = 3;
 }
        if (!nrf24.waitPacketSent()) {
          Serial.print("Sndg Fail ");
   routed = 4;
        }
        return ( routed == 1 || b_flag ) ;
}
Receiver function , configures NRF24L01 in RX mode and selects frequency based on same formula used in TX mode .
bool listen_rx() {
  f  = cid * 11117 + ( frame *31 );
  f = (f/13) % 11 ;
  f = (f * 10) +1 ;
  nrf24.powerUpRx();
  if (!nrf24.setChannel(f))
     Serial.println("setChannel failed");
   if (nrf24.waitAvailableTimeout(5)) {
          if (!nrf24.recv((uint8_t*)&data_junk, &len)) {
            Serial.println("read failed");
     return 0;
   }
       if ( debug == 1 && data_junk.frame_type==2) {
          if ( serial_read == 'A' ) {
             trigger_delay = data_junk.data1 -65 ;
             Serial.print("setting val ");
             Serial.println(trigger_delay , DEC );        
          }
          Serial.print(data_junk.h_from_add,DEC);
          Serial.print(" rx from add ,S'dg ");
          serial_read = data_junk.data1;
          Serial.print(serial_read,DEC);
          Serial.print(" frame is ");
          Serial.println(frame,DEC);
        }
        if ( data_junk.frame_type == 2 && data_junk.to_add != cid) {
            data_in=data_junk;
            route_packet =1;
            route_pac_delay = random(2,8);
            num_retries = 0 ; 
        }
   }
  return 1;
}
Function used for synchronizing two nodes , received beacon packet will have counter value which is used to load into TCNT1 of received node .
void sync_me (bool ip) {
        nrf24.powerUpRx();
        if (!nrf24.setChannel(B_Freq))
    Serial.println("setChannel failed");
        mask1 = mask | up_link ;
        if (!nrf24.setTransmitAddress((uint8_t*)(&mask1), 5))
      Serial.println("setTransmitAddress failed");
         if ( ip == 1)  {
         }
         if ( ip == 1 ) {
             TCCR1B &= ~(1 << CS11);    // stop counter
      nrf24.waitAvailable() ;
             TCCR1B |= (1 << CS11);    // start counter
         } 
 if (!nrf24.recv((uint8_t*)&data, &len))
   Serial.println("read failed");
 TCNT1 = data.data1 - 500;
 frame = data.frame;
 mask1 = mask | data.h_from_add ;
 is_sync =1; 
        nrf24.setTransmitAddress((uint8_t*)"NULL1", 5);
}
Function used to send beacon packet for slave nodes 
void send_beacon () {
 // Serial.print("Send beac ");
 //  Serial.println(frame,DEC);
   b_flag = 1;
   send_to(cid);
   b_flag = 0;
   b_cnt = random(300,600);
}
Function calling route_data() and from there send_to() .
void send_packet () {
  //Serial.println("send pack");
  data=data_in;
  data.frame_type =2;
    if ( ! route_data() ) {
   num_retries++;
   if ( num_retries > 10 ) {
                         Serial.println("Droping pack");
    route_packet =0 ;
    num_retries = 0 ;
   }
  } else {
   route_packet = 0;
   num_retries = 0 ;
  }
route_pac_delay = random(5,15);
data.frame_type = 0;
}
MISC functions used for book keeping
bool process_state () {
  while ( ping_s == 0 ) {delayMicroseconds(1);}
  ping_s = 0 ;
  frame= frame+1 ;
  if ( frame > 150 ) {frame = 0;}
}
bool post_processing () {
// nrf24.powerDown();
if ( route_pac_delay > 0 ) {
  route_pac_delay--;
}
 b_cnt ++ ;
 ping_timeout++ ;
}
Functional loop used to send/receive/synchronize nodes .
void loop() {
 loop_var = 10;
 process_state();
 if ( cid == 0 ) {
   digitalWrite(2,HIGH); 
   digitalWrite(2,LOW); 
 }
 if ( is_sync == 0 ) {
    loop_var = 3;
   sync_me(1);
   Serial.println("sync'd");
 } else if ((cid+2) == frame  ) {
    loop_var = 4;
    send_beacon();
 }  else if ( (up_link+2)==frame ) {
    loop_var = 5;
       sync_me(0);
 } else if (route_packet == 1 && route_pac_delay == 0) {
    loop_var = 6;
      send_packet();
 } else if (route_packet == 0 && Serial.available()) {
      loop_var = 7;
     Serial.println(max_tcnt,DEC);
      data_in.data1 = Serial.read(); ;
      data_in.to_add = ping_node ;
      data_in.from_add = cid ;
      route_packet =1;
      num_retries = 0 ;
 } else {
    loop_var = 8;
    listen_rx();
 }
 nrf24.setTransmitAddress((uint8_t*)"NULL1", 5);
 post_processing();
 if ( ping_s == 1  ) {
   Serial.print("Error ");
   Serial.println(loop_var,DEC);
 //  delay(100000);
 }
}
I'll update more information and few pictures explaining how routing between nodes work .