Advertisement
Guest User

Serial over nRF24L01

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