nRF24/RF24Audio

Audio Receiver/Radio Transmitter on Single RF Module

Febrezio opened this issue · 5 comments

This is a questions about using RF24Audio and RF24 library in same Arduino sketch.
On node A, I want to transmit data (non-audio) to node B then receive audio data on node A from node B.
This is being attempted using one NRF24L01+ module on node A and one NRF24L01+ module on node B.
Is it possible to do both tasks on same RF module:

  1. Use RF24 library to transmit non-audio data to node B
  2. Use RF24Audio library to receive audio data from node A

Right now I'm trying to just test task 1 after calling rfAudio.begin(), but when I add a call to rfAudio.begin() in setup() task 1 no longer receives correct response from node B.

Node B shows it received the expected payload, but node A now always gets null response:
Sent 56924, Got response 0, Round-trip delay 14928 microseconds

Node A (Arduino) Code
RF24 radio(7,8);
RF24Audio rfAudio(radio,1);
const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL};

void setup() {
Serial.begin(115200);
printf_begin();
rfAudio.begin();
radio.begin();
radio.setPALevel(RF24_PA_MAX);
/* Set our radio options to the audio library defaults */
radio.setChannel(1);
radio.setAutoAck(0);
radio.setCRCLength(RF24_CRC_8);
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1, addresses[1]);
radio.printDetails();
radio.startListening();

Serial.println("Setup OK. Begin transmission of audio");

radio.stopListening();

Serial.println(F("Now sending"));

unsigned long start_time = micros();
if (!radio.write( &start_time, sizeof(unsigned long) )) {
Serial.println(F("failed"));
}

radio.startListening(); // Now, continue listening

unsigned long started_waiting_at = micros();
boolean timeout = false;

while ( ! radio.available() ) { // While nothing is received
if (micros() - started_waiting_at > 200000 ) { // If waited longer than 200ms, indicate timeout and exit while loop
timeout = true;
break;
}
}
rfAudio.begin();
if ( timeout ) { // Describe the results
Serial.println(F("Failed, response timed out."));
} else {
unsigned long got_time;
radio.read( &got_time, sizeof(unsigned long) );
unsigned long end_time = micros();

Serial.print(F("Sent "));
Serial.print(start_time);
Serial.print(F(", Got response "));
Serial.print(got_time);
Serial.print(F(", Round-trip delay "));
Serial.print(end_time - start_time);
Serial.println(F(" microseconds"));
}
}

Node B (RPi) Code
I'm using gettingstarted.cpp example that came with RF24 with 2 changes:

// Radio pipe addresses for the 2 nodes to communicate.
//const uint8_t pipes[][6] = {"1Node","2Node"};
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL};

main()
/* Set our radio options to the audio library defaults */
radio.setChannel(1);
radio.setAutoAck(0);
radio.setCRCLength(RF24_CRC_8);

Once you call rfAudio.begin();, the library will automatically handle all received payloads.

I attempted to build in sending commands/data along with the audio library, but it was difficult and didn't work very well.

See https://github.com/TMRh20/RF24Audio/blob/master/RF24Audio.cpp#L298
If a payload with first character 'r' is received when not streaming, the receiver calls the TX() function. This could be modified to call a custom function, read the data, etc. but is only provided as-is.

Thank you for your quick reply.
I'll have to come back to revising and testing RF24Audio later.

I've done this in an easier way using Arduino Due - http://tmrh20.github.io/AAAudio/index.html

It can manage recording from a microphone & transmitting while receiving audio data, and commands are separated from audio data by sending them to separate pipes/addresses.

In the included example, the microphone data can simply be replaced with other data. I'm thinking this would be pretty difficult on AVR devices.

I got this to work modifying handleRadio() as you previously suggested.
This works for my use case and I'm not seeing any problems yet.

// I ended up adding another case inside handleRadio() and some things for convenience

char message[buffSize]; // Holds incoming commands
bool isMessageAvailable;
...
switch(buffer[0][0]){ 
...
case 'I': 
    if(buffer[0][1] == 'N' && buffer[0][2] == 'C') { 
        int i = 3;
        char c;
        while (i < buffSize) {
            c = buffer[0][i];
            message[i++] = c;
        }
        isMessageAvailable = 1;
    }
    break;
...
}
...
void RF24Audio::readMessage(char* buf, uint8_t len ) {
    // Fetch the payload
int i = 0;
while( i < len) {
    buf[i] = message[i++];
}
isMessageAvailable = 0;
}

bool RF24Audio::messageAvailable() {
return isMessageAvailable;
}

// In my Arduino (UNO) sketch I use this method when I'm ready to send command to RPi to send back audio

void getAudio() {
  // Switch to TX mode to send data
  rfAudio.transmit();

  unsigned long start_time = micros();
  unsigned char message[32] = {'I', 'N', 'C', 'B', 'A', 'D'};  

  // Send command to RPi
  if (!radio.write( &message, 32 )) {
    Serial.println(F("failed"));
  }

 // Switch to RX mode to listen for incoming audio data 
  rfAudio.receive();
}

// If I am expecting a command to be sent back from my RPi instead of audio

while( !rfAudio.messageAvailable() ) {
    // wait
}
rfAudio.readMessage(&buffer,32);

Hi ..great project . I am college student and I am doing same project as what u did. So I wanted to know that I am using android phone to give input to preamp circuit but preamp circuit is not working for me .also which transistor and capacitor u use . Second problem is that there r so many codes in link provided by you

https://github.com/TMRh20/RF24Audio/archive/master.zip

I am newbie in coding so please tell me which code I need to upload in transmitter side and which in receiver side

Also I have read all comments in this page. You were taking about uncomment #define speakertx in config.h to get output in transmitter side so after doing this which code I have to upload ....plzzz I have deadline on 29 nov 2016 ..