Overview
In this tutorial, we are gonna learn how to use an incremental type Rotary Encoder with the NRF24L01 wireless transceiver module to control the speed of a rotating fan or a DC Motor wirelessly using Arduino. We will simply make the wireless transmitter and receiver circuit. The transmitter circuit with the rotary encoder will control the receiver circuit with DC fan or motor. Both the section will have common Arduino and NRF24 L01 wireless transceiver module.
The input from the Rotary encoder is used to control the wireless DC Motor. The Encoder positional value and speed in percentage is displayed on 16×2 LCD Display.
Before starting you can see our few projects related to NRF24L01 & Rotary Encoder.
What is Rotary Encoder? Construction & Working of Rotary Encoder
How to use Rotary Encoder with Arduino
nRF24L01 based Wireless Temperature Monitoring with DHT11 Arduino
ESP8266 & nRF24L01 based Wireless Temperature Humidity Monitoring
Bill of Materials
The following are the components required for the project: DC Motor Speed Control with NRF24L01 Rotary Encoder & Arduino. All these components can be purchased from the given Amazon link.
| S.N. | Components Name | Quantity | Purchase Links |
|---|---|---|---|
| 1 | Arduino UNO Board | 2 | Amazon | AliExpress |
| 2 | NRF24L01 Module | 2 | Amazon | AliExpress |
| 3 | Rotary Encoder | 1 | Amazon | AliExpress |
| 4 | Motor Driver IC L293D | 1 | Amazon | AliExpress |
| 5 | 16x2 LCD Display | 1 | Amazon | AliExpress |
| 6 | Potentiometer 10K | 1 | Amazon | AliExpress |
| 7 | 12V DC Fan | 1 | Amazon | AliExpress |
| 8 | Power Supply 9V | 1 | Amazon | AliExpress |
| 9 | Connecting Wires | 10-20 | Amazon | AliExpress |
| 10 | Breadboard | 1 | Amazon | AliExpress |
Block Diagram
This is the block diagram of this whole System. We have two sections, one as transmitter and other as a receiver.
The transmitter section has a Rotary encoder as input. The rotary encoder is an incremental type. It will either increase the raw value in clockwise rotation or decrease the raw value in anticlockwise rotation. Then we have Arduino as a processing unit. The processed code is then transmitted via the NRF24L01 Module.
On the receiver side, the NRF24 module receives the signal wirelessly. The received signal is checked and processed by Arduino UNO. Then the Arduino sends the value to be displayed on LCD Display and also to L293D Motor Driver IC to drive DC Motor.
Circuit Diagram

Let’s see the circuit of transmitter section first. The NRF24 is an SPI module. So it’s connected to SPI pins of Arduino. Its CE and CSN pin are connected to Arduino digital pin 7 and 8. The DT pin of the rotary encoder is connected to Arduino Digital pin 4 and CLK is connected to Arduino Digital pin 6. NRF24 module is supplied with 3.3V and Rotary Encoder with 5V.

Let’s see the circuit of the receiver section now. The NRF24 is again connected to SPI pins of Arduino. Its CE and CSN pin are connected to Arduino digital pin 7 and 8. It is supplied with 3V power. The 16×2 LCD display is connected to all analogue pins of Arduino. The L293D motor driver input from Arduino is controlled via digital pin 9 and 5. A 12V DC Fan or DC motor is connected to the output of the Motor Driver IC.
Please, use external 12V supply to power on L293D Motor Driver module at its pin 8. The Arduino power supply is not enough o drive the circuit.
Project Demonstration & Working
This is the assembled circuit of transmitter on a breadboard. We have an Arduino Uno board. And then NRF24L01 Module with wireless antenna and an incremental type rotary encoder.
Similarly, at the receiver section, we have NRF24LO1 Module. 16 cross 2 LCD display. And then an Arduino UNO board. A motor driver IC L293D and a DC Fan of 12V.
This both transmitter and receiver circuit will wirelessly control the speed of DC Motor with rotary encoder. So when it is rotated in a clockwise direction, the LCD will show the position of the encoder and it will also display the speed of rotation of DC Fan in percentage. So on increasing the encoder positional value, the speed of the fan will also increase. The maximum positional limit is up to 50 only. Means at 50 the fan will rotate at full speed as 100%.
If you try to rotate the fan beyond positional value 50, the motor will just stop and it won’t move. Now, if you want to decrease the speed of the fan, you need to decrease the positional value. This can be done by rotating the rotary encoder in the anticlockwise direction.
So this is how you can use the rotary encoder to control the speed of the DC Motor wirelessly using the NRF24L01 Module & Arduino.
Source Code/Program
The code for transmitter section and receiver section both are given below. You need the libraries first. So download the libraries from the link and add it to Arduino IDE.
RF24 Radiohead Library: Download
Transmitter Code
|
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 |
#include<SPI.h> #include<RF24.h> #include<nRF24L01.h> RF24 radio(7,8); // CE, CSN const byte address[6] = "00001"; #define outputA 6 #define outputB 4 int counter = 0; int aState; int aLastState; void setup() { pinMode (outputA,INPUT); pinMode (outputB,INPUT); radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); radio.stopListening();//pinMode (en, OUTPUT); Serial.begin (9600); //lcd.begin(16,2); // Reads the initial state of the outputA aLastState = digitalRead(outputA); //Serial.begin(9600); } void loop() { aState = digitalRead(outputA); // Reads the "current" state of the outputA // If the previous and the current state of the outputA are different, that means a Pulse has occured if (aState != aLastState){ // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise if (digitalRead(outputB) != aState) { counter ++; } else { counter --; //analogWrite(en, 255); } Serial.print("Position: "); Serial.println(counter); radio.write(&counter, sizeof(counter)); //Serial.println("datasent"); } aLastState = aState; // Updates the previous state of the outputA with the current state } |
Receiver Code
|
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 |
#include<LiquidCrystal.h> LiquidCrystal lcd(14,15,16,17,18,19); #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #define M1 5 #define M2 9 RF24 radio(7,8); // CE, CSN const byte address[6] = "00001"; void setup() { pinMode (M1, OUTPUT); pinMode (M2, OUTPUT); //pinMode (en, OUTPUT); Serial.begin (9600); radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_MIN); radio.startListening(); lcd.begin(16,2); lcd.print("Project-Maanasa"); //lcd.clear(); } void loop() { if (radio.available()) { lcd.clear(); int r; radio.read(&r, sizeof(r)); // Serial.println(r); lcd.setCursor(0,0); lcd.print("Position:"); lcd.setCursor(10,0); lcd.print(r); if(r<=50) { //Serial.println("r>0"); int mapva= map(r,0,50,0,255); analogWrite(M1,mapva); analogWrite(M2,0); float s=((float)mapva/(float)255)*100; Serial.print("speed percentage: "); Serial.println(s); lcd.setCursor(0,1); lcd.print("Speed:"); lcd.setCursor(8,1); lcd.print(s); lcd.setCursor(13,1); lcd.print("%"); if(r>50) { analogWrite(M1,255); analogWrite(M2,0); Serial.println("speed percentage:100"); lcd.setCursor(0,1); lcd.print("Speed: 100.00%"); } } else if((r>-51)&&(r<0)) { int mapval=map(r,-50,-1,0,255); analogWrite(M2,mapval); analogWrite(M1,0); float s=((-1)*(float)mapval/(float)255)*100; Serial.print("speed percentage: "); Serial.println(s); lcd.print("Speed:"); lcd.setCursor(8,1); lcd.print(s); lcd.setCursor(13,1); lcd.print("%"); if(r<=-51) { analogWrite(M1,0); analogWrite(M2,0); Serial.println("speed percentage:0"); lcd.setCursor(0,1); lcd.print("Speed:0.00%"); } } else { digitalWrite(M1, LOW); digitalWrite(M2, LOW); } //analogWrite(en, 255); delay(100); } } |
Code Explanation
Transmitter Code
|
1 |
#include<SPI.h> |
First SPI library is included for SPI communication.
|
1 2 3 4 |
#include<RF24.h> #include<nRF24L01.h> RF24 radio(7,8); // CE, CSN const byte address[6] = "00001" |
And then we need to add NRF24 L01 Library. Using RF24 radio we define the CE and CSN pin function. This line const byte address[6] = “00001”; defines byte array which will represent the address or the so-called pipe through which the two modules will communicate.
The rotary encoder pins 6 and 4 are defined using the line OutputA & OutputB. And then we defined 3 integers as a counter which is zero, and the astate as a present state and alaststate as a previous state.
|
1 2 3 4 5 6 7 8 9 10 11 |
pinMode (outputA,INPUT); pinMode (outputB,INPUT); radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); radio.stopListening();//pinMode (en, OUTPUT); Serial.begin (9600); //lcd.begin(16,2); // Reads the initial state of the outputA aLastState = digitalRead(outputA); //Serial.begin(9600); |
Under the setup function, we set rotary encoder pin A and B. And then we initialize the radio object and using the radio.openWritingPipe function we set the address of the receiver to which we will send data, the 5 letter string we previously set.
Then using the radio.setPALevel function we set the Power Amplifier level, in our case I will set it to a minimum as my modules are very close to each other. Next, we have the radio.stopListening function which sets the module as a transmitter.
|
1 2 3 4 5 6 7 8 9 |
aState = digitalRead(outputA); // Reads the "current" state of the outputA // If the previous and the current state of the outputA are different, that means a Pulse has occured if (aState != aLastState){ // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise if (digitalRead(outputB) != aState) { counter ++; } else { counter --; |
In the loop section, we will read the value from the present state and previous state. If the previous and the current state of the outputA are different, that means a Pulse has occurred. If the outputB state is different from the outputA state, that means the encoder is rotating clockwise.
The counter will increase the value every time when rotated in clockwise or decrease the value when rotated in an anti-clockwise direction.
|
1 |
radio.write(&counter, sizeof(counter)); |
And then we will transmit the numeric value to the receiver section using radio.Write function.
Receiver Code
|
1 2 3 4 5 6 7 8 9 10 |
#include<LiquidCrystal.h> LiquidCrystal lcd(14,15,16,17,18,19); #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #define M1 5 #define M2 9 RF24 radio(7,8); // CE, CSN const byte address[6] = "00001"; |
The LCD pin is defined with the Liquid Crystal library that will display the data on LCD. Again we have used SPI and NRF24 Library. And then we defined the motor output connected to Arduino digital Pins. Again CE and CSN pins are defined and the same array of byte address which was earlier defined in transmitter code.
|
1 2 3 4 5 6 7 |
pinMode (M1, OUTPUT); pinMode (M2, OUTPUT); Serial.begin (9600); radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_MIN); radio.startListening(); |
In the setup section, the output function of the motor digital pin is set. And we also set the same radio commands as explained earlier.
In the loop section whatever the command is received from the transmitter is either printed in LCD Display or on the serial monitor. The value is mapped using the map function. Then the mapped value is converted into a percentage.
And then the value is compared here so that the encoder value doesn’t go beyond 50 and doesn’t get more than 100%. As well as it should stop when it goes beyond 50.










4 Comments
Hola….. Disculpa y como haria para controlar un motor dc con un potenciómetro…. Tanto sentido de giro como velocidad…. Claro a través del NRF24… De ante mano… Muchas gracias
bluetooth .
How could it be done?
I want to ask one thing that why portion value is 50 only? Can I increase it ? If yes, then please tell me how to do it.
Der Empfängercode funktioniert so nicht