27Mhz Transmitter Conversion to 2.4Ghz Unsing Ardunio Nano and NRF24L
by phenoxyethanol in Circuits > Remote Control
1891 Views, 13 Favorites, 0 Comments
27Mhz Transmitter Conversion to 2.4Ghz Unsing Ardunio Nano and NRF24L
For some time I have been wanting to make my own radio control using the Arduino and NRF24L radio module. I have also wanted to convert an old 27Mhz radio transmitter for the job as well. To that end, this instructable combines both of these into 1.
There are other tutorials out there, some of which may suit your needs better, but this is how i've done it. This is basically my MK 1 version, and is as basic as it gets. My main reasoning for this was to make sure everything worked, as it was my first attempt. I already have ideas for further improvements in both functionality and code, so watch this space....
To give some context, this was made for the hovercraft I have made. To run this I needed 3 channels. 1 for steering, 1 for thrust and 1 for the hover. As the hover is basically set and left, I determined I could implement this using a potentiometer, hence only needing 2 channels for the joysticks.
Supplies
For the transmitter, you will need:
1 - An old 27Mhz transmitter. It doesn't need to be functional, provided the joysticks themselves work, as it is only the case and sticks we will be using. (You can also make one with joysticks bought seperately, but often these aren't very responsive)
2 - Arduino Nano (or Nano clone)
3 - Buck/boost converter
4 - NRF24L+Pa+LNA (the version with the powered antenna)
5 - The base module to fit the NRF24L (which allows 5v supply)
6 - On/off switch
7 - Additional switches/potentiometers as required for additional channels
8 - Miscellaneous components/LED's as required
For the receiver you will need:
1 - Arduino Nano (or Nano clone)
2 - NRF24L+Pa+LNA (the version with the powered antenna)
3 - The base module to fit the NRF24L (which allows 5v supply)
4 - On/off switch
5 - Miscellaneous components/LED's as required
Hardware and Wiring.
This project has 2 components. The transmitter and the receiver.
The transmitter uses the case and joysticks (including the joystick wiring) from the original unit. The original circuit board and aerial can be removed and disposed of.
If you look at the picture, you can see how I have placed the components within the case of the transmitter. How you do this will depend on the transmitter you have as not all transmitters will be identical. I requred 3 channels for my needs, but this was only a 2 channel unit, so I added a potentioneter to use as a third channel, and also added a switch, which I ended up using for a fourth channel. I was fortunate that I could clamp my NRF24L into the original aerial clamp. All I had to do was drill out the hole at the top for the larger diameter of my aerial. Hopefully you will be just as fortunate.
I ended up using the original battery bay (which houses 8 AA batteries) to power the unit. This then goes through a buck/boost converter to produce a steady 5v output. The beauty of this system is it will step down the higher voltage to 5v, but when the batteries drop below 5v, it will boost the voltage up to 5v, That way, I should get good life out of them. You could, of course use a different power source if you wish.
The buck/boost converter I bought was one with an 'enable' function. This meant I could wire an on/off switch directly to it to turn it on/off.
I took all the 5v lines from the joysticks, pot, Nano, etc and tied them together. I also did the same with the ground lines. Whilst this does make the wiring look messy, it works. I was more concerned with functionalitly than looks, but feel free to make yours look pretty.
I have included the wiring diagram as well.
For the receiver, the parts are even simpler. The main components are the Nano, NRF24L and base module. Again, I include pictures and a wiring diagram to help.
This part of the circuit doesn't have a dedicated case, so you will either need to buy one or make one. The box I used was recycled from an old project.
The power from the circuit comes from one of the ESC's, which has a battery elimination circuit (BEC). If you do not have a BEC, you will need to power it with a 5v supply suitable of supplying enough current to run the Rx and any attached servo's.
I mounted a piece of stripboard on one side of the box with pin headers attached. I tied together the 5v lines and ground lines (and also fed these to the nano and NRF24L via an onn/off switch), and connected the signal outputs from the Nano to the signal pins of each output. The servo/esc control has 3 pins in the order signal/positive/negative. You will need to ensure your pin headers follow that pattern.
When attaching multiple ESC's with a BEC, you must never connect more thn 1 BEC to power your receiver. As I had 2 ESC's, both with a BEC, I made sure the output for the channel with the BEC I didn't want to use not only had a 3 pin header, but also a 2 pin header, which was missing the positive pin. This still allowed me to control the ESC, but without allowing it to power my circuit.
The Code
I have attached the code files for both the Tx and Rx. This is based on my configuration and pin allocations, so if you want to do anything differently, you will need to alter the code accordingly.
Transmitter code:
Hopefully it is fairly self explanatory, but I will just point ot a few things in the loop:
void loop()
{ xVal = analogRead(xPin); yVal = analogRead(yPin); switchVal = !(digitalRead(switchPin)); potVal = analogRead(potPin); if(xVal > 690) { xVal = 690; } if(xVal < 325) { xVal = 325; } if(yVal > 690) { yVal = 690; } if(yVal < 325) { yVal = 325; } if(potVal > 1023) { potVal = 1023; } if(potVal < 0) { potVal = 0; } //First, all individual variables are added to the int array. joystick[0] = map(xVal,690,325,0,255); joystick[1] = map(yVal,294,735,0,255); joystick[2] = switchVal; joystick[3] = map(potVal,0,1023,0,255); //Serial prints contents of array, just to check it is what we think it is! Serial.print(" xVal = "); Serial.print(joystick[0]); Serial.print(" , y Val ="); Serial.print(joystick[1]); Serial.print(" , switchVal = "); Serial.print(joystick[2]); Serial.print(" , potVal = "); Serial.println(joystick[3]); //Array is written to the radio module to send radio.write(&joystick, sizeof(joystick)); delay(20);}
Firstly, the loop reads the values from the 2 joysticks, the pot and the switch. It then checks the joystick and pot values to ensure they fall between an upper and lower limit. If these limits are exceeded, the end points are capped. (You will need to determine these values for your own system as it will depend on the values of your pots. You can run a simple sketch to take the value form each input and see what those values are, them transfer those to this sketch.). By capping these values at the end points, it stops any risk of overflow (which could, for example cause your throttle to run at full power when fully off, or vice versa).
Next, the values are mapped to a value between 0 and 255, as these are sent as bytes (the exception is the switch which can only ever be 0 or 1!.
After printing the values to the serial port (which can be commented out or deleted, but is useful for debugging), the values are added to an array and sent to the receiver.
A short delay is added at the end.
Receiver code:
Again, hopefully self explanatory, but a brief comment on the code
void loop()
{ //First, check if anything to receive! if (radio.available()) //Looking for the data. { digitalWrite(ledPin, LOW); counter = 0; //Read in data (our array) radio.read(&joystick, sizeof(joystick)); //Reading the data xVal = map(joystick[0],0,255,1000,2000); byte temp = 255-joystick[1]; yVal = map(temp,0,255,0,3000); switchVal = map(joystick[2],0,1,1000,2000); potVal = map(joystick[3],0,255,1000,2000); //Output array to serial for checking! Serial.print("SIGNAL OK! "); Serial.print(" xVal = "); Serial.print(xVal); Serial.print(" , y Val ="); Serial.print(yVal); Serial.print(" , switchVal = "); Serial.print(switchVal); Serial.print(" , potVal = "); Serial.println(potVal); //Allocate data from array to individual variable //This isn't strictly necessary as we could display variables by reference to the array //eg: instead if i, we would reference joystick[0]. thrust.writeMicroseconds(xVal); //Value written out to the servo rudder.writeMicroseconds(yVal); //Value written out to the servo hover.writeMicroseconds(potVal); //Value written out to the servo } else { digitalWrite(ledPin, HIGH); counter = counter + 1; if(counter > 500) { if(xVal < xValDefault-100) { xVal=xVal + 100; } else { xVal++; } if(xVal > xValDefault+100) { xVal=xVal - 100; } else { xVal--; } if(yVal < yValDefault - 100) { yVal=yVal + 100; } else { yVal++; } if(yVal > yValDefault + 100) { yVal=yVal - 100; } else { yVal--; } if(switchVal == 1000) { if(potVal < potValDefault-100) { potVal=potVal + 100; } else { potVal++; } if(potVal > potValDefault+100) { potVal=potVal - 100; } else { potVal--; } } Serial.print("NO SIGNAL! "); Serial.print(" xVal = "); Serial.print(xVal); Serial.print(" , y Val ="); Serial.print(yVal); Serial.print(" , switchVal = "); Serial.print(switchVal); Serial.print(" , potVal = "); Serial.println(potVal); thrust.writeMicroseconds(xVal); //Value written out to the servo rudder.writeMicroseconds(yVal); //Value written out to the servo hover.writeMicroseconds(potVal); //Value written out to the servo } }//Delay added. This is approx 1/2 of the send delay, but very much depends on what else you want to do in your code.delay(10);
Firsly it checks there is something to receive. If there is, it maps the received values to values between 1000 and 2000. After a serial print for debugging, the 3 joystick/pot values are sent to the 3 outputs for controling them.
If there is no signal, the Red LED (pin 5) is turned on and a counter is incremented by 1. If the counter reaches 500 (an arbitury figure, but ensures minor dropout doesn't result in erratic behaviour), the outputs are taken to default values (over a short period - Not abruptly) pre set in the setup at the top of the code (basically hover and thrust off and steering neutral). If, however, signal is lost, but the switch (4th channel) is in the 'on' position, the thrust and steering reset, but the hover stays as is. This is because if I am on water and signal is lost, I do not want my hovercraft to sink!
Summary
I hope this instructable makes enough sense. I will review it and update it as I find any issues, or determine it is problematic to follow.
If you find you want to add more channels, you can add to this code to create up to 32 channels in total (although relistically you probably wouldn't want more than 8-10 at most.
Although I have used powered versions of the NRF24L, some people have used the non powered version for the receiver without issue. You will just need to check the range suits your needs.
I know the wiring and code is a bit sloppy, but as already stated, my goal was functionality, not beauty!
Further down the line I will also be sharing impovements/modifications.
Feel free to ask questions.