SHOW:
|
|
- or go back to the newest paste.
| 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 | [email protected] | |
| 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 | } |