Commit 6263bccd authored by TMRh20's avatar TMRh20

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
parent 0ddec525
......@@ -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;
}
}
}
......
......@@ -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.
* 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
*
* Using txStandBy(1) will not return until the data is transmitted. It will never return 0.
*/
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();
bool txStandBy(bool block);
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
*
......
......@@ -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
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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 <SPI.h>
#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
/*
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 <SPI.h>
#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<cycles; i++){ // Loop through a number of cycles
data[0] = i; // Change the first byte of the payload for identification
if(!radio.writeBlocking(&data,32,timeoutPeriod)){ // If retries are failing and the user defined timeout is exceeded
timedOut = 1; // Indicate failure
counter = cycles; // Set the fail count to maximum
break; // Break out of the for loop
}
}
stopTime = millis(); // Capture the time of completion or failure
//This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success
if(timedOut){ radio.txStandBy(); } //Partially blocking standby, blocks until success or max retries. FIFO flushed if auto timeout reached
else{ radio.txStandBy(timeoutPeriod); } //Standby, block until FIFO empty (sent) or user specified timeout reached. FIFO flushed if user timeout reached.
}else{
Serial.println("Communication not established"); //If unsuccessful initiating transfer, exit and retry later
}
float rate = cycles * 32 / (stopTime - startTime); //Display results:
Serial.print("Transfer complete at "); Serial.print(rate); printf(" KB/s \n\r");
Serial.print(counter);
Serial.print(" of ");
Serial.print(cycles); Serial.println(" Packets Failed to Send");
counter = 0;
}
if(role == RX){
if(!transferInProgress){ // If a bulk data transfer has not been started
if(radio.available()){
radio.read(&data,32); //Read any available payloads for analysis
if(data[0] == 'H' && data[4] == 'S'){ // If a bulk data transfer command has been received
payloads = data[8]; // Read the first two bytes of the unsigned long. Need to read the 3rd and 4th if sending more than 65535 payloads
payloads |= data[9] << 8; // This is the number of payloads that will be sent
counter = 0; // Reset the payload counter to 0
transferInProgress = 1; // Indicate it has started
startTime = rxTimer = millis(); // Capture the start time to measure transfer rate and calculate timeouts
}
}
}else{
if(radio.available()){ // If in bulk transfer mode, and a payload is available
radio.read(&data,32); // Read the payload
rxTimer = millis(); // Reset the timeout timer
counter++; // Keep a count of received payloads
}else
if(millis() - rxTimer > 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)
}
}
}
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment