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 .