Table of Contents
Introduction
Arduinos are great for many reasons, one of them being their ability to wire up to almost anything. But there are times when you want to connect to your Arduino without using any wires, and when you do get the desire to go wireless there are several methods to choose from.
In this article (and in the corresponding video) I will examine one method of Arduino wireless communications, the nRF24L01+ module. This is an inexpensive module that provides 2-way communications using the 2.4 GHz band. This band is free to use for low power devices without a license and in some cases can be useful up to a kilometer (although you should expect much shorter ranges without a special antenna).
The nRF24L01+ is available in a number of different configurations, in this article I’ll look at a couple of the more popular ones. We’ll hook them up and use a very extensive library to facilitate communications between them.
After we get them working we will use them to build something fun – a wireless joystick control for the Robot Car Base that we worked on earlier.
Before we begin let’s examine the nRF24L01+ and some of the factore you need to take into account when designing wireless devices.
Wireless Communications
We have been sending information wirelessly since the late 1880’s, Thomas Edison used a system of Electromagnetic Induction to send telegraph signals from a moving train to a set of wires beside the track. Wireless devices are pretty well a part of our lives and most work using one of the following methods:
- Signals are sent on beams of infrared light
- Signals are sent using radio waves
Radio waves have a number of advantages over beams of infrared light, the most obvious is that radio waves can travel (to a degree) through walls and most other obstructions.
Radio waves are by no means a perfect method of communication, they are subject to interference from a number of sources and can be obstructed by metal or thick walls. But they do serve their purpose in a number of low-speed data applications and are thus perfect or Arduino and Raspberry Pi experimenters who want to build remote controlled devices or who need to send data without wires.
Radio signals are based upon the concept of changing or “modulating” a “carrier wave” that is transmitted wirelessly to a receiver. On the receiving end the carrier wave is stripped off and the signal is “demodulated” to extract the original information from it.
Since these carrier waves can interfere with one another the allotment of them is strictly controlled, and every nation has a government department responsible for regulating them. In the United States it’s the Federal Communications Commission (FCC), in Canada it’s the Canadian Radio and Television Commission (CRTC) and in the UK the radio waves are regulated by the Office of Communications (Ofcom). Using radio carrier frequencies illegally can result in a very stiff fine and is also pretty rude, so just don’t do it.
There are plenty of frequencies available to experimenters like us, one of the most popular is the 2.4 GHz Band.
The 2.4 GHz Band
The 2.4 GHz Industrial, Scientific and Medical (ISM) band has been reserved for unlicensed low-powered devices and this makes it perfect for building remotely controlled Arduino devices. Of course it also makes it perfect for a number of other devices in your house like wireless routers, cordless phones, Bluetooth gizmos and other wireless dodadds.
The band in question runs from 2.400.0 GHz to 2.483.5 GHz and in order to make it possible for multiple devices to coexist it’s broken down into channels. Although there are 14 channels available not every one is legal in every area. Channels 1 to 11 are legal in most every part of the world so you’d be advised to contain your experimenting to those channels.
As communicating on the 2.4 GHz band is a pretty common function there are a number of modules made for exactly that purpose. The one we will be playing with today is possibly the most popular, it’s available for a couple of dollars or less on eBay and Amazon.
The nRF24L01+
The nRF24L01+ is the part number of a common chip used to construct 2.4 GHz transmitters and receivers, or “transceivers”. This chip has been used to create some simple and inexpensive modules that can be used to transmit and receive data using the 2.4 GHz band.
There are a variety of modules available based upon the nRF24L01, I’m going to use two very common ones in this article. If you have a different module it should work fine, just be sure to observe the wiring and especially the power supply requirements.
<INSERT NRF24L01 2 Modules PICTURE>
The two modules I’m using are quite similar and are interchangeable, the difference between them is that one of them has a built in Low Noise Amplifier (LNA) and an external antenna connection. I tend to prefer that one even though it’s a bit more expensive as it can be used for reliable data communications over a pretty fair distance. Unless you live in a castle it will probably be more than sufficient to cover your entire house.
All of the experiments, including the wireless joystick, may be built with either module (they share the same pinouts) but you’ll achieve better range with the model with the external antenna.
nRF24L01 Connections
The nRF24L01 has an 8-pin connector that interfaces it with the outside world. This connector is common between both styles of nRF24L01 modules. Although the nRF24L01 is powered by a 1.9 to 3.9 volt supply the logic pins are 5-volt tolerant so they can be used directly with an Arduino or other 5-volt logic microcontroller.
SPI Bus
The nRF24L01 communicates using the Serial Peripheral Interface or SPI bus. This is a standard bus that is used by many microcontrollers and microcomputers including the Arduino and the Raspberry Pi.
The SPI bus uses a concept of a Master and Slave, in most common applications the microcontroller or microcomputer is the Master and the nRF24L01 is the Slave. Unlike the I2C bus the number of slaves on the SPI bus is limited, on the Arduino Uno you can use a maximum of two SPI slaves.
The SPI bus is a bidirectional bus, meaning that the master and slave can transmit and receive simultaneously, however the library we will be using with the nRF24L01 doesn’t do that.
Each slave device needs to be selected by the master in order for it to communicate. Only one slave can communicate at any given time. The nRF24L01 and other slave devices have an Interrupt pin that can alert the master when they need to communicate but the library we will be using today ignores that so in our applications we won’t be connecting the interrupt pin to the Arduino.
Module Connections
The connections to the nRF24L01 module are as follows:
- GND. This is the Ground Pin. It is usually marked by encasing the pin in a square so it can be used as a reference for identifying the other pins.
- VCC. The positive voltage. This can be anywhere from 1.9 to 3.9 volts. It os NOT 5-volt tolerant!
- CE. Chip Enable, an active-high pin. When selected the nRF24L01 will either transmit or receive, depending upon which mode it is currently in.
- CSN. Chip Select Not. Thi is an active-low pin, it is the pin that the SPI bus uses to select the nRF24L01 slave.
- SCK. The Clock pin, an external clock source provided by the SPI bus Master.
- MOSI. Master Out Slave In. The input to the nRF24L01.
- MISO. Master In Slave Out. The output from the nRF24L01.
- IRQ. The Interrupt output pin.
The style of nRF24L01 that uses an external antenna also has an SMA connector for attaching the antenna.
Power Supply Considerations
Because the nRF24L01 has a power supply range of 1.9 – 3.9 volts it can be battery powered. It is also common to power the module with a 3.3 volt power supply.
When selecting a power supply it should be noted that the nRF24L01 can consume a fair amount of current when transmitting at its highest power. Your power supply should be capable of providing at least 300 mA of current.
Noise on the power supply can also cause problems with the nRF24L01. It is advised to place a filter capacitor (100 microfarads is ideal) across the power supply lines as physically close to the nRF24L01 module as possible to eliminate power supply noise.
Another way to resolve the power supply issues, and the one I suggest you employ, is to use an Adapter Module for your nRF24L01.
nRF24L01 Adapter Module
The nRF24L01 Adapter Module is a very inexpensive prototyping board that simplifies working with the nRF24L01. I recommend you use one and I show it in all the schematics included in this article.
The adapter module has an 8-pin female connector to allow you to plug in an nRF24L01, it can accommodate either the module with the =integrated or external antenna. It also has a 6-pin male connector for the SPI and Interrupt connections and a 2-pin connector for power input.
The adapter module has its own 3.3 volt voltage regulator and a set of filter capacitors, so you can power it with a 5-volt power supply. Assuming your power supply has the required current capability the adapter module will resolve all of the power supply considerations mentioned above.
Since these modules are available for about a dollar a piece there is no real reason why you shouldn’t use one. They can make the difference between success and failure with your nRF24L01 design.
nRF24L01+ and Arduino
In our experiments we will be using two nRF24L01 modules with a couple of Arduino Unos. You could of course use another model of Arduino, if you do however you may need to change the pinouts as different Arduino models use different pins for the SPI bus.
I’ll describe the pinouts for both the Arduino Uno and the Arduino Mega 2560 here. Going forward (in in the schematics) I’ll only be using an Arduino Uno so if you are using a Mega 2560 you’ll need to substitute pin numbers accordingly. Our Robot Car project was based around an Arduino Uno, this is the project that we will be modifying to use the wireless joystick with.
Arduino Libraries and Connections
As with other radio modules there are a number of libraries available for the nRf24l)1. Using a library will really simplify creating projects with these modules.
The following libraries will all work with the nRF24L01+ modules:
- TMRh20 – This library has been around for several years. It is great for creating secure wireless communications devices. You can read more on the TMRh20 Project Blog and get the latest version on the TMRh20 GitHub repository fork for Arduino devices.
- RF24 – This is an old standard and has been used in many nRF24L01 projects. It has been superseded by the RadioHead and TMRh20 libraries.
- Mirf Library – Based on the Tinkerer library. This is a much older library so you won’t find too many projects based upon it anymore.
- RadioHead – This is a modern library with many advanced features, capable of supporting many RF modules.
In the experiments we will be performing and for our wireless joystick project we will be using the RadioHead library.
Please note that not all of the libraries listed above use the came connections to the Arduino, and that the connections differ depending upon which type of Arduino you are using.
RadioHead Library
RadioHead is a library written by Mike McCauley for the Airspayce company. I used it in a previous article, Using Inexpensive 433MHz Transmit and Receive Modules with Arduino.
This is an advanced library which allows many methods of packet radio communications between RF modules like the nRF24L01. It contains many different drivers for different RF modules, the driver for the nRF24L01 is the RH_NRF24 driver.
You can learn more about the RadioHead library and download the ZIP file that you will need to install in in your Arduino IDE on the RadioHead website. Look for the link to the ZIP file near the top of the description on the page.
Once you download the ZIP file you will need to install it in your Arduino IDE. This is a very simple process:
- Open the Arduino IDE.
- Select Sketch from the top menu bar,
- Select Include Library from the Sketch menu drop-down.
- Select Add .ZIP Library from the Include Library sub-menu.
- Use the dialog box to select the ZIP file you have downloaded.
- The RadioHead library will be installed.
After you have the RadioHead library installed in your Arduino IDE you are ready to begin the experiments with the nRF24L01.
Hooking up the Arduinos
The RadioHead library comes with a number of sample sketches that illustrate its use. We will begin our experiments with a few of these sketches, then we’ll modify a couple of them for our joystick project.
Here are the connections you will need to make for an Arduino Uno:
Note that you will need to make two of these circuits! We will refer to one of the circuits as the Server and one as the Client. The wiring for both is identical.
Also note that I’m illustrating the schematic using a nRF24L01 Adapter Module which has its own voltage regulator to supply the 3.3 volts to the nRF24L01. You can wire directly to the nRF24L01 itself if you wish but you’ll need to use the 3.3 volt output from your Arduino and not the 5 volt output (which will likely destroy your nRF24L01 module).
Note that many Arduino clones don’t have sufficient current on the 3.3 volt output for the nRF24L01. Even if yours does it’s advisable to use a filter capacitor across the power supply lines. But again your best bet is to simply use the nRF24L01 Adapter Module and save yourself a lot of grief and frustration!
If you are using an Arduino Mega 2560 then the pinouts for the RadioHead library are a bit different:
- GND. This is still Ground of course so it goes to one of the Mega 2560 ground pins.
- VCC. Again this is still a power supply connection. See the notes above regarding which voltage to use.
- CE. This is the same as the Arduino Uno, it goes to pin 8 on the Mega 2560.
- CSN. Connect this to output pin 53 on the Mega 2560.
- SCK. Connect this to output pin 52 on the Mega 2560.
- MOSI. This goes to pin 51 on the Mega 2560.
- MISO. Finally this goes to pin 50 on the Mega 2560.
Note that the IRQ pin on the nRF24L01 is not used with either of the Arduino boards as it’s ignored by the RadioHead library.
Once you have everything hooked up you are ready to run the first sketches.
RadioHead Sample Sketch – Client & Server
The first sketches we will be running are the basic client and server examples included with the RadioHead library. You can find and load them as follows:
- Open the Arduino IDE (you may have already done this).
- Open the File menu from the top menu bar.
- Select Examples. A sub-menu will be displayed.
- Scroll down the Examples sub-menu to the section at the bottom titled Examples from Custom Libraries.
- Select RadioHead from the menu. Another sub-menu will appear beside this one.
- Select nrf24 from the RadioHead sub-menu.
- A list of example sketches for the RadioHead RH_NRF24 Driver will be displayed.
There are two sketches we need to load, one on each Arduino. If you don’t have the luxury of having two computers then you can do these individually using one computer.
The sketches we need are as follows:
- On the Server Arduino load the nrf24_server sketch.
- On the Client computer load the nrf24_client sketch.
The sketches are very well commented so I’ll just go over some of the essential elements of the here.
Each sketch includes the RadioHead RH_NRF24 library as well as the Arduino SPI library. They both then declare an instance of the radio driver. If you want to change the wiring or use a different type of Arduino you can add optional parameters when declaring the driver.
After that they both move into the Setup routine, which begins by setting up the serial monitor and initializing the driver. Afterwards the setChannel method is called to change the radio channel from the default channel (which is channel 2) to channel 1. You can experiment with different channels if you find any 2.4 GHz devices you have (i.e wireless mice) interfere with the experiment.
You can also add parameters to change the data rate and transmit power of the module. A slower data rate will result in a longer range of operation. Just be sure to keep the data rate and channel the same between the server and client.
We then proceed to the loop.
On the server side the loop starts by looking for a message from the client. If it is received it is placed into a buffer and then printed to the serial monitor. After that a reply “And hello back to you” is placed into an array and is sent to the client.
On the client side the loop begins in the opposite fashion. A message “Hello World” is placed into an array and is sent to the server. We then wait to receive a message from the client (the “And hello back to you” message). If/when we receive the message it gets printed out to the serial monitor.
If you are lucky enough to have two computers you can open both serial monitor and observe the interaction between the server and client. If you only have one computer then I suggest you power one Arduino with a battery or USB power supply while you use your computer to power and monitor the other one.
While this is a very basic sketch it does illustrate how the RadioHead library makes it easy to work with the nRF24L01. And it also has a practical use – you can use it (with one Arduino battery powered) to determine the range you can achieve with your two modules. If you have both the modules with integrated antennas and the ones with external antennas you’ll soon see how vastly superior the external antenna modules really are.
RadioHead Sample Sketch – Reliable Datagram
The previous sketches work well and for many applications they are all you’ll ever need. But if you have a situation where you’re transmitting data that simply must be received without errors then you’ll want to look at another method.
This can be a requirement when you are breaking up a large file into several small bits. The transmitting end needs to make sure that the receiving end has received every bit intact. If it isn’t then the data needs to be resent.
Data transfer on the Internet works using this principle.
The RadioHead Reliable Datagram method of exchanging data also uses this method of verifying data integrity. It doesn’t require any special coding on either end as the Reliable Datagram library does it all for you in the background. Let’s look at it now.
For this experiment you won’t need to make any wiring changes as the hookup is identical to the previous experiment.
Go back into the RadioHead Library Example sketches for nrf24 and select the following two sketches:
- On the Server Arduino load the nrf24_reliable_datagram_server sketch.
- On the Client Arduino load the nrf24_reliable_datagram_client sketch.
Again these sketches are well commented and they also have many similarities to the sketches we just looked at, so I’ll mostly discuss the differences here.
Aside from the two libraries loaded in the previous sketches these sketches also load the RadioHead RHReliableDatagram library.
Afterwards two constants are defined, a CLIENT_ADDRESS and SERVER_ADDRESS. These addresses are not radio channels, instead they are addresses used within the datagram packets exchanged between the server and client.
After creating an instance of the radio driver each sketch set up a datagram manager using one of the addresses defined above (this is where the server and client differ).
In the setup routine the serial monitor is setup and the datagram manager is initialized.
Outside of the setup routine and before the loop an array is defined with the data to be sent and a buffer is defined.
In the loop the operation is very similar to the previous sketches. The server waits for a message to be received from the client, prints it to the serial monitor and then sends a message of its own. The client does the same in reverse.
One thing you will notice in the serial monitor is that both sides print out the address contained in the received packet.
Try out the demo and see the results. At far range you’ll occasionally notice a slight delay in receiving data, this will occur when packets drop off and need to be resent.
As with the previous sketches this one works very well. We will modify this sketch now to send some joystick data and then use it to build our wireless joystick.
Joystick Demo
The two previous sets of sketches illustrated how to exchange text data like “Hello World” and “And hello back to you”, which in itself can be useful. But in many situations you’ll want to exchange numerical data wirelessly between two Arduinos. An example of this would be sending data from a remote sensor to a base station.
In our next experiment we will send data from a joystick to the remote receiver. Each axis of the joystick will be sent as as single byte along with a “dummy byte” whose use I will explain in due time. Depending upon the position of the joystick the values of the axis data wil range from 0 to 255.
You can of course use this sketch to send other sensor data, it doesn’t need to be from a joystick. Your imagination is the only limitation here.
Each sketch is a modified version of the Reliable Datagram sketches we saw earlier, you’ll recognize a lot of the code. No sense in reinventing the wheel!
Before we get started you’ll need to take one of the Arduinos and add a joystick to it. The hookup is shown below:
As you can see the joystick hookup is very simple. If you don’t have a joystick just use two potentiometers as that’s really all that an analog joystick is – a pot for the x-axis and another one for the y-axis. Each control is connected to one of the Arduino’s analog inputs.
On the other end just leave the Arduino and nRF24L01 wired as they are, the only thing you’ll need to change is the sketch.
Here is the sketch for the joystick side of things. Note that it is based upon the RadioHead Reliable Datagram Client sketch, that was just an arbitrary choice on my part as I could have just as easily used the server sketch.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
/* nRF24L01+ Joystick Transmitter nrf24l01-joy-xmit-demo.ino nRF24L01+ Transmitter with Joystick Use with Joystick Receiver Demo DroneBot Workshop 2018 https://dronebotworkshop.com */ // Include RadioHead ReliableDatagram & NRF24 Libraries #include <RHReliableDatagram.h> #include <RH_NRF24.h> // Include dependant SPI Library #include <SPI.h> // Define Joystick Connections #define JoyStick_X_PIN A0 #define JoyStick_Y_PIN A1 // Define addresses for radio channels #define CLIENT_ADDRESS 1 #define SERVER_ADDRESS 2 // Create an instance of the radio driver RH_NRF24 RadioDriver; // Sets the radio driver to NRF24 and the client address to 1 RHReliableDatagram RadioManager(RadioDriver, CLIENT_ADDRESS); // Declare unsigned 8-bit joystick array uint8_t joystick[3]; // Define the Message Buffer uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN]; void setup() { // Setup Serial Monitor Serial.begin(9600); // Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBm if (!RadioManager.init()) Serial.println("init failed"); } void loop() { // Print to Serial Monitor Serial.println("Reading joystick values "); // Read Joystick values and map to values of 0 - 255 joystick[0] = map(analogRead(JoyStick_X_PIN), 0, 1023, 0, 255); joystick[1] = map(analogRead(JoyStick_Y_PIN), 0, 1023, 0, 255); joystick[2] = 100; //Display the joystick values in the serial monitor. Serial.println("-----------"); Serial.print("x:"); Serial.println(joystick[0]); Serial.print("y:"); Serial.println(joystick[1]); Serial.println("Sending Joystick data to nrf24_reliable_datagram_server"); //Send a message containing Joystick data to manager_server if (RadioManager.sendtoWait(joystick, sizeof(joystick), SERVER_ADDRESS)) { // Now wait for a reply from the server uint8_t len = sizeof(buf); uint8_t from; if (RadioManager.recvfromAckTimeout(buf, &len, 2000, &from)) { Serial.print("got reply from : 0x"); Serial.print(from, HEX); Serial.print(": "); Serial.println((char*)buf); } else { Serial.println("No reply, is nrf24_reliable_datagram_server running?"); } } else Serial.println("sendtoWait failed"); delay(100); // Wait a bit before next transmission } |
The sketch starts in the same way as the RadioHead Reliable Datagram sketches, it loads the required libraries. We also define the inputs used by the joystick, as well as client and server addresses for the reliable datagram packets.
We then define an 8-bit unsigned integer array called “joystick” with three elements:
- joystick[0] is the x-axis value.
- joystick[1] is the y-axis value.
- joystick[2] is the “dummy” value.
The only reason for sending the “dummy” value is to have a third byte as our final wireless joystick sketch will use this byte to indicate the motor direction. By defining it in this demonstration sketch we can use the receiver we build here to troubleshoot the final product if necessary.
I assigned a value of 100 to the dummy value, you can assign pretty well any value between 0 and 255. It’s just there to test data integrity right now.
The setup routine is identical to the RadioHead Reliable Datagram example.
In the loop we start the serial monitor as we will use it to monitor joystick values. We then proceed to get those joystick values using an Arduino analogRead function on each of the joystick analog inputs.
As the Arduino’s analog to digital converter is a 10-bit converter we will get a value of 0 to 1023 back from each joystick. We use the Arduino map command to convert this into a range of 0 to 255. Each of the hvalues is assigned to its respective element in the joystick array.
The remainder of the sketch is pretty well identical to the Reliable Datagram sketch. The array is sent to the server end and we wait to see if we get a reply. Then we do it all over again.
The other end (i.e. the “joystick receiver”) is even simpler. Here is the sketch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
/* nRF24L01+ Joystick Receiver Demo nrf24l01-joy-rcv-demo.ino nRF24L01+ Receiver with Joystick Decode Use with Joystick Transmitter Demo DroneBot Workshop 2018 https://dronebotworkshop.com */ // Include RadioHead ReliableDatagram & NRF24 Libraries #include <RHReliableDatagram.h> #include <RH_NRF24.h> // Include dependant SPI Library #include <SPI.h> // Define addresses for radio channels #define CLIENT_ADDRESS 1 #define SERVER_ADDRESS 2 // Create an instance of the radio driver RH_NRF24 RadioDriver; // Sets the radio driver to NRF24 and the server address to 2 RHReliableDatagram RadioManager(RadioDriver, SERVER_ADDRESS); // Define a message to return if values received uint8_t ReturnMessage[] = "JoyStick Data Received"; // Define the Message Buffer uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN]; void setup() { // Setup Serial Monitor Serial.begin(9600); // Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBm if (!RadioManager.init()) Serial.println("init failed"); } void loop() { if (RadioManager.available()) { // Wait for a message addressed to us from the client uint8_t len = sizeof(buf); uint8_t from; if (RadioManager.recvfromAck(buf, &len, &from)) //Serial Print the values of joystick { Serial.print("got request from : 0x"); Serial.print(from, HEX); Serial.print(": X = "); Serial.print(buf[0]); Serial.print(" Y = "); Serial.print(buf[1]); Serial.print(" Z = "); Serial.println(buf[2]); // Send a reply back to the originator client, check for error if (!RadioManager.sendtoWait(ReturnMessage, sizeof(ReturnMessage), from)) Serial.println("sendtoWait failed"); } } } |
The only difference between this sketch and the RadioHead Reliable Datagram server sketch is that we are displaying numerical values in the received data array instead of text. We label these as X, Y and Z:
- X is the x-axis reading.
- Y is the y-axis reading.
- Z is the “dummy value”.
After loading bnoth sketches run them, with at least the receiver connected to a computer so you can observe the serial monitor. You should observe the values change as you move the joystick.
Robot Car Remote
So now we can see how we can send joystick values. It’s time to put it all together and create our Robot Car remote joystick.
On the joystick side you have already done the wiring, all you’ll need to change is the sketch. On the other end though you’ll need a robot car!
If you followed the instructions in the previous article “Build a Robot Car with Speed Sensors” then you already have a robot car. If not then go and see that article for instructions on putting together a robot car using an inexpensive kit.
As this project doesn’t use the speed sensors you can ignore that part. If you already have built the robot car then just leave it as it is, you don’t need to remove the speed sensors.
If you did build the original car there are some changes you will need to make, specifically in how the L298N H-Bridge motor controller is hooked up. The original design uses some of the pins required by the nRF24L01 so it needs to be required.
Here is the new Robot Car schematic:
The connections to the nRF24L01 module are exactly the same as they have been in our other experiments, no surprise there. You can use any type of nRF24L01 module but I strongly recommend using the model with the external antenna for improved performance, at least on the car side.
Using an Analog Pin as a Digital Pin
On the motor side you’ll notice that the pins for Motor A have been moved when compared to the original design. One of them might surprise you – the L289N H-Bridge IN1 pin is connected to the Arduino analog pin A0. Why an analog pin?
If you look at the specs of the ATMega328, which is the heart of the Arduino Uno, you’ll understand why I used A0. It turns out the the “analog” pins on an Arduino can also function quite well as digital I/O pins.
I needed an extra pin for my L298N motor controller and I had a few choices:
- I didn’t want to use pins 2 or 3 as the Robot Car uses these for the speed sensors. Even though the sensors are not part of this design I wanted to keep them free.
- Pins 1 and 2 might look promising but they are also special pins – they are used as the RX and TX lines for the serial interface. I wanted to keep them free, also due to internal reasons they won’;t work very well in this application anyway.
- I chose to use pin A0. Its and analog pin but it’s also digital I/O pin #14 on the Arduino Uno.
As long as the pin is defined as an output in code it will work fine.
Once you have the car wired up all that remains is to load the code. We will look at the joystick code first.
Joystick Transmitter Sketch
As you might expect the remote joystick sketch is very similar to the joystick demo sketch we looked at earlier. Her it is in all its glory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
/* nRF24L01+ Joystick Transmitter nrf24l01-joy-xmit-car.ino nRF24L01+ Transmitter with Joystick for Robot Car Use with Joystick Receiver for Robot Car DroneBot Workshop 2018 https://dronebotworkshop.com */ // Include RadioHead ReliableDatagram & NRF24 Libraries #include <RHReliableDatagram.h> #include <RH_NRF24.h> // Include dependant SPI Library #include <SPI.h> // Define Joystick Connections #define joyVert A0 #define joyHorz A1 // Define Joystick Values - Start at 512 (middle position) int joyposVert = 512; int joyposHorz = 512; // Define addresses for radio channels #define CLIENT_ADDRESS 1 #define SERVER_ADDRESS 2 // Create an instance of the radio driver RH_NRF24 RadioDriver; // Sets the radio driver to NRF24 and the client address to 1 RHReliableDatagram RadioManager(RadioDriver, CLIENT_ADDRESS); // Declare unsigned 8-bit motorcontrol array // 2 Bytes for motor speeds plus 1 byte for direction control uint8_t motorcontrol[3]; // Define the Message Buffer uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN]; void setup() { // Setup Serial Monitor Serial.begin(9600); // Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBm if (!RadioManager.init()) Serial.println("init failed"); // Set initial motor direction as forward motorcontrol[2] = 0; } void loop() { // Print to Serial Monitor Serial.println("Reading motorcontrol values "); // Read the Joystick X and Y positions joyposVert = analogRead(joyVert); joyposHorz = analogRead(joyHorz); // Determine if this is a forward or backward motion // Do this by reading the Verticle Value // Apply results to MotorSpeed and to Direction if (joyposVert < 460) { // This is Backward // Set Motors backward motorcontrol[2] = 1; //Determine Motor Speeds // As we are going backwards we need to reverse readings motorcontrol[0] = map(joyposVert, 460, 0, 0, 255); motorcontrol[1] = map(joyposVert, 460, 0, 0, 255); } else if (joyposVert > 564) { // This is Forward // Set Motors forward motorcontrol[2] = 0; //Determine Motor Speeds motorcontrol[0] = map(joyposVert, 564, 1023, 0, 255); motorcontrol[1] = map(joyposVert, 564, 1023, 0, 255); } else { // This is Stopped motorcontrol[0] = 0; motorcontrol[1] = 0; motorcontrol[2] = 0; } // Now do the steering // The Horizontal position will "weigh" the motor speed // Values for each motor if (joyposHorz < 460) { // Move Left // As we are going left we need to reverse readings // Map the number to a value of 255 maximum joyposHorz = map(joyposHorz, 460, 0, 0, 255); motorcontrol[0] = motorcontrol[0] - joyposHorz; motorcontrol[1] = motorcontrol[1] + joyposHorz; // Don't exceed range of 0-255 for motor speeds if (motorcontrol[0] < 0)motorcontrol[0] = 0; if (motorcontrol[1] > 255)motorcontrol[1] = 255; } else if (joyposHorz > 564) { // Move Right // Map the number to a value of 255 maximum joyposHorz = map(joyposHorz, 564, 1023, 0, 255); motorcontrol[0] = motorcontrol[0] + joyposHorz; motorcontrol[1] = motorcontrol[1] - joyposHorz; // Don't exceed range of 0-255 for motor speeds if (motorcontrol[0] > 255)motorcontrol[0] = 255; if (motorcontrol[1] < 0)motorcontrol[1] = 0; } // Adjust to prevent "buzzing" at very low speed if (motorcontrol[0] < 8)motorcontrol[0] = 0; if (motorcontrol[1] < 8)motorcontrol[1] = 0; //Display the Motor Control values in the serial monitor. Serial.print("Motor A: "); Serial.print(motorcontrol[0]); Serial.print(" - Motor B: "); Serial.print(motorcontrol[1]); Serial.print(" - Direction: "); Serial.println(motorcontrol[2]); //Send a message containing Motor Control data to manager_server if (RadioManager.sendtoWait(motorcontrol, sizeof(motorcontrol), SERVER_ADDRESS)) { // Now wait for a reply from the server uint8_t len = sizeof(buf); uint8_t from; if (RadioManager.recvfromAckTimeout(buf, &len, 2000, &from)) { Serial.print("got reply from : 0x"); Serial.print(from, HEX); Serial.print(": "); Serial.println((char*)buf); } else { Serial.println("No reply, is nrf24_reliable_datagram_server running?"); } } else Serial.println("sendtoWait failed"); delay(100); // Wait a bit before next transmission } |
Those of you who went through the “Controlling DC Motors with the L298N Dual H-Bridge and an Arduino” article may recognize some of the code here as it’s taken from the sketch I used to demo a joystick with a robot car (that one used a wire).
We start by defining our libraries as we did before. Then we define the analog pins used for the joystick inputs as well as a couple of variables that hold values of those inputs.
The real difference in this sketch is what we do with those values. We want the joystick to operate as follows:
- If we push the joystick forward the car should go forward. The further we push it the faster it should go.
- If we pull the joystick back towards us the car should run in reverse. The further we pull it back the faster it should go.
- If we move it to the left the car should steer left.
- If we move it to the right the car should steer right.
- If we leave the joystick in the center position then the car should not move at all.
I established the “middle” of both the horizontal and vertical travel of the joystick to have values between 460 and 564. The exact middle would of course be 511.5 but we are using integers and we also have to consider that two dollar joysticks are not the most precision instruments available.
If you follow the sketch through you should see the logic in this. We determine if the vertical joystick is above 564 and if it is we are going to drive forward. So we set the motorcontrol[2] variable to a value of 0, which in this sketch means “forward”.
If our vertical joystick is below 460 then we set motorcontrol[2] to 1 to indicate we want to go backwards.
We then use the Arduino map function to map the joystick values to a value in the 0 to 255 range for the motor speeds, which are assigned to the motorcontrol[0] and motorcontrol[1] variables.
The horizontal control functions in the same manner, except it applies an offset to the speed values to make one motor spin faster than the other one.
We then send the three variables in the array off to the transmitter, just like we did in the joystick demo sketch.
Joystick Receiver Sketch
The receiver sketch, the one that runs on the car itself, is actually pretty simple. Here it is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
/* nRF24L01+ Joystick Receiver for Robot Car nrf24l01-joy-rcv-car.ino nRF24L01+ Receiver and L298N driver for Robot Car Use with Joystick Transmitter for Robot Car DroneBot Workshop 2018 https://dronebotworkshop.com */ // Include RadioHead ReliableDatagram & NRF24 Libraries #include <RHReliableDatagram.h> #include <RH_NRF24.h> // Include dependant SPI Library #include <SPI.h> // Define addresses for radio channels #define CLIENT_ADDRESS 1 #define SERVER_ADDRESS 2 // Motor A Connections int enA = 9; int in1 = 14; int in2 = 4; // Motor B Connections int enB = 5; int in3 = 7; int in4 = 6; // Create an instance of the radio driver RH_NRF24 RadioDriver; // Sets the radio driver to NRF24 and the server address to 2 RHReliableDatagram RadioManager(RadioDriver, SERVER_ADDRESS); // Define a message to return if values received uint8_t ReturnMessage[] = "JoyStick Data Received"; // Define the Message Buffer uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN]; void setup() { // Setup Serial Monitor Serial.begin(9600); // Set all the motor control pins to outputs pinMode(enA, OUTPUT); pinMode(enB, OUTPUT); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); // Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBm if (!RadioManager.init()) Serial.println("init failed"); } void loop() { if (RadioManager.available()) { // Wait for a message addressed to us from the client uint8_t len = sizeof(buf); uint8_t from; if (RadioManager.recvfromAck(buf, &len, &from)) { //Serial Print the values of joystick //Serial.print("got request from : 0x"); //Serial.print(from, HEX); //Serial.print(": MotorA = "); //Serial.print(buf[0]); //Serial.print(" MotorB = "); //Serial.print(buf[1]); //Serial.print(" Dir = "); //Serial.println(buf[2]); // Set Motor Direction if (buf[2] == 1) { // Motors are backwards digitalWrite(in1, LOW); digitalWrite(in2, HIGH); digitalWrite(in3, LOW); digitalWrite(in4, HIGH); }else{ // Motors are forwards digitalWrite(in1, HIGH); digitalWrite(in2, LOW); digitalWrite(in3, HIGH); digitalWrite(in4, LOW); } // Drive Motors analogWrite(enA, buf[1]); analogWrite(enB, buf[0]); // Send a reply back to the originator client, check for error if (!RadioManager.sendtoWait(ReturnMessage, sizeof(ReturnMessage), from)) Serial.println("sendtoWait failed"); } } } |
Essentially this is the same receiver sketch we have used in the last demo with the addition of variables to define the motor connections. Note that we use Arduino pin “14” for variable in1, this is of course the analog A0 pin. You could actually substitute an “A0” here if you wish and it will work just fine.
In the setup we define the motor controller pins as outputs. Note that the pins used for the two L298N enable lines need to be capable of PWM as that’s how the motor speed is regulated.
You may notice I have remarked out all of the serial monitor statements. They are not really necessary and just get in the way when the car is operating but you can “unremark” if you need to troubleshoot your car.
The buffer values correspond to the motor control values we used in the transmitter. So buf[2] contolas the motor direction and buf[0] and buf[1] handle the motor speeds.
The motors are controlled with PWM using the Arduino analogWrite function.
Load the sketches and fire everything up. You should now have a remote controlled robot car!
Conclusion
As you can see the nRF24L01 can be used to create some very useful wireless projects with very little code, thanks to the RadioHead library. If building robot cars isn’t your thing you can still find a lot of use for this powerful combination, and I’ll be featuring some more projects using these devices very soon.
Until then enjoy your robot car and happy motoring!
Parts List
Here are some components that you might need to complete the experiments in this article. Please note that some of these links may be affiliate links, and the DroneBot Workshop may receive a commission on your purchases. This does not increase the cost to you and is a method of supporting this ad-free website.
COMING SOON!
Resources
Sketches for the Article. All of the sketches used in this article in a very handy ZIP file, just for you!
RadioHead Library. You will need the RadioHead Library for Arduino to run the experiments in this article.
nRF24L01 How-To. This is an excellent resource from the Arduino Info blog that tells you a LOT about the nRF24L01.


How would the sketch be modified to use this joystick remote and nano shield. Both have CE and CSN wired to D9 and D10. Both use an Arduino Nano, and have a socket for the nRF24L01 module.
https://www.itead.cc/itead-arduino-nano-io-shield.html
http://wiki.sunfounder.cc/index.php?title=Mobile_Robot_Remote_Controller
Hi, any idea why I copy and pasted the ” Joystick Receiver Sketch ” it compiles just fine. But when I try and add :
#include
It says that it cannot compile error.
And I don’t know why.
That should be #include
Hi Peter, you don’t specify what file you’re trying to include, but I have the same problem when I add #include to a sketch that uses the radiohead library. I can remove all of the other code and it sitll will not work.Simply adding the Servo library stops the compiler. ???
Hello, thanks for the great tutorial. I have one question what is a good way to stop the car in case the transmitter stops transmitting while the car is moving? I find when that happens I have to chase down the car and pull the power.
Thanks,
Are you using integrated antenna?
Hi, great tutorial. I got it working but I’m experiencing some pretty high latency, about 0.5-1 second between when I move the joystick to when my robot responds. Any idea why this might be happening? I’m using the nrf24 model with the external antenna, Arduino Uno for receiver and Arduino Nano for transmitter.
Thanks,
Austin
Hi, These tutorials are by far the easiest to follow for a beginner like myself, so thank you.
I’m having the same problems as Austin. A 0.5 – 1 second lag using the joystick. I’ve removed the delay(100); command and that hasn’t made any difference. ( I didn’t think it would as it’s only one tenth of a second). Can channel choice make any difference? Can channels become slow if they are busy. Any help would be appreciated, I’m not lazy, I’m frustrated. I will try channel changing next.
This is a great tutorial. I was able to put it together without any problems. I did add some LEDS for headlights and tail lights. I would like to be able to turn them off with the switch on the joystick. I just meed to find the code and merge it with your program. I can come up with ideas, but I’m not a programmer. I don’t know if the redhaed library has anything in it or do I just need to write something else in the code. I hope someone can help me.
Thanks
Hi Bob, great tutorial, but big problems. None of the sketches runs. As I fount out the sketch hangs here ” if (RadioManager.sendtoWait(motorcontrol, sizeof(motorcontrol), SERVER_ADDRESS))” on joystick site or here ” if (RadioManager.available())” on car site. Used the latest library. Othe the latest librarys are not .ino but .pde files (not big problems as just the extension. In your turorial you work with Arduino IDE and did not mention that, did they chance it recently. I double checked all the wiring it is as you printed out in the turorial. I am not a novice in arduino or electronics at… Read more »
Sorry to disturb you, got the adapters for the nrf24i01 today and the sketch works. Did not think the lack of the 3,3V power of the Arduino Clone is so severe. But did not think that this will hang the sketch totally, instead bring up an error message, what I assumed.
Glad to see you have it running, sorry for the late response!
Power supply issues are the most common problem with the nRF24L01, which is why I always use those adapters. I also had difficulties getting them to work without them.
Bill
i am very new to adruino im tring to use a nrf24lo1 to send the readings from a pot to a easydriver using nanos can anyone help me out i need to see one then i could learn were im going wrong
nemo 17
easydriver
nano
10k pot
nrf24lo1
My joystick controlled robot is working flawlessly.
The code works perfectly,
thanks to you
Can you share me your email id want to talk regarding this project as having some doubt
Dear,
can u share ur email want to talk regarding this project i have some problem regarding receiver code.
Dear Sir, Can you explain how to transfer HC-SR04 data from one Ardiuno to another by using nRF24L01 module.
I really enjoyed the video and appreciate you doing it, I only wish to request if you could help write the sketch code using the l293d chip for the motor control , rf 433mhz transceiver and a wii nunchuck for the joystick
Great project and very informative. I have built a version with an UNO as receiver and a Nano in the transmitter. Did not have the adapters for my nRF’s but instead power them with a 3,3V step down regulator.
However, it is not working. The cimpiltation and upload works fine, the cables and connections are checked (many times). The serial monitor on the transmitter says ” sendtoWait failed”. The values from the joystick changes when moving it. What can be the problem?
Did you fixed this problem….
I am also getting the same sir…
If you fixed this problem… Please tell me how you was fixed the problem….?
Same problem here
Did you find a way to solve this?
Many thanks for your sharing.
Is it possible to connect two joysticks to one Arduino UNO? How will the code for such configuration look like?
I am making a wireless robot car with nRF24L01 modules as my university project. I have uploaded the codes given by you in project. But when I try to get readings from joystick it always shows ‘init failed’ in Serial monitor of Arduino IDE. I want to clarify that I am using Arduino NANO on transmitter side to make the remote compact and Arduino UNO on receiver side. Will it affect the process of interfacing? I have tried both transmitter and receiver setup on different computers. I have nRF24L01 modules with external antenna. I am following your method throughout the… Read more »
I have just looked up you prob on the Arduino website. this might help: Uno Connections: SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). These pins support SPI communication, which, although provided by the underlying hardware, is not currently included in the Arduino language. Connect the CE to Digital pin 8. PS SS means Slave Select. If this doesn’t work then get back to me on my email address. you may also try to declare the CE (chip enable) and SS pins in your code as follows: RH_NRF24 RadioDriver(8,10);.You should not need to modify the Uno code. Hope this… Read more »
Thanks for your reply on website.
I have tried the connections you mentioned.
But I am still unable to interface between transmitter and receiver.
Following your instructions throughout the project I fill that you can help me.
Please reply if you find something helpful for me.
Thanks.
Hello again…Thanks for your help. I want to share something that finally I got success in the wireless interfacing with nRF24L01 modules. I would like to share the problem that I was facing. The labelling was wrong on both nRF24L01 modules. After trying all the different possibilities of error I concluded with this mistake made while production. So I had to be careful while purchasing these types of modules. By the way my robot driven by for motors is working efficiently. And I am happy with the range. I will recommend nRF modules with external antennas to get the batter… Read more »
what label? or pins? same problems here..need liitle help
@Robert SPANTON Thank You for the info to assign CE, the china copy has it hard wired to pin 9 on a rf nano (they put the imposter lgt8f328p processor on it too.
Same problem here..!!!
Dear,
can u share ur email want to talk regarding this project i have some problem regarding receiver code.
Tried to add the channel change and bitrate change methods (available in the nrf library) in the code using the reliable library. However its tells me that these are not supported in the reliable library, I would really like to change these. Please help.
Can i use cytron MDD10A in place of L298N
Hi sir…
I am doing arduino robot car +joystick +nRF24L01
I followed all instructions to building but after doing all connections correctly…
In transmitter side it showing messages “init failed” and “send to wait failed” but its reading joystick values when I am changing joystick position…. 😞
And in receiver side… It is showing message “init failed”…. 😞
So please tell me what is the problem to run the program correctly…
Please answer me to soon….what should I change in the circuit and program….
I’ve also experienced problems using the nER24L01 and in virtually every case it was caused by wiring. Not incorrect wiring, just the length of the wires. The nRF24L01 is an RF module operating in the low microwave band, so the wavelength is about 120mm, meaning even short wires are a good fraction of the wavelength. Another issue, again with wires, is picking up electrical noise. And finally, the power supply, any noise on that can drive these modules nuts. I was able to solve all of these issues using the small carrier module that you see me using in this… Read more »
hello …,before ive tried your code..ive simple code…with use old library…, manual ce/csn pin and then..manual radio.write…,the only problem is they only can send 1 integer..data…,your code seem can send multiple variable…,but without changing haedware or pins…except(9,10) ==>(8,10)..,your code returnt…”init failed”…,if it is not hardware or pins…maybe it on library or soft ware i dont know..,need your little help..very frustating..xixi
Can we use Arduino UNO on the client and Arduino Mega 2560 on the server??? Like not using Arduino UNO on both sides that will work right???
Bob, you know how to explain everything with the right details . love your site .I built I legoo bulldozer scaled up 3 times and I’m trying to use your wireless car code to operate it. .My problem is when I push joystick forward or backward nothing happens . . when I push right it turns right in a circle and when I push left it turns left in a circle. I have checked wire hook ups many times and all appear to be as you explain in article. . I’ve checked the nrf24lo1 modules for wrong labeling also am… Read more »
TENGO EL MISMO PROBLEMA, LLegaste a solucionarlo?
int enA = 9; these turn it on
int in1 = 14; these control direction
int in2 = 4; these control direction
// Motor B Connections
int enB = 5; these turn it on
int in3 = 7; these control direction
int in4 = 6; these control direction
i think the en lines have to be on PWM pins
I was trying to do the basic experiment with the nRF2401 with the Breakout Adapter with On-board 3.3V Regulator and a Arduino Nano. I have it wired as per the diagram. I loaded up the RadioHead libraries and used the rf24_client and rf24_server. Both sketches loaded correctly. Only the rf24_client was running the monitor said that there was no server.The rf24_server gave an init fail message and the program was not running (no flashing red led). I swapped the client and server circuits and load the client and server sketches and had the same problem. The circuit that was running… Read more »
I’m having the same problem. Did you ever fix this?
FYI for anyone having the same issue. I was able to get it working by playing around with the Transmit Power parameter in the setRF method. My computer is close to my wireless router which was provided by my ISP. It handles the wifi in my house as well as provide signal to my set top boxes, I think it was interfering with the NRF module.
Hello Joebo
would you share the the code section that sets the Transmit Power parameter in the setRF method. please.
It’s really awesome that the time was taken to make this, but to not reply to one message is kinda crazy..
Hello,
Thanks for this great tutorial. However I try to solve a problem of latency between the joystick and the Receiver… More or less 5′ of offset.
Do you have any idea to remove this problem?
Thanks.
Alain
Hello,
First, thanks a lot for this tutorial which help me to introduce with Arduino.
However I have a problem to finalize this project.
I have a great latency between the joystick and the receiver. Maybe more or less 5 secondes.
Can you help me solve this problem please?
Best regards.
Alain
Great job.Are you planning any robot cars using the XOD software?
Real thanks
Great tutorial….
Would I be correct in thinking that the same principles used here to control vehicle motors could also be used to control robotic arm motors (or servos) wirelessly?
Hi Workshoppers, Anyone have this problem? When I add Servo.h (servo library) to a sketch that uses the Radiohead library the sketch will no longer compile, and there is no specific compiler error message. Just, “compiler error” Servo.h library works fine with other nRF24 libraries.
Hi Steve, I had this same error. It is because the servo and the radio head library use the same timer. Google and download the ServoTimer2 library to fix it. Note, the servo will need to have inputs written as PWM signals, not degrees when using servotimer2
Hello, Would someone please help me with modifying the code on the final project to run a Cytron MDD10A motor controller rather than the L298N? I’m stuck!
nrf24.init() returning false… Stuck after 2 days struggle 🙁 Using the Radiohead library AND the NRF24L01 Adapter Module (to avoid any powering issues as described above) I connected the NRF24L01 AND the Adapter Module to an Arduino Mega and loaded the Radiohead nrf24_client sketch : I get nrf24.init() returning false. Checked the wires, rechecked the wires, rechecked again… still the same. Using pins 8 and 50..53. Then I shortened the wires to about 10cm (see discussion above). Still the same problem. In the library init() function, I added some debug and the spiWriteRegister() methods return “strange” Status values. The spiReadRegister()… Read more »
Did some more debugging. It seems the value of the status returned by spiWriteRegister() is not always meaningfull, so I stopped looking at it. I added some more debug in the init() method, and it seems on the Mega the spiReadRegister() always returns 0, whatever register is read. It is clear the problem is there even before any data is sent over the NRF24, the writing/reading to the internal registers of the NRF24 already fails. Changed all the wires, changed the NR module between the Arduino Uno or Nano and the one connected to the Mega. It is always the… Read more »
Hi, I finally found the cause of the error (in the Radio Library) on the Arduino Mega, and a simple work around. @Bill : as the (excellent!!!) documentation above is impacted by this error, it is maybe worth mentioning it. It is all about the SPI pin for SS on the Arduino Mega (and maybe other boards). SS should (!) be connected to pin 10, even on the Arduino Mega, due to an error in the RadioHead library. You should then initialize the library as RH_NRF24 nrf24(8, 10); For more details, see https://github.com/PaulStoffregen/RadioHead/issues/39 Some other feedback that might help other… Read more »
I am currently facing the same problem. Anyways, thank you for the clear updates. I will follow the comments you have updated above.
Doing some homework for a possible future project.
Absolutely brilliant info presented clearly and understandably – I love it!
Just one problem:
When I click on the “RF24L01 How-To. This is an excellent resource from the Arduino Info blog that tells you a LOT about the nRF24L01.” link at the end of the article, it does not work.
Anybody with an updated link?
Thanks again
Andre
Hi Andre
Unfortunately, WikiSpaces has now gone out of business, and they removed their articles. However, the GOOD NEWS is that the Arduino-info Wiki has been moved to a new home!
I’m currently updating this website and haven’t gotten to the nRF24L01 remote car article yet. But I just did update that link, you can now find the article at http://arduinoinfo.mywikis.net/wiki/Nrf24L01-2.4GHz-HowTo
Thanks for bringing it to my attention!
Bill
Great Tutorial ! I passed it on to my Ez-Robot / Synthiam friends,
thanks again
Excellent tutorial, I am learning so much from these workshops. The Arduino is very new to me, but using the sketch I have managed to wire up the nRF2401 to the Elegroo robot car and it works amazingly good. had to rewire the L298n but eventually got it all working and it has a great range. I would like to add lights to the car and switch them on and off remotely, but I really haven’t a clue how to go about this, I have done loads of research but to no avail!! if anyone has any links that will… Read more »
Hi,
Please help, I try to use Radio Head client with Radio Head server and is not working.
When I start serial monitor for server I get “init failed”. I try to use uno and nano, same problem, I change the nrf module, same problem.
Can you help me ?
Thank you
thanks so much for this tutorial it has helped me a lot. But I am still struggling with a big input delay and/or inconsistent connection between transmitters when using the car sketches and ive checked and made sure im getting the correct voltages for the transmitters and ive even tried other codes and they seem to transmit more reliable. So I was wondering is there a way to modify the joystick car code to make the transmitters more reliable. Thanks
Hi, this is a great tutorial, I’ve got it all working using Aduino Nanos. I need to control one motor for forward/backward and one motor for left/right. Can you guide me on the changes I need to make to the code to achieve this please? I have tried to change the code but have not had any success.
Hi and thanks for a great tutorial. I would like to send the same data from one transmitter to three receivers in a three way camera remote system. Is it possible to use the nRF2401´s this way? Is it possible to create three instances of the radio driver, each with its own CLIENT_ADDRESS and communicate sequentially with the three receivers? I would like to use the RHReliableDatagram but it is not critical.
A great tutorial but my server side serial monitor just throws a message ‘init failed’. Have tried many different things to troubleshoot. Used the nrf adapter, filter capacitors, checked wiring countless times, powered the module with a separate power source,searched the web for a solution, tried to use different libraries, swaped the client and server modules to check if any one of them is defective but always the client sends its message and the server side serial monitor throws a annoying statement ‘init failed’. Please suggest something to make it work.
Dear,
can u share ur email want to talk regarding this project i have some problem regarding receiver code.
I love the way you teach amazing info. thanks
Do not like the turns using reversal of motor directions. Would prefer turning while driving forward. I tried to modify the code for turning but got a long string of error messages when verifying code. Please provide code for turning while going forward.
Otherwise the code worked remarkably well except for lags in transmissions. For example on going forward there is a short delay before the car responds and continues to go forward for a short time after joystick released.
Swop the connections to driver pins 1 and 2 and pins 3 and 4 then the car/tank should run the right way.
Such a well presented description which clearly explains all aspects of this example. I have looked at a number of others and this demo is much superior.
Hi! I have build the Joystick Transmitter and the Car Receiver. I could at first not get nrf24l01-joy-rcv-car.ino to work, but after removing the comments in the lines 72 to 80 it worked fine.To low power and I experience latency and/or “run away” behaviour. Putting an 100uF Capacitor on the L298N Driver and/or on the nrf24l01 can help a lot. Good luck in life, everybody!
It works for me too but also with quite a bit of latency. I bought some new NRF24L01´s and i will try if something is wrong with my initial NRF24L01´s or not. Anybody else experiencing any lag or latency issues???
I’m having big latency issues as well.. almost 4 seconds! Any fixes?
I did. I wanted to try a different channel, data rate, gain but i need help, like an example in the radiohead language. can you help?
would An 100uF capacitor be placed on both of the nrf24l01 modules (transmitter and receiver) or just one of them (transmitter or receiver)?
I will try the cap. what did lines 72 – 80 fix? Latency?
Thanks for the grate video how would you set the nRF24 to a different channel
Shouldn’t server and client address be the same so thy can be connected to one another?
The server and client address are not what sets the actual radio frequency, so it’s okay that they are different
is there a possibility to use 2 channel pwm motor driver with encoder instead of using a normal DC motor, how to use them ?
I cannot get this to work. I’ve double, triple checked my wiring. I tried flipping pins 11 and 12. All I get is init failed. What could I be doing wrong? I see some sketches on the Arduino web site projects use pins 9 and 10. I’m using Arduino Uno so why different PIN numbers? Does the library determine which pins to use or is it something built into the hardware?
I actually tried this with two arduino unos and it work perfectly, but for a recent project I have to use an arduino mega for the receiver side. And now it does not work anymore, even though I changed the SPI pins to D52, D51, D50 (SCK, MOSI, MISO) and D8, D53 for CE, CSN pins. Does somebody have any resolutions, like changing the pins or changing the program? Additionally, I have to say that I have never used this library before. Thanks in advance for any help
define them in the beginning.
#define CE_PIN 9
#define CSN_PIN 10
“Init Failed”!! Aarrgh… Oops sorry. First I’d like to say “Legendary!!!” What a treasure this workshop is and “Thanks!!!”. So back to “AAAaarrghh! Init failed!!” again…again…and again. WTF is going wrong???? WHY??? … Tried decoupling and external power supplies and standing on my head in a bucket of vinegar…. *forehead slap to self*… So check your libraries and sketches. After a week of hair pulling I watched the vid from the beginning…and suddenly Helios dawned!! What, you may ask, was my problem? Duhhh…I was trying to use the RF24 code. Re-uploaded the NRF24 sketches (as opposed to the RF24 ones)… Read more »
Hello great tutorial!! everything works, but i do have a delay of like half a second or something. Is that normal? or can i do something about that? putting the antenna’s against to each other severaly reduces lag (not every sent instruction get’s received).
mee tooo except for the antenna part. I was thinking different channel. wanna help?
Great website, do you have a version with a more low-level library because i would prefer not to use the RF_24 library?
i’m new to adruino but i’m a builder and am really exited about what it can do. I have little code skill, but i’m trying. I would really like to see you hook up the WayinTop NRF24L01+PA+LNA RF 2.4 Ghz module up to your project and run thru the code and a couple of examples. I learn alot from your presentation and style. Thanks