/*
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
[email protected]
TODO :-
- rewrite codes to use serialEvent()
- better handling of sender/receiver detection
- reduce/rewrite the usage of memcpy()
*/
#include <SoftwareSerial.h>
#include <SPI.h>
#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()
}
Comments