/* This program will transmit all data received from the h/w serial pins out to the nRF radio and sent out all the data received from the nRF to SoftSerial monitor For this code, I m using a GPS module Skylab SKM53 running at 9600bps Max nRF payload size = 30 1st byte header :- 7 : fragment/no fragment 4 - 6 : number of fragments 3 : unused 0 - 2 : fragment sequence number Max buffer is 90 bytes SoftSerial pins RX 5 ,TX 6 ( for debugging ) nRF pins CE 8, CSN, 9 MOSI 11, MIS0 12, SCK 13 Date : 27/07/2013 Version : 4 delay of 20 per radio.write works Release Notes : Working but the satellite signals will dropped when viewed on Min GPS Written by Stanley Seow stanleyseow@gmail.com TODO :- - rewrite codes to use serialEvent() - better handling of sender/receiver detection - reduce/rewrite the usage of memcpy() */ #include #include #include "nRF24L01.h" #include "RF24.h" #include "printf.h" #define DATABUFFERSIZE 90 char dataBuffer[DATABUFFERSIZE]; byte dataBufferIndex = 0; char startChar = '$'; char endChar = '\r'; // RX, TX SoftwareSerial Serial2(5,6); // Set up nRF24L01 radio on SPI pin for CE, CSN RF24 radio(8,9); const uint64_t pipes[2] = { 0xDEDEDEDEE7ULL, 0xDEDEDEDEE9ULL }; // Defines for radio buffers char RXPayload[33] = ""; char RXPayload2[33] = ""; char RXPayload3[33] = ""; char STR1[33],STR2[33],STR3[33] = ""; uint8_t flag0, flagA0, flagA1, flagB0, flagB1, flagB2 = 0; int Sender, storeString = 0; void setup(void) { // Serial.begin(115200); Serial.begin(9600); Serial2.begin(9600); pinMode(2,OUTPUT); pinMode(3,OUTPUT); printf_begin(); radio.begin(); // Default radio setings radio.enableDynamicPayloads(); radio.setDataRate(RF24_1MBPS); radio.setPALevel(RF24_PA_MAX); radio.setChannel(80); // delay 1ms, 3 retries // 0 - 250us, 15 - 4000us radio.setRetries(15,15); // Enable AutoAck, send 2nd / 3rd fragment only after 1st/2nd fragment is ACK radio.setAutoAck(1); //check for which side is the sender ( receive data via h/w serial RX ) // Uses hardware serial for GPS if ( Serial.available() > 0 ) { if ( Serial.read() ) { Sender = true; } } if ( Sender ) { Serial2.println("Sender mode.. "); radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); } else { // this side is the receiver connected to Serial Monitor Serial2.println("Receiver mode.. "); Serial.end(); Serial.begin(57600); radio.openWritingPipe(pipes[1]); radio.openReadingPipe(1,pipes[0]); // Only print radio details on the receiver side radio.startListening(); radio.printDetails(); } delay(500); } void loop(void) { if ( !Sender ) { nRF_Receive(); } else { nRF_Sender(); } } // End of loop() void nRF_Sender() { char dataBuffer2[DATABUFFERSIZE]=""; if (getSerialString() ) { // Serial2.println(dataBuffer); // Make a copy of dataBuffer array memcpy(&dataBuffer2, &dataBuffer,strlen(dataBuffer)); fragmentPackets(dataBuffer2,strlen(dataBuffer2) ); sendPackets(STR1,STR2,STR3); } } boolean getSerialString(){ static byte dataBufferIndex = 0; while(Serial.available()>0){ char incomingbyte = Serial.read(); if(incomingbyte==startChar){ dataBufferIndex = 0; //Initialize our dataBufferIndex variable storeString = true; } if(storeString){ //Let's check our index here, and abort if we're outside our buffer size //We use our define here so our buffer size can be easily modified if(dataBufferIndex==DATABUFFERSIZE){ //Oops, our index is pointing to an array element outside our buffer. dataBufferIndex = 0; break; } if(incomingbyte==endChar){ dataBuffer[dataBufferIndex] = 0; //null terminate the C string //Our data string is complete. return true return true; } else{ dataBuffer[dataBufferIndex++] = incomingbyte; dataBuffer[dataBufferIndex] = 0; //null terminate the C string } } else{ } } // Did not get a valid string, so return false return false; } void fragmentPackets(char Buffer2[DATABUFFERSIZE],int len) { // Two headers with 30 bytes payload // 1st byte // 7 bit - fragment, 1 or 0 // 6 to 4 bit - number of fragment, 111, 7 max fragment // 3 bit - none // 0 to 2 bit - fragment number, starting with 0 to 7, 000 to 111 // // 2nd byte, reserved STR1[0], STR2[0], STR3[0] = 0; if ( len < 31 ) { STR1[0] = B00010000; // No fragmentation, 1 segment STR1[1] = 0xff; // Reversed header STR1[2] = 0; // null terminate string strcat(STR1,Buffer2); } else if ( len < 61 ) { STR1[0] = 0xA0; // fragmentation, 1010 0000, fragment bit, 2 fragments, fragment no. 0 STR1[1] = 0xff; // Reverse header STR1[2] = 0; // null terminate string strncat(STR1, Buffer2,30); STR2[0] = 0xA1; // fragmentation, 1010 0001, fragment bit, 2 fragments, fragment no. 1 STR2[1] = 0xff; // Reverse header STR2[2] = 0; // null terminate string, 32 bytes + 2 extra bytes strcat(STR2, &Buffer2[30]); // Copy the balance of pointer address 30 and above } else if ( len < 91 ) { STR1[0] = 0xB0; // fragmentation, 1011 0000, fragment bit, 3 fragments, fragment no. 0 STR1[1] = 0xff; // Reverse header STR1[2] = 0; // null terminate string strncat(STR1, Buffer2,30); // Copy the 1st 30 bytes to STR1 STR2[0] = 0xB1; // fragmentation, 1011 0001, fragment bit, 3 fragments, fragment no. 1 STR2[1] = 0xff; // Reverse header STR2[2] = 0; // null terminate string strncat(STR2, &Buffer2[30],30); // Copy the next 30 bytes to STR2 STR3[0] = 0xB2; // fragmentation, 1011 0011, fragment bit, 3 fragments, fragment no. 2 STR3[1] = 0xff; // Reverse header STR3[2] = 0; // null terminate string strcat(STR3, &Buffer2[60]); } else { // payload > 90 bytes, discard or add more fragments Serial2.print("Input serial string more than 90 bytes"); } // end if } // end fragmentPackets void sendPackets(char TMP1[33], char TMP2[33], char TMP3[33]) { // Mask the 1st Byte, bits 5 & 6 and shift 4 places to right // Return 0, 2 or 3 fragments int status = (STR1[0] & B00110000)>>4; digitalWrite(2, LOW); digitalWrite(3, LOW); radio.stopListening(); switch (status) { case 1: radio.write( TMP1,strlen(TMP1)); // fine tune the correct delay values based on radio.setRetries() delay(20); break; case 2: radio.write(TMP1,strlen(TMP1)); delay(20); radio.write( TMP2,strlen(TMP2)); // fine tune the correct delay values based on radio.setRetries() delay(20); break; case 3: radio.write(TMP1,strlen(TMP1)); delay(20); radio.write(TMP2,strlen(TMP2)); delay(20); radio.write(TMP3,strlen(TMP3)); // fine tune the correct delay values based on radio.setRetries() delay(20); break; } // switch/case end radio.startListening(); } // nrf_Send end // Receive payload from nRF at remote end void nRF_Receive(){ uint8_t len=0, Header = 0, recvPacket = 0; // Call startlistening everytime here RXPayload[0] = 0; if ( radio.available() > 0 ) { len = radio.getDynamicPayloadSize(); radio.read( &RXPayload, len ); RXPayload[len] = 0; // Terminate RxPayload string with 0 // Extract header bits for comparision Header = RXPayload[0] & 0xff; //Serial.print("RXPayload:"); //Serial.print(Header,HEX); //Serial.print(" "); //Serial.println(RXPayload); switch ( Header ) { case 0x10: // No fragment, strip off first 2 header bytes memcpy(&STR1,&RXPayload[2],len-2 ); STR1[len-2]=0; flag0 = 1; //Serial.print("flag0:"); //Serial.println(STR1); break; case 0xA0: // Fragment packets, with 2 fragments, 1st fragment memcpy(&STR1, &RXPayload[2],30); STR1[30]=0; flagA0 = 1; //Serial.print("flagA0:"); //Serial.println(STR1); break; case 0xA1: // Fragment packets, with 2 fragments, last fragment memcpy(&STR2, &RXPayload[2],len-2); STR2[len-2]=0; flagA1 = 1; //Serial.print("flagA1:"); //Serial.println(STR2); break; case 0xB0: // Fragment packets, with 3 fragments, 1st fragment memcpy(&STR1, &RXPayload[2],30); STR1[30]=0; flagB0 = 1; //Serial.print("flagB0:"); //Serial.println(STR1); break; case 0xB1: // Fragment packets, with 3 fragments, 2nd fragment memcpy(&STR2, &RXPayload[2],30); STR2[30]=0; flagB1 = 1; //Serial.print("flagB1:"); //Serial.println(STR2); break; case 0xB2: // Fragment packets, with 3 fragments, last fragment memcpy(&STR3, &RXPayload[2],len-2); STR3[len-2]=0; flagB2 = 1; //Serial.print("flagB2:"); //Serial.println(STR3); break; default: Serial.println("Invalid Headers"); } // end of switch // Merge payload to Serial Monitor if ( flag0 ) { sprintf(dataBuffer,"%s",STR1); flag0 = 0; } else if ( flagA0 && flagA1 ) { sprintf(dataBuffer,"%s%s",STR1,STR2); flagA0, flagA1 = 0; } else if ( flagB0 && flagB1 && flagB2 ) { sprintf(dataBuffer,"%s%s%s",STR1,STR2,STR3); flagB0, flagB1, flagB2 = 0; } if ( (dataBuffer[0] == '$') ) { Serial.println(dataBuffer); // Reset all buffers and flags dataBuffer[0] = 0; STR1[0] = 0; STR2[0] = 0; STR3[0] = 0; } } // endif radio.available() }