From 6263bccd0241aaf0c0e45106d514ea34516f39e9 Mon Sep 17 00:00:00 2001 From: TMRh20 Date: Sat, 29 Mar 2014 05:29:29 -0600 Subject: [PATCH] Extended timeouts, txStandBy changes - For use in noisy or low signal scenarios - Allows user specified timeout period of extended duration - Modified txStandBy() and writeBlocking() functions to rely on a user defined timeout period, automatic retries and payload reUse --- RF24.cpp | 43 ++-- RF24.h | 172 ++++++++----- examples/GettingStarted/GettingStarted.ino | 17 +- examples/GettingStarted/GettingStarted.pde | 227 ------------------ .../TransferTimeouts/TransferTimeouts.ino | 189 +++++++++++++++ examples/TransferTimeouts/printf.h | 37 +++ 6 files changed, 366 insertions(+), 319 deletions(-) delete mode 100644 examples/GettingStarted/GettingStarted.pde create mode 100644 examples/TransferTimeouts/TransferTimeouts.ino create mode 100644 examples/TransferTimeouts/printf.h diff --git a/RF24.cpp b/RF24.cpp index bbd9b02..e0713ac 100644 --- a/RF24.cpp +++ b/RF24.cpp @@ -471,25 +471,27 @@ bool RF24::write( const void* buf, uint8_t len ) /****************************************************************************/ //For general use, the interrupt flags are not important to clear -bool RF24::writeBlocking( const void* buf, uint8_t len ) +bool RF24::writeBlocking( const void* buf, uint8_t len, unsigned long timeout ) { //Block until the FIFO is NOT full. //Keep track of the MAX retries and set auto-retry if seeing failures //This way the FIFO will fill up and allow blocking until packets go through //The radio will auto-clear everything in the FIFO as long as CE remains high + unsigned long timer = millis(); //Get the time that the payload transmission started while ( (read_register(FIFO_STATUS) & _BV(FIFO_FULL))){ //Blocking only if FIFO is full. This will loop and block until TX is successful - if( get_status() & _BV(MAX_RT)){ - reUseTX(); //Set re-transmit + if( get_status() & _BV(MAX_RT)){ //If MAX Retries have been reached + reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag } - + if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0 } - //Start Writing - startFastWrite(buf,len); - return 1; + //Start Writing + startFastWrite(buf,len); //Write the payload if a buffer is clear + + return 1; //Return 1 to indicate successful transmission } @@ -504,7 +506,6 @@ void RF24::reUseTX(){ /****************************************************************************/ -//This is for when every bit of data is important bool RF24::writeFast( const void* buf, uint8_t len ) { //Block until the FIFO is NOT full. @@ -516,9 +517,7 @@ bool RF24::writeFast( const void* buf, uint8_t len ) while ( (read_register(FIFO_STATUS) & _BV(FIFO_FULL))){ //Blocking only if FIFO is full. This will loop and block until TX is successful if( get_status() & _BV(MAX_RT)){ - write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag reUseTX(); //Set re-transmit - delayMicroseconds(15); //CE needs to stay high for 10us, for TX_REUSE to engage return 0; //Return 0. The previous payload has been retransmitted //From the user perspective, if you get a 0, just keep trying to send the same payload } @@ -565,23 +564,31 @@ void RF24::startWrite( const void* buf, uint8_t len ) } bool RF24::txStandBy(){ - txStandBy(0); + while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ + if( get_status() & _BV(MAX_RT)){ + write_register(STATUS,_BV(MAX_RT) ); + flush_tx(); //Non blocking, flush the data + ce(LOW); //Set STANDBY-I mode + return 0; + } + } + + ce(LOW); //Set STANDBY-I mode + return 1; } -bool RF24::txStandBy(bool block){ +bool RF24::txStandBy(unsigned long timeout){ + + unsigned long start = millis(); while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ if( get_status() & _BV(MAX_RT)){ write_register(STATUS,_BV(MAX_RT) ); - if(block){ + if(timeout > 0){ ce(LOW); //Set re-transmit ce(HIGH); - delayMicroseconds(15); + if(millis() - start > timeout){ ce(LOW); flush_tx(); return 0; } - }else{ - flush_tx(); //Non blocking, flush the data - ce(LOW); //Set STANDBY-I mode - return 0; } } } diff --git a/RF24.h b/RF24.h index 78f5322..35e262c 100644 --- a/RF24.h +++ b/RF24.h @@ -152,13 +152,6 @@ protected: */ uint8_t flush_rx(void); - /** - * Empty the transmit buffer - * - * @return Current value of status register - */ - uint8_t flush_tx(void); - /** * Retrieve the current status of the chip * @@ -270,7 +263,7 @@ public: void stopListening(void); /** - * @note Optimization: Improved performance and reliability + * @note Optimization: Improved performance slightly * Write to the open writing pipe * * Be sure to call openWritingPipe() first to set the destination @@ -293,56 +286,57 @@ public: bool write( const void* buf, uint8_t len ); /** - * @note Optimization: New Command - * Write to the open writing pipe filling up the FIFO buffers - * - * Be sure to call openWritingPipe() first to set the destination - * of where to write to. - * + * @note Optimization: New Command * * This will not block until the 3 FIFO buffers are filled with data. * Once the FIFOs are full, writeFast will simply wait for success or * timeout, and return 1 or 0 respectively. From a user perspective, just * keep trying to send the same data. The library will keep auto retrying * the current payload using the built in functionality. * - * The maximum size of data written is the fixed payload size, see - * getPayloadSize(). However, you can write less, and the remainder - * will just be filled with zeroes. - * * ONLY max retry interrupt flags will be cleared when writeFast is called * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail. + * @endcode + * + * @see txStandBy() + * @see write() + * @see writeBlocking() + * * @param buf Pointer to the data to be sent * @param len Number of bytes to be sent * @return True if the payload was delivered successfully false if not */ bool writeFast( const void* buf, uint8_t len ); - /** - * @note Optimization: New Command - * Write to the open writing pipe - * - * Be sure to call openWritingPipe() first to set the destination - * of where to write to. - * - * This will not block until the 3 FIFO buffers are filled with data or - * a timeout is detected. If so the library will auto retry until a new - * payload is written or the TX buffers are flushed. Interrupts can be - * used to control the timeout period. - * - * This will never return a 0. It will not return until a packet is - * loaded successfully into the FIFO and TX is complete. - * - * The maximum size of data written is the fixed payload size, see - * getPayloadSize(). However, you can write less, and the remainder - * will just be filled with zeroes. - * - * ONLY max retry interrupt flags will be cleared when writeBlocking is called - * - * @param buf Pointer to the data to be sent - * @param len Number of bytes to be sent - * @return True if the payload was delivered successfully false if not - */ - bool writeBlocking( const void* buf, uint8_t len ); + /** + * @note Optimization: New Command + * This function extends the auto-retry mechanism to any specified duration. + * It will not block until the 3 FIFO buffers are filled with data. + * If so the library will auto retry until a new payload is written + * or the user specified timeout period is reached. + * + * ONLY max retry interrupt flags will be cleared when writeBlocking is called + * @code + * Example (Full blocking): + * + * radio.writeBlocking(&buf,32,1000); //Writes 1 payload to the buffers with extended timeout of 1 second + * txStandBy(1000); //Returns 0 if failed after timeout period. 1 if success. + * //Blocks only until user timeout or success. Data flushed on fail. + * @endcode + * @see txStandBy() + * @see write() + * @see writeFast() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param timeout User defined timeout in milliseconds. + * @return True if the payload was delivered successfully false if not + */ + bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout ); /** * @note Optimization: New Command @@ -355,29 +349,42 @@ public: * the manufacturer to drop the radio out of TX or STANDBY-II mode if there is * time enough between sends for the FIFOs to empty. * - * @note This does NOT need to be called when using per-payload noACK commands, - * or when using the regular write command since it is only capable of single - * payload transmission.. - * Per the datasheet, the radio will automatically engage STANDBY-I mode when - * using the W_TX_PAYLOAD_NOACK command. + * Relies on built-in auto retry functionality. * * @code - * Example: + * Example (Partial blocking): + * * radio.writeFast(&buf,32); * radio.writeFast(&buf,32); * radio.writeFast(&buf,32); //Fills the FIFO buffers up - * bool ok = txStandBy(0); //Returns 0 if failed. 1 if success. - * //Blocks only until timeout or success. Data flushed on fail. - * - * Using txStandBy(1) will not return until the data is transmitted. It will never return 0. - * + * bool ok = txStandBy(); //Returns 0 if failed. 1 if success. + * //Blocks only until MAX_RT timeout or success. Data flushed on fail. * @endcode - * + * @see txStandBy(unsigned long timeout) * @return True if transmission is successful * */ - bool txStandBy(); - bool txStandBy(bool block); + bool txStandBy(); + + /** + * @note Optimization: New Command + * + * This function allows extended blocking and auto-retries per a user defined timeout + * @code + * Fully Blocking Example: + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success. + * //Blocks only until user defined timeout or success. Data flushed on fail. + * @endcode + * + * @param timeout Number of milliseconds to retry failed payloads + * @return True if transmission is successful + * + */ + bool txStandBy(unsigned long timeout); /** * Non-blocking write to the open writing pipe used for buffered writes @@ -386,7 +393,9 @@ public: * will remain in TX or STANDBY-II Mode until a txStandBy() command is issued. * This allows the chip to be used to its full potential in TX mode. * + * @see write() * @see writeFast() + * @see startWrite() * @see writeBlocking() * * @param buf Pointer to the data to be sent @@ -401,9 +410,14 @@ public: * @note Optimization: The available functino now checks the FIFO * buffers directly for data instead of relying of interrupt flags. * - * @note: Interrupt flags will not be cleared until a payload is + * @note Interrupt flags will not be cleared until a payload is * actually read from the FIFO * + * @see txStandBy() + * @see startWrite() + * @see write() + * @see writeFast() + * * @return True if there is a payload available, false if none is */ bool available(void); @@ -422,7 +436,7 @@ public: * * @param buf Pointer to a buffer where the data should be written * @param len Maximum number of bytes to read into the buffer - * @return No return value. Use available. + * @return No return value. Use available(). */ void read( void* buf, uint8_t len ); @@ -526,7 +540,7 @@ public: * For dynamic payloads, this pulls the size of the payload off * the chip * - * Optimization: Corrupt packets are now detected and flushed per the + * @note Optimization: Corrupt packets are now detected and flushed per the * manufacturer. * * @return Payload length of last-received dynamic payload @@ -663,7 +677,7 @@ public: * To return to normal power mode, either write() some data or * startListening, or powerUp(). * - * Optimization: The radio will never enter power down unless instructed + * @note Optimization: The radio will never enter power down unless instructed * by the MCU via this command. */ void powerDown(void); @@ -681,10 +695,12 @@ public: * Just like write(), but it returns immediately. To find out what happened * to the send, catch the IRQ and then call whatHappened(). * - * @note Optimization: This function again behaves as it did previously. - * startFastWrite() has been moved to an internal function + * @note Optimization: This function again behaves as it did previously for backwards-compatibility. + * with user code. The library uses startFastWrite() internally. + * This is mainly used for single-payload transactions. * * @see write() + * @see writeFast() * @see startFastWrite() * @see whatHappened() * @@ -708,6 +724,8 @@ public: * * @note This is to be used AFTER auto-retry fails if wanting to resend * using the built-in payload reuse features. + * After issuing reUseTX(), it will keep reending the same payload forever or until + * a payload is written to the FIFO, or a flush_tx command is given. */ void reUseTX(); @@ -735,7 +753,7 @@ public: * * @note Optimization: Calling this function NO LONGER clears the interrupt * flag. The new functionality checks the RX FIFO buffer for an ACK payload - * instead of relying on interrupt flags. + * instead of relying on interrupt flags.Reading the payload will clear the flags. * * @return True if an ack payload is available. */ @@ -766,6 +784,13 @@ public: */ void whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready); + /** + * Empty the transmit buffer + * + * @return Current value of status register + */ + uint8_t flush_tx(void); + /** * Test whether there was a carrier on the line for the * previous listening period. @@ -797,6 +822,11 @@ public: */ bool isValid() { return ce_pin != 0xff && csn_pin != 0xff; } + /** + * @see txStandBy() + */ + bool txStandBy(bool block); + /**@}*/ }; @@ -824,6 +854,18 @@ public: * with the receiver displaying the payload count. (32Byte Payloads) */ +/** + * @example TransferTimeouts.ino + * Updated: TMRh20 + * This example demonstrates the use of and extended timeout period and + * auto-retries/auto-reUse to increase reliability in noisy or low signal scenarios. + * + * Write this sketch to two different nodes. Put one of the nodes into 'transmit' + * mode by connecting with the serial monitor and sending a 'T'. The data + * transfer will begin, with the receiver displaying the payload count and the + * data transfer rate. + */ + /** * @example nordic_fob.pde * diff --git a/examples/GettingStarted/GettingStarted.ino b/examples/GettingStarted/GettingStarted.ino index d74db81..1dfd8ab 100644 --- a/examples/GettingStarted/GettingStarted.ino +++ b/examples/GettingStarted/GettingStarted.ino @@ -89,8 +89,8 @@ void loop(void) unsigned long time = millis(); // Take the time, and send it. This will block until complete printf("Now sending %lu...",time); - bool ok = radio.writeFast( &time, sizeof(unsigned long) );//New function for proper use of FIFO buffers - while( ! radio.txStandBy() ){} //Called when STANDBY-I mode is engaged (User is finished sending) + radio.writeFast( &time, sizeof(unsigned long) ); //New function for proper use of FIFO buffers + bool ok = radio.txStandBy(); //Called when STANDBY-I mode is engaged (User is finished sending) if (!ok) printf("failed.\n\r"); @@ -142,8 +142,8 @@ void loop(void) radio.stopListening(); // First, stop listening so we can talk - radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back. - + radio.writeFast( &got_time, sizeof(unsigned long) ); // Send the final one back. + radio.txStandBy(); radio.startListening(); // Now, resume listening so we catch the next packets. //printf("Sent response.\n\r"); @@ -163,17 +163,16 @@ void loop(void) printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); role = role_ping_out; // Become the primary transmitter (ping out) - //radio.openWritingPipe(pipes[0]); - //radio.openReadingPipe(1,pipes[1]); + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); } else if ( c == 'R' && role == role_ping_out ) { printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); role = role_pong_back; // Become the primary receiver (pong back) - //radio.openWritingPipe(pipes[1]); - //radio.openReadingPipe(1,pipes[0]); + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); } } } -// vim:cin:ai:sts=2 sw=2 ft=cpp \ No newline at end of file diff --git a/examples/GettingStarted/GettingStarted.pde b/examples/GettingStarted/GettingStarted.pde deleted file mode 100644 index bf1851a..0000000 --- a/examples/GettingStarted/GettingStarted.pde +++ /dev/null @@ -1,227 +0,0 @@ -/* - Copyright (C) 2011 J. Coliz - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as published by the Free Software Foundation. - */ - -/** - * Example for Getting Started with nRF24L01+ radios. - * - * This is an example of how to use the RF24 class. Write this sketch to two - * different nodes. Put one of the nodes into 'transmit' mode by connecting - * with the serial monitor and sending a 'T'. The ping node sends the current - * time to the pong node, which responds by sending the value back. The ping - * node can then see how long the whole cycle took. - */ - -#include -#include "nRF24L01.h" -#include "RF24.h" -#include "printf.h" - -// -// Hardware configuration -// - -// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 - -RF24 radio(9,10); - -// -// Topology -// - -// Radio pipe addresses for the 2 nodes to communicate. -const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; - -// -// Role management -// -// Set up role. This sketch uses the same software for all the nodes -// in this system. Doing so greatly simplifies testing. -// - -// The various roles supported by this sketch -typedef enum { role_ping_out = 1, role_pong_back } role_e; - -// The debug-friendly names of those roles -const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; - -// The role of the current running sketch -role_e role = role_pong_back; - -void setup(void) -{ - // - // Print preamble - // - - Serial.begin(57600); - printf_begin(); - printf("\n\rRF24/examples/GettingStarted/\n\r"); - printf("ROLE: %s\n\r",role_friendly_name[role]); - printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); - - // - // Setup and configure rf radio - // - - radio.begin(); - - // optionally, increase the delay between retries & # of retries - radio.setRetries(15,15); - - // optionally, reduce the payload size. seems to - // improve reliability - //radio.setPayloadSize(8); - - // - // Open pipes to other nodes for communication - // - - // This simple sketch opens two pipes for these two nodes to communicate - // back and forth. - // Open 'our' pipe for writing - // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) - - //if ( role == role_ping_out ) - { - //radio.openWritingPipe(pipes[0]); - radio.openReadingPipe(1,pipes[1]); - } - //else - { - //radio.openWritingPipe(pipes[1]); - //radio.openReadingPipe(1,pipes[0]); - } - - // - // Start listening - // - - radio.startListening(); - - // - // Dump the configuration of the rf unit for debugging - // - - radio.printDetails(); -} - -void loop(void) -{ - // - // Ping out role. Repeatedly send the current time - // - - if (role == role_ping_out) - { - // First, stop listening so we can talk. - radio.stopListening(); - - // Take the time, and send it. This will block until complete - unsigned long time = millis(); - printf("Now sending %lu...",time); - bool ok = radio.write( &time, sizeof(unsigned long) ); - - if (ok) - printf("ok..."); - else - printf("failed.\n\r"); - - // Now, continue listening - radio.startListening(); - - // Wait here until we get a response, or timeout (250ms) - unsigned long started_waiting_at = millis(); - bool timeout = false; - while ( ! radio.available() && ! timeout ) - if (millis() - started_waiting_at > 200 ) - timeout = true; - - // Describe the results - if ( timeout ) - { - printf("Failed, response timed out.\n\r"); - } - else - { - // Grab the response, compare, and send to debugging spew - unsigned long got_time; - radio.read( &got_time, sizeof(unsigned long) ); - - // Spew it - printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time); - } - - // Try again 1s later - delay(1000); - } - - // - // Pong back role. Receive each packet, dump it out, and send it back - // - - if ( role == role_pong_back ) - { - // if there is data ready - if ( radio.available() ) - { - // Dump the payloads until we've gotten everything - unsigned long got_time; - bool done = false; - while (!done) - { - // Fetch the payload, and see if this was the last one. - done = radio.read( &got_time, sizeof(unsigned long) ); - - // Spew it - printf("Got payload %lu...",got_time); - - // Delay just a little bit to let the other unit - // make the transition to receiver - delay(20); - } - - // First, stop listening so we can talk - radio.stopListening(); - - // Send the final one back. - radio.write( &got_time, sizeof(unsigned long) ); - printf("Sent response.\n\r"); - - // Now, resume listening so we catch the next packets. - radio.startListening(); - } - } - - // - // Change roles - // - - if ( Serial.available() ) - { - char c = toupper(Serial.read()); - if ( c == 'T' && role == role_pong_back ) - { - printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); - - // Become the primary transmitter (ping out) - role = role_ping_out; - radio.openWritingPipe(pipes[0]); - radio.openReadingPipe(1,pipes[1]); - } - else if ( c == 'R' && role == role_ping_out ) - { - printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); - - // Become the primary receiver (pong back) - role = role_pong_back; - radio.openWritingPipe(pipes[1]); - radio.openReadingPipe(1,pipes[0]); - } - } -} -// vim:cin:ai:sts=2 sw=2 ft=cpp diff --git a/examples/TransferTimeouts/TransferTimeouts.ino b/examples/TransferTimeouts/TransferTimeouts.ino new file mode 100644 index 0000000..65fce99 --- /dev/null +++ b/examples/TransferTimeouts/TransferTimeouts.ino @@ -0,0 +1,189 @@ +/* +TMRh20 2014 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** Reliably transmitting large volumes of data with a low signal or in noisy environments + * This example demonstrates data transfer functionality with the use of auto-retry + and auto-reUse functionality enabled. This sketch demonstrates how a user can extend + the auto-retry functionality to any chosen time period, preventing data loss and ensuring + the consistency of data. + + This sketh demonstrates use of the writeBlocking() functionality, and extends the standard + retry functionality of the radio. Payloads will be auto-retried until successful or the + extended timeout period is reached. + */ + + + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +/************* USER Configuration *****************************/ + +RF24 radio(48,49); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8 +unsigned long timeoutPeriod = 3000; // Set a user-defined timeout period. With auto-retransmit set to (15,15) retransmission will take up to 60ms and as little as 7.5ms with it set to (1,15). + // With a timeout period of 1000, the radio will retry each payload for up to 1 second before giving up on the transmission and starting over + +/***************************************************************/ + +const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate. + +byte data[32]; //Data buffer + +volatile unsigned long counter; +unsigned long rxTimer,startTime, stopTime, payloads = 0; +bool TX=1,RX=0,role=0, transferInProgress = 0; + + +void setup(void) { + + Serial.begin(57600); + printf_begin(); + + radio.begin(); // Setup and configure rf radio + radio.setChannel(1); // Set the channel + radio.setPALevel(RF24_PA_LOW); // Set PA LOW for this demonstration. We want the radio to be as lossy as possible for this example. + radio.setDataRate(RF24_1MBPS); // Raise the data rate to reduce transmission distance and increase lossiness + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.setRetries(2,15); // Optionally, increase the delay between retries. Want the number of auto-retries as high as possible (15) + radio.setCRCLength(RF24_CRC_16); // Set CRC length to 16-bit to ensure quality of data + radio.openWritingPipe(pipes[0]); // Open the default reading and writing pipe + radio.openReadingPipe(1,pipes[1]); + + radio.startListening(); // Start listening + radio.printDetails(); // Dump the configuration of the rf unit for debugging + + printf("\n\rRF24/examples/Transfer Rates/\n\r"); + printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); + + randomSeed(analogRead(0)); //Seed for random number generation + for(int i=0; i<32; i++){ + data[i] = random(255); //Load the buffer with random data + } + radio.powerUp(); //Power up the radio + + +} + + + +void loop(void){ + + + if(role == TX){ + delay(2000); // Pause for a couple seconds between transfers + printf("Initiating Extended Timeout Data Transfer\n\r"); + + unsigned long cycles = 1000; // Change this to a higher or lower number. This is the number of payloads that will be sent. + + unsigned long transferCMD[] = {'H','S',cycles }; // Indicate to the other radio that we are starting, and provide the number of payloads that will be sent + radio.writeFast(&transferCMD,12); // Send the transfer command + if(radio.txStandBy(timeoutPeriod)){ // If transfer initiation was successful, do the following + + startTime = millis(); // For calculating transfer rate + boolean timedOut = 0; // Boolean for keeping track of failures + + for(int i=0; i timeoutPeriod){ // If no data available, check the timeout period + Serial.println("Transfer Failed"); // If per-payload timeout exceeeded, end the transfer + transferInProgress = 0; + }else + if(counter >= payloads){ // If the specified number of payloads is reached, transfer is completed + startTime = millis() - startTime; // Calculate the total time spent during transfer + float numBytes = counter*32; // Calculate the number of bytes transferred + Serial.print("Rate: "); // Print the transfer rate and number of payloads + Serial.print(numBytes/startTime); + Serial.println(" KB/s"); + printf("Payload Count: %d \n\r", counter); + transferInProgress = 0; // End the transfer as complete + } + } + + + } + + // + // Change roles + // + + if ( Serial.available() ) + { + char c = toupper(Serial.read()); + if ( c == 'T' && role == RX ) + { + printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + radio.stopListening(); + role = TX; // Become the primary transmitter (ping out) + } + else if ( c == 'R' && role == TX ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + radio.startListening(); + printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); + role = RX; // Become the primary receiver (pong back) + } + } +} + + diff --git a/examples/TransferTimeouts/printf.h b/examples/TransferTimeouts/printf.h new file mode 100644 index 0000000..b2efd56 --- /dev/null +++ b/examples/TransferTimeouts/printf.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +#ifdef ARDUINO + +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__