Arduino simple 433Mhz/315Mhz remote control(transmitter & receiver)

I decided to create probably the simplest and cheapest remote control which is compatible with the rest of the commercial RC equipment. The remote control purpose is to be cheap, simple and fast enough for ground equipment such as RC cars, tanks, rovers, robots, etc.  If the remote proves to be reliable and more important fast enough it can be used for flying stuff like quad copters and other single and multi rotor equipment.I am bringing up the speed topic because I will be doing a lot of DA and AD conversions which will need time. In my initial tests the remote control response time is 1/15 seconds which should be enough speed for most ground vehicles.

The remote control is again based on those cheap ASK 315/433Mhz modules and Arduino to keep the cost low. I will be using the 433Mhz modules since I found great and cheap antennas for them only and without good antennas the range will be probably less than 10 meters which renders the project almost useless. With the antennas the initial tests were successful at transmitting at 15 meters indoors (3 concrete walls in between) which is a great result.

I guess outdoors the range can easily reach at least 60 meters at line of sight, probably more. I will post an update when I test it. And if this is not enough the range can be further extended by increasing the voltage of the transmitter from 5 volts to the maximum the transmitter can accept. On mine it is 12 volts (Please check your transmitter max voltage)

Parts List(for a 2-3 channel transmitter):

1. PS2 Game Joystick Module

2. 315Mhz/433Mhz transmitter receiver pair

3. Antennas

4. Arduino Nano v3  – 2pcs

5. Power bank for transmitter power (Optional)

Total cost is under 10$ without the power bank

For the transmission I will be using the RadioHead library and more specifically their RH_ASK Class. In order for the code to compile you will need to download the library from:  http://www.airspayce.com/mikem/arduino/RadioHead/RadioHead-1.61.zip

If you like how RadioHead works for you, please consider donating to the author at http://www.airspayce.com/ via the Donate button

The  first thing you should do after installing the RadioHead library is to force it to use Timer2 otherwise it will conflict with the Servo library and the code will not compile. To instruct RadioHead to use Timer2 you need to go to the place you installed the library and find the file named RH_ASK.cpp  Edit the file with your favorite editor and find the line // #define RH_ASK_ARDUINO_USE_TIMER2. Uncomment the line, save the file and you are done. If you don’t do this you will get an error during compilation of the receiver code saying  something about `__vector_11′ being already used.

Building the transmitter:

Parts:

  1. PS2 Game Joystick Module
  2. 433Mhz transmitter
  3. Arduino Nano
  4. Antenna (optional but highly recommended)

The parts should be connected in the following manner:

Transmitter data pin should be connected to pin 12 on the Arduino Nano. Transmitter Vcc to the 5v on the Arduino and the transmitter GND to Arduino GND.

The PS2 Joystick should be connected ass follows: GND on the Joystick to the GND on the arduino, +5V on the joystick to the 5V on the arduino, VRx should be connected to A0 on the arduino, VRy should be connected to A1 and the SW on the joystick should be connected to D2 on the Arduino. Basically that is how simple it is.

//Transmitter code

#include
#include // Not actually used but needed to compile

RH_ASK driver(1000, 11, 12, 10); // bps,rx,tx

int xPin = A1;
int yPin = A0;
int buttonPin = 2;

int xPosition = 0;
int yPosition = 0;
int buttonState = 0;

void setup()
{
Serial.begin(115200); // Debugging only
if (!driver.init())
Serial.println("init failed");
}
void loop()
{
// Since my joysticks are really not precise we can encode their values at 256 possibly less
xPosition = analogRead(xPin);
xPosition = map(xPosition, 0, 1023, 0, 255);
yPosition = analogRead(yPin);
yPosition = map(yPosition, 0, 1023, 0, 255);
buttonState = digitalRead(buttonPin);

//Put the values in the array, 8 bits per input
uint8_t values[3];
values[0]=(uint8_t) xPosition;
values[1]=(uint8_t) yPosition;
values[2]=(uint8_t) buttonState;

Serial.print(xPosition);
Serial.print(" : ");
Serial.println(yPosition);
driver.send(values, 3);
driver.waitPacketSent();
delay(2);
}

Building the receiver:

Parts:

  1. 433Mhz transmitter
  2. Arduino Nano
  3. One or two servos (depending on your specific needs)
  4. External 5 volt power supply at least 1A for the servo(s) since they require larger currents
  5. Antenna (optional but highly recommended)

The parts should be connected in the following manner:

Receiver data pin should be connected to pin 11 on the Arduino Nano. Receiver Vcc to the 5v on the Arduino and the Receiver GND to Arduino GND.

Servo signal pin(yellow or white wire) should be connected to D3, servo ground wire(black or brown) should be connected to the Arduino GND and also to the external power supply ground. The servo positive + wire(Red) should be connected to the external power supply +5V.

If you are connecting a second servo connect its signal pin to D9 and its positive and negative terminals just as the first servo

The code is currently set to 1000 bps  so it would have slower speed but better range and thus it is easier to test. Please feel free to increase that to 2000 after successful tests. To avoid headaches please after uploading the code to the transmitter move it to a different USB power supply. I had a lot of issues trying to transmit anything when the transmitter and receiver were both connected to the USB ports on my laptop. Moving the transmitter to an external USB power supply instantly resolved the issues. The button on the receiver is connected to the LED pin D13 but it also seems to be used  by RadioHead for transmission indication. Please change that according your needs

//Receiver code

#include 
#include  // Not actualy used but needed to compile
#include 

Servo servo1;
Servo servo2;
//RH_ASK driver;
 RH_ASK driver(1000, 11, 12, 10); // bps,rx,tx


//Those are used for fine tuning
int SERVO_LOW = 0;
int SERVO_HIGH = 180;
int c1,c2,c3;

// Pin assignments for channels(output to servos)
byte CH1_PIN = 3;
byte CH2_PIN = 9;
byte CH3_PIN = 13;

void setup()
{   
    servo1.attach(CH1_PIN);
    servo2.attach(CH2_PIN);
    pinMode(CH3_PIN, OUTPUT);

    // Debugging only, comment serial stuff when done  
    Serial.begin(115200); 
    if (!driver.init())
         Serial.println("init failed");
}
void loop()
{
    uint8_t buf[12];
    uint8_t buflen = sizeof(buf);
    if (driver.recv(buf, &buflen)) // Non-blocking
    {
        c1 = buf[0];
        c2 = buf[1];
        c3 = buf[2];

        // Remap values to the predefined range
        byte v1 = map(c1, 0, 255, SERVO_LOW, SERVO_HIGH); 
        byte v2 = map(c2, 0, 255, SERVO_LOW, SERVO_HIGH);

        servo1.write(v1);
        servo2.write(v2);

        //Output button state to a led
        digitalWrite(CH3_PIN, c3); 

        //Servo reaction time(adjust delay to your needs)
        delay(35);
     
        Serial.print(v1);
        Serial.print("  ");
        Serial.println(v2);
    }

}

Enjoy your new 2(3) channel arduino remote controller!