SHARE
TWEET

Serial over nRF24L01

a guest Dec 13th, 2013 3,039 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  /*
  2.  This program will transmit all data received from the h/w serial pins out to the nRF radio
  3.  and sent out all the data received from the nRF to SoftSerial monitor
  4.  
  5.  For this code, I m using a GPS module Skylab SKM53 running at 9600bps
  6.  
  7.  Max nRF payload size = 30
  8.  1st byte header :-
  9.  7     : fragment/no fragment
  10.  4 - 6 : number of fragments
  11.  3     : unused
  12.  0 - 2 : fragment sequence number
  13.  
  14.  Max buffer is 90 bytes
  15.  
  16.  SoftSerial pins RX 5 ,TX 6 ( for debugging )
  17.  nRF pins CE 8, CSN, 9 MOSI 11, MIS0 12, SCK 13
  18.  
  19.  Date : 27/07/2013
  20.  Version : 4
  21.  
  22.  delay of 20 per radio.write works
  23.  
  24.  Release Notes : Working but the satellite signals will dropped
  25.  when viewed on Min GPS
  26.  
  27.  
  28.  Written by Stanley Seow
  29.  stanleyseow@gmail.com
  30.  
  31.  TODO :-
  32.  
  33.  - rewrite codes to use serialEvent()
  34.  - better handling of sender/receiver detection
  35.  - reduce/rewrite the usage of memcpy()
  36.  
  37. */
  38.  
  39. #include <SoftwareSerial.h>
  40. #include <SPI.h>
  41. #include "nRF24L01.h"
  42. #include "RF24.h"
  43. #include "printf.h"
  44.  
  45.  
  46. #define DATABUFFERSIZE 90
  47. char dataBuffer[DATABUFFERSIZE];
  48.  
  49. byte dataBufferIndex = 0;
  50. char startChar = '$';
  51. char endChar = '\r';
  52.  
  53. // RX, TX
  54. SoftwareSerial Serial2(5,6);
  55.  
  56. // Set up nRF24L01 radio on SPI pin for CE, CSN
  57. RF24 radio(8,9);
  58.  
  59. const uint64_t pipes[2] = { 0xDEDEDEDEE7ULL, 0xDEDEDEDEE9ULL };
  60.  
  61. // Defines for radio buffers
  62. char RXPayload[33] = "";
  63. char RXPayload2[33] = "";
  64. char RXPayload3[33] = "";
  65.  
  66. char STR1[33],STR2[33],STR3[33] = "";
  67. uint8_t flag0, flagA0, flagA1, flagB0, flagB1, flagB2 = 0;
  68.  
  69. int Sender, storeString = 0;
  70.  
  71. void setup(void)
  72. {
  73. //  Serial.begin(115200);
  74.   Serial.begin(9600);
  75.   Serial2.begin(9600);
  76.  
  77.   pinMode(2,OUTPUT);
  78.   pinMode(3,OUTPUT);  
  79.  
  80.   printf_begin();
  81.   radio.begin();
  82.  
  83.   // Default radio setings
  84.   radio.enableDynamicPayloads();
  85.   radio.setDataRate(RF24_1MBPS);
  86.   radio.setPALevel(RF24_PA_MAX);
  87.   radio.setChannel(80);
  88.   // delay 1ms, 3 retries
  89.   // 0 - 250us, 15 - 4000us
  90.   radio.setRetries(15,15);
  91.   // Enable AutoAck, send 2nd / 3rd fragment only after 1st/2nd fragment is ACK
  92.   radio.setAutoAck(1);
  93.  
  94.   //check for which side is the sender ( receive data via h/w serial RX )
  95.   // Uses hardware serial for GPS
  96.   if ( Serial.available() > 0 ) {
  97.      if ( Serial.read() ) { Sender = true; }
  98.   }
  99.    
  100.   if ( Sender ) {
  101.     Serial2.println("Sender mode.. ");
  102.     radio.openWritingPipe(pipes[0]);
  103.     radio.openReadingPipe(1,pipes[1]);
  104.   } else {
  105.     // this side is the receiver connected to Serial Monitor  
  106.     Serial2.println("Receiver mode.. ");
  107.     Serial.end();
  108.     Serial.begin(57600);
  109.     radio.openWritingPipe(pipes[1]);
  110.     radio.openReadingPipe(1,pipes[0]);  
  111.    
  112.     // Only print radio details on the receiver side
  113.     radio.startListening();  
  114.     radio.printDetails();
  115.   }
  116.  
  117.   delay(500);
  118.  
  119. }
  120.  
  121. void loop(void) {
  122.  
  123.   if ( !Sender ) {  
  124.  
  125.       nRF_Receive();
  126.   } else {
  127.       nRF_Sender();
  128.   }
  129. } // End of loop()
  130.  
  131.  
  132. void nRF_Sender() {
  133.  
  134.   char dataBuffer2[DATABUFFERSIZE]="";
  135.  
  136.   if (getSerialString() ) {
  137.  
  138.    // Serial2.println(dataBuffer);  
  139.    
  140.     // Make a copy of dataBuffer array
  141.     memcpy(&dataBuffer2, &dataBuffer,strlen(dataBuffer));
  142.  
  143.     fragmentPackets(dataBuffer2,strlen(dataBuffer2) );
  144.     sendPackets(STR1,STR2,STR3);
  145.    
  146.  }  
  147. }
  148.  
  149.  
  150. boolean getSerialString(){
  151.     static byte dataBufferIndex = 0;
  152.     while(Serial.available()>0){
  153.         char incomingbyte = Serial.read();
  154.         if(incomingbyte==startChar){
  155.             dataBufferIndex = 0;  //Initialize our dataBufferIndex variable
  156.             storeString = true;
  157.         }
  158.         if(storeString){
  159.             //Let's check our index here, and abort if we're outside our buffer size
  160.             //We use our define here so our buffer size can be easily modified
  161.             if(dataBufferIndex==DATABUFFERSIZE){
  162.                 //Oops, our index is pointing to an array element outside our buffer.
  163.                 dataBufferIndex = 0;
  164.                 break;
  165.             }
  166.             if(incomingbyte==endChar){
  167.                 dataBuffer[dataBufferIndex] = 0; //null terminate the C string
  168.                 //Our data string is complete.  return true
  169.                 return true;
  170.             }
  171.             else{
  172.                 dataBuffer[dataBufferIndex++] = incomingbyte;
  173.                 dataBuffer[dataBufferIndex] = 0; //null terminate the C string
  174.             }
  175.         }
  176.         else{    
  177.         }
  178.     }
  179.     // Did not get a valid string, so return false
  180.     return false;
  181. }
  182.  
  183.  
  184. void fragmentPackets(char Buffer2[DATABUFFERSIZE],int len) {
  185. // Two headers with 30 bytes payload
  186. // 1st byte
  187. //      7 bit - fragment, 1 or 0
  188. // 6 to 4 bit - number of fragment, 111, 7 max fragment
  189. //      3 bit - none
  190. // 0 to 2 bit - fragment number, starting with 0 to 7, 000 to 111
  191. //
  192. // 2nd byte, reserved
  193.  
  194.  
  195.    STR1[0], STR2[0], STR3[0] = 0;
  196.    
  197.    if ( len < 31 ) {
  198.      STR1[0] = B00010000;    // No fragmentation, 1 segment
  199.      STR1[1] = 0xff;         // Reversed header  
  200.      STR1[2] = 0;            // null terminate string
  201.      strcat(STR1,Buffer2);  
  202.    } else if ( len < 61 ) {
  203.         STR1[0] = 0xA0; // fragmentation, 1010 0000, fragment bit, 2 fragments, fragment no. 0
  204.         STR1[1] = 0xff; // Reverse header          
  205.         STR1[2] = 0;     // null terminate string
  206.         strncat(STR1, Buffer2,30);
  207.  
  208.         STR2[0] = 0xA1; // fragmentation, 1010 0001, fragment bit, 2 fragments, fragment no. 1
  209.         STR2[1] = 0xff; // Reverse header            
  210.         STR2[2] = 0;     // null terminate string, 32 bytes + 2 extra bytes
  211.         strcat(STR2, &Buffer2[30]);    // Copy the balance of pointer address 30 and above
  212.        
  213.    } else if ( len < 91 )  {  
  214.         STR1[0] = 0xB0; // fragmentation, 1011 0000, fragment bit, 3 fragments, fragment no. 0
  215.         STR1[1] = 0xff; // Reverse header          
  216.         STR1[2] = 0;     // null terminate string  
  217.         strncat(STR1, Buffer2,30);    // Copy the 1st 30 bytes to STR1
  218.        
  219.         STR2[0] = 0xB1; // fragmentation, 1011 0001, fragment bit, 3 fragments, fragment no. 1
  220.         STR2[1] = 0xff; // Reverse header  
  221.         STR2[2] = 0;     // null terminate string
  222.         strncat(STR2, &Buffer2[30],30);  // Copy the next 30 bytes to STR2
  223.  
  224.         STR3[0] = 0xB2; // fragmentation, 1011 0011, fragment bit, 3 fragments, fragment no. 2
  225.         STR3[1] = 0xff; // Reverse header        
  226.         STR3[2] = 0;     // null terminate string      
  227.         strcat(STR3, &Buffer2[60]);        
  228.        
  229.       } else {
  230.       // payload > 90 bytes, discard or add more fragments  
  231.       Serial2.print("Input serial string more than 90 bytes");
  232.    } // end if
  233.  
  234. }  // end fragmentPackets
  235.  
  236.  
  237. void sendPackets(char TMP1[33], char TMP2[33], char TMP3[33]) {
  238.  
  239.   // Mask the 1st Byte, bits 5 & 6 and shift 4 places to right
  240.   // Return 0, 2 or 3 fragments
  241.   int status = (STR1[0] & B00110000)>>4;
  242.   digitalWrite(2, LOW);
  243.   digitalWrite(3, LOW);
  244.    
  245.   radio.stopListening();
  246.  
  247.   switch (status) {
  248.     case 1:
  249.           radio.write( TMP1,strlen(TMP1));
  250.           // fine tune the correct delay values based on radio.setRetries()
  251.           delay(20);    
  252.           break;
  253.     case 2:
  254.           radio.write(TMP1,strlen(TMP1));  
  255.           delay(20);
  256.           radio.write( TMP2,strlen(TMP2));  
  257.  
  258.           // fine tune the correct delay values based on radio.setRetries()
  259.           delay(20);    
  260.           break;
  261.     case 3:
  262.           radio.write(TMP1,strlen(TMP1));
  263.           delay(20);
  264.           radio.write(TMP2,strlen(TMP2));  
  265.           delay(20);
  266.           radio.write(TMP3,strlen(TMP3));
  267.  
  268.           // fine tune the correct delay values based on radio.setRetries()
  269.           delay(20);
  270.           break;
  271.     } // switch/case  end
  272.    
  273.     radio.startListening();
  274.  
  275. } // nrf_Send end
  276.  
  277.  
  278.  
  279. // Receive payload from nRF at remote end
  280.  
  281. void nRF_Receive(){
  282.  
  283.   uint8_t len=0, Header = 0, recvPacket = 0;
  284.  
  285.  // Call startlistening everytime here
  286.    
  287.   RXPayload[0] = 0;
  288.  
  289.   if ( radio.available() > 0 ) {
  290.     len = radio.getDynamicPayloadSize();
  291.     radio.read( &RXPayload, len );
  292.     RXPayload[len] = 0; // Terminate RxPayload string with 0
  293.  
  294.     // Extract header bits for comparision
  295.     Header = RXPayload[0] & 0xff;
  296.    
  297. //Serial.print("RXPayload:");
  298. //Serial.print(Header,HEX);
  299. //Serial.print(" ");
  300. //Serial.println(RXPayload);
  301.  
  302.     switch ( Header ) {
  303.  
  304.     case 0x10:
  305.      // No fragment, strip off first 2 header bytes
  306.         memcpy(&STR1,&RXPayload[2],len-2 );  
  307.         STR1[len-2]=0;
  308.         flag0 = 1;
  309. //Serial.print("flag0:");
  310. //Serial.println(STR1);
  311.         break;
  312.        
  313.     case 0xA0:    
  314.      // Fragment packets, with 2 fragments, 1st fragment
  315.         memcpy(&STR1, &RXPayload[2],30);
  316.         STR1[30]=0;
  317.         flagA0 = 1;
  318. //Serial.print("flagA0:");
  319. //Serial.println(STR1);        
  320.         break;
  321.        
  322.     case 0xA1:
  323.       // Fragment packets, with 2 fragments, last fragment
  324.         memcpy(&STR2, &RXPayload[2],len-2);
  325.         STR2[len-2]=0;
  326.         flagA1 = 1;
  327. //Serial.print("flagA1:");
  328. //Serial.println(STR2);  
  329.         break;  
  330.  
  331.     case 0xB0:
  332.       // Fragment packets, with 3 fragments, 1st fragment
  333.         memcpy(&STR1, &RXPayload[2],30);
  334.         STR1[30]=0;
  335.         flagB0 = 1;
  336. //Serial.print("flagB0:");
  337. //Serial.println(STR1);          
  338.         break;
  339.        
  340.     case 0xB1:
  341.       // Fragment packets, with 3 fragments, 2nd fragment
  342.         memcpy(&STR2, &RXPayload[2],30);
  343.         STR2[30]=0;
  344.         flagB1 = 1;
  345. //Serial.print("flagB1:");
  346. //Serial.println(STR2);          
  347.         break;  
  348.  
  349.     case 0xB2:
  350.       // Fragment packets, with 3 fragments, last fragment
  351.         memcpy(&STR3, &RXPayload[2],len-2);
  352.         STR3[len-2]=0;
  353.         flagB2 = 1;
  354. //Serial.print("flagB2:");
  355. //Serial.println(STR3);          
  356.         break;  
  357.     default:
  358.         Serial.println("Invalid Headers");
  359.    
  360.     } // end of switch    
  361.        
  362.        
  363.     // Merge payload to Serial Monitor
  364.    
  365.     if ( flag0 ) {
  366.          sprintf(dataBuffer,"%s",STR1);
  367.          flag0 = 0;
  368.     } else if ( flagA0 && flagA1 ) {
  369.          sprintf(dataBuffer,"%s%s",STR1,STR2);
  370.          flagA0, flagA1 = 0;
  371.     } else if ( flagB0 && flagB1 && flagB2 ) {
  372.          sprintf(dataBuffer,"%s%s%s",STR1,STR2,STR3);
  373.          flagB0, flagB1, flagB2 = 0;
  374.     }
  375.    
  376.     if ( (dataBuffer[0] == '$') ) {
  377.      Serial.println(dataBuffer);
  378.      // Reset all buffers and flags
  379.      dataBuffer[0] = 0;
  380.      STR1[0] = 0; STR2[0] = 0; STR3[0] = 0;
  381.     }
  382.  
  383.   } // endif radio.available()  
  384. }
RAW Paste Data
Top