nRF24L01 connected to an Arduino Pro Mini |
***********Arduino code for transmit module*********************************
//This sketch is from a tutorial video for getting started with the nRF24L01 tranciever module on the ForceTronics YouTube Channel
//the code was leverage from Ping pair example at http://tmrh20.github.io/RF24/pingpair_ack_8ino-example.html
//This sketch is free to the public to use and modify at your own risk
#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include "printf.h" //This is used to print the details of the nRF24 board. if you don't want to use it just comment out "printf_begin()"
const int pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const int pinCSN = 10; //This pin is used to tell the nRF24 whether the SPI communication is a command or message to send out
byte counter = 1; //used to count the packets sent
bool done = false; //used to know when to stop sending packets
RF24 wirelessSPI(pinCE, pinCSN); // Create your nRF24 object or wireless SPI connection
const uint64_t pAddress = 0xB00B1E5000LL; // Radio pipe addresses for the 2 nodes to communicate.
void setup()
{
Serial.begin(57600); //start serial to communicate process
printf_begin(); //This is only used to print details of nRF24 module, needs Printf.h file. It is optional and can be deleted
wirelessSPI.begin(); //Start the nRF24 module
wirelessSPI.setAutoAck(1); // Ensure autoACK is enabled so rec sends ack packet to let you know it got the transmit packet payload
wirelessSPI.enableAckPayload(); // Allow optional ack payloads
wirelessSPI.setRetries(5,15); // Sets up retries and timing for packets that were not ack'd, current settings: smallest time between retries, max no. of retries
wirelessSPI.openWritingPipe(pAddress); // pipe address that we will communicate over, must be the same for each nRF24 module
wirelessSPI.stopListening();
wirelessSPI.printDetails(); // Dump the configuration of the rf unit for debugging
}
void loop()
{
if(!done) { //if we are not done yet
Serial.print("Now send packet: ");
Serial.println(counter); //serial print the packet number that is being sent
unsigned long time1 = micros(); //start timer to measure round trip
//send or write the packet to the rec nRF24 module. Arguments are the payload / variable address and size
if (!wirelessSPI.write( &counter, 1 )){ //if the send fails let the user know over serial monitor
Serial.println("packet delivery failed");
}
else { //if the send was successful
unsigned long time2 = micros(); //get time new time
time2 = time2 - time1; //calculate round trip time to send and get ack packet from rec module
Serial.print("Time from message sent to recieve Ack packet: ");
Serial.print(time2); //print the time to the serial monitor
Serial.println(" microseconds");
counter++; //up the packet count
}
//if the reciever sends payload in ack packet this while loop will get the payload data
while(wirelessSPI.available() ){
char gotChars[5]; //create array to hold payload
wirelessSPI.read( gotChars, 5); //read payload from ack packet
Serial.print(gotChars[0]); //print each char from payload
Serial.print(gotChars[1]);
Serial.print(gotChars[2]);
Serial.println(gotChars[3]);
done = true; //the ack payload signals we are done
}
}
delay(1000);
}
***********Arduino code for receiver module*********************************
//This sketch is from a tutorial video for getting started with the nRF24L01 tranciever module on the ForceTronics YouTube Channel
//the code was leverage from Ping pair example at http://tmrh20.github.io/RF24/pingpair_ack_8ino-example.html
//This sketch is free to the public to use and modify at your own risk
#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include "printf.h" //This is used to print the details of the nRF24 board. if you don't want to use it just comment out "printf_begin()"
const int pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const int pinCSN = 10; //This pin is used to tell the nRF24 whether the SPI communication is a command or message to send out
byte gotByte = 0; //used to store payload from transmit module
bool done = false;
RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI)
const uint64_t pAddress = 0xB00B1E5000LL; //Create a pipe addresses for the 2 nodes to communicate over, the "LL" is for LongLong type
void setup()
{
Serial.begin(57600); //start serial to communicate process
printf_begin(); //This is only used to print details of nRF24 module, needs Printf.h file. It is optional and can be deleted
wirelessSPI.begin(); //Start the nRF24 module
wirelessSPI.setAutoAck(1); // Ensure autoACK is enabled, this means rec send acknowledge packet to tell xmit that it got the packet with no problems
wirelessSPI.enableAckPayload(); // Allow optional payload or message on ack packet
wirelessSPI.setRetries(5,15); // Defines packet retry behavior: first arg is delay between retries at 250us x 5 and max no. of retries
wirelessSPI.openReadingPipe(1,pAddress); //open pipe o for recieving meassages with pipe address
wirelessSPI.startListening(); // Start listening for messages
wirelessSPI.printDetails(); //print details of nRF24 module to serial, must have printf for it to print to serial
}
void loop()
{
if(gotByte >= 9 & !done) { //once we get 10 packets send ack packet with payload telling the transmit module we are done
char cArray[5] = "done"; //create char array to store "done," note that the fifth char is for the null character
wirelessSPI.writeAckPayload(1, cArray, sizeof(cArray)); //send ack payload. First argument is pipe number, then pointer to variable, then variable size
}
//loop until all of the payload data is recieved, for this example loop should only run once
while(wirelessSPI.available() & !done){
wirelessSPI.read( &gotByte, 1 ); //read one byte of data and store it in gotByte variable
Serial.print("Recieved packet number: "); //payload counts packet number
Serial.println(gotByte); //print payload / packet number
}
if(gotByte > 9) done = true; //we are finished so set "done" to true
delay(200);
}
***********Arduino code for Printf.h 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.
*/
/**
* @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__
Nice! Would you please walk through the status information (as seen in 12:51 of the video), line-by-line, to explain what all of the individual numbers mean?
ReplyDeleteThanks for the request. Stepping through the status information would be a little too much to write in the comments section so I would have to do it in a new post. Is there one part in particular that you need to know or just curious in general to learn all the status parts?
DeleteAll the parts, but especially the Tx and Rx address parts. You could start with that and see how far you get before you get tired of typing.
ReplyDeleteBy the way, does here exist an NRF24L01 that's integrated with a low power arduino onto a small form factor board, similar to either the moteino or the Ciseco RF u-328? At the end of the day, that's what I'd prefer to deploy on.
Now that I think of it: cover the status information that you yourself find useful. That way you'd already know it. No sense dwelling on information you don't find useful anway.
ReplyDeleteAnyhow, the reason I ask is that I have a situation where I have screens of numbers on both the Tx and Rx serial monitors, but for some reason either the transmissions aren't working right or they aren't being received right, or both, and I have no idea why, because all tx attempts are reported as failures. Perhaps if I understood the status information better, it might help me troubleshoot the problem.
ReplyDeleteSounds like your modules are not connecting to each other for whatever reason. Could be there is an address issue or did you "start listening" for the receiver or something else. Are you using the code and setup from my video?
DeleteNo, I was using the pingpair_ack example, but from the same library. Funny thing: I powered up the modules again to do some screen captures on the node information, and now they're working perfectly. Go figure. I'm guessing one of the jumper wire connections is flakey.
DeleteAnyhow, I'd still be interested in learning about the status info. Most of the online tutorials run dry after the initial setup.
It does sometimes get blank ACK payloads, though, so I'm not sure why that would be. Does the CRC check apply just to the payload and not to the entire frame? Because if it's to the entire frame, I don't see how it would have gotten an ACK with a blank payload.
DeleteJust to clarify: most of the payloads aren't blank, but a few are.
DeleteHmmm... Can't seem to get 250kbps data rate to work using this library, even tough the default of 1mbps does work. The information screen shows I did set the data rate to 250kbps, but the link doesn't work anymore. Argh...!
ReplyDelete