Today, lets build an Transmitter to control DIY RC projects using easy to obtain off the shelves parts and  Arduino Micro as brains.                                                                                                                     

What is RC Transmitter?

RC is basically short form of referring Remote Control. It is often used where there are application of a remote or a transmitter and a receiver to receive the control signals.

What is a Transmitter ?

Transmitter is basically an electronic device which produces radio waves with an antenna with the purpose of signal transmission up to a radio receiver to receive at particular frequency.

What is Arduino Micro ?

Arduino Micro is a microcontroller board based on the ATmega32u4, developed in conjunction with Adafruit. It has 20 digital input/output pins of which 7 can be used as PWM outputs and 12 as analog inputs, a 16 MHz crystal oscillator, a micro USB connection, an ICSP header, and a reset button.

Some of the key features of Arduino Micro-

  • ATmega32u4
  • 2.5kB RAM
  • Supported input voltage 4–12V DC
  • 1× UART, 1× I2C controllers, 1x SPI, 7× PWM channels

Hardware Requirements of this Project –

Software Requirements of this Project –

Circuit Diagram and Hardware Interfacing –

Circuit Diagram –

RC Transmitter 1

Hardware Interfacing –

Arduino Micro

Arduino Micro

NRF24L01

 11 

CE

12

CSN

SCK

SCK

MISO

MISO

MOSI

MOSI

Arduino Micro

MPU6050

2

SDA

3

SCL

Arduino Micro

SSD 1306 Disp 1

2

SDA

3

SCL

Arduino Micro

SSD 1306 Disp 2

2

SDA

3

SCL

Arduino Micro

Toggle Switches

5

SW 1 UP

6

SW 1 DOWN

7

SW 2 UP

8

SW 2 DOWN

Arduino Micro

Joystick

A0

JS X

A1

JS Y

4

JS Switch

Arduino Micro

Potentiometers

A2

Pot 1 Output

A5

Slide Pot Output

Coding –

Though, I’ve fitted this remote with manual and gyro options for controlling. But is up to the coding on how to utilize the available resources and plan on which functions to do what.

#include <SPI.h>
#include <Wire.h>
#include <nRF24L01.h>
#include <RF24.h>

#include <Adafruit_GFX.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>

Adafruit_SSD1306 disp1(-1);
Adafruit_SSD1306 disp2(-1);

Adafruit_MPU6050 mpu;

RF24 radio(11, 12); // CE, CSN
const byte addresses[][6] = {"00001", "00002"};

struct pack{
  int spot=0, x=0, y=0, jsw=1, trim=0;
};

struct drone{
  int batt;
};

pack data;
drone stat;

void setup() {
  Serial.begin(9600);
  //Wire.setClock(400000);

  pinMode(5, INPUT_PULLUP);   //SW 1 L
  pinMode(6, INPUT_PULLUP);   //SW 1 H
  pinMode(7, INPUT_PULLUP);   //SW 2 L
  pinMode(8, INPUT_PULLUP);   //SW 2 H

  pinMode(A0, INPUT);         //JY X
  pinMode(A1, INPUT);         //JY Y
  pinMode(4, INPUT_PULLUP);   //JY SW
  
  pinMode(A2, INPUT);         //POT  OUT
  pinMode(A5, INPUT);         //SPOT OUT

  radio.begin();
  radio.setRetries(15, 15);
  radio.openWritingPipe(addresses[1]); // 00002
  radio.openReadingPipe(1, addresses[0]); // 00001
  radio.setPALevel(RF24_PA_MIN);

  if (!disp1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {                   // Large Display Check & Initialize
    Serial.println("Failed to initialize Large Display");
    for(;;);
  }

  if (!disp2.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {                   // Small Display Check & Initialize
    Serial.println("Failed to initialize Small Display");
    for(;;);
  }

  if (! mpu.begin()) {                                              // MPU 6050 Check & Initialize
    Serial.println("Failed to initialize MPU6050 chip");
    for(;;);
  }
  
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

  disp1.clearDisplay();                                           //Clear Initial Buffers
  disp2.clearDisplay();

  disp1.setTextSize(1);
  disp1.setTextColor(WHITE);
  disp1.setCursor(42, 0);
  disp1.println("Booting");
  disp1.display();
  disp2.display();
  
  delay(2000);

  if(analogRead(A5) >= 5){
    while(analogRead(A5) >= 2){
      disp1.clearDisplay(); 
      disp1.setTextColor(WHITE);
      disp1.setCursor(35, 0);
      disp1.println("! Warning !");
      disp1.setCursor(15, 20);
      disp1.println("Throttle not Zero");
      disp1.display();
      delay(50);
    }
  }

}

sensors_event_t a, g, temp;                                       // Gyro Variables
int flag = 0;                                                     // To zero out gyro                                                    
float x_cor= 0, y_cor= 0;                                         // Correction Values 

void loop(){

  if(digitalRead(5) == digitalRead(6)){
    calc_0();

    delay(25);
    radio.stopListening();
    radio.write(&data, sizeof(data));

    // delay(25);
    // radio.startListening();
    // if (radio.available()) {
    //   while (radio.available()){
    //     radio.read(&stat, sizeof(stat));
    //   }
    // }

    selector_screen();
    flag=0;

  }

  else if(digitalRead(5) == 0){
    calc_1();

    delay(25);
    radio.stopListening();
    radio.write(&data, sizeof(data));

    // delay(25);
    // radio.startListening();
    // if (radio.available()) {
    //   while (radio.available()){
    //     radio.read(&stat, sizeof(stat));
    //   }
    // }

    //serial_debug();
    screen_1();
    flag=0;
  }

  else if(digitalRead(6) == 0){
    while (flag == 0 && digitalRead(6) == 0){
      zero_out();
    }
    if(flag == 1){
      mpu.getEvent(&a, &g, &temp);
      calc_2();

      delay(25);
      radio.stopListening();
      radio.write(&data, sizeof(data));

      // delay(25);
      // radio.startListening();
      // if (radio.available()) {
      //   while (radio.available()){
      //     radio.read(&stat, sizeof(stat));
      //   }
      // } 


      serial_debug();
      screen_2();
    }
  }
}

void selector_screen(){
  disp1.clearDisplay();
  disp1.setTextSize(1);
  disp1.setTextColor(WHITE);
  disp1.setCursor(10, 0);
  disp1.println("Select Mode");
  disp1.setCursor(10, 10);
  disp1.println("Up for Manual");
  disp1.setCursor(10, 20);
  disp1.println("Down for Gyro");
  disp1.display();

  disp2.clearDisplay();
  disp2.setTextSize(2);
  disp2.setTextColor(WHITE);
  disp2.setCursor(5, 0);
  disp2.cp437(true); 
  disp2.write(24);
  disp2.display();
}

void screen_1(){
  disp1.clearDisplay();
  disp1.setTextSize(1);
  disp1.setTextColor(WHITE);
  disp1.setCursor(32, 0);
  disp1.println("Manual Mode");
  disp1.display();

  disp2.clearDisplay();
  disp2.display();
}

void screen_2(){
  disp1.clearDisplay();
  disp1.setTextSize(1);
  disp1.setTextColor(WHITE);
  disp1.setCursor(40, 0);
  disp1.println("Gyro Mode");
  disp1.display();

  disp2.clearDisplay();
  disp2.setTextSize(1);
  disp2.setTextColor(WHITE);

  disp2.setCursor(5, 0);
  disp2.println("X = ");
  disp2.setCursor(25, 0);
  disp2.println(a.acceleration.x + x_cor);

  disp2.setCursor(5, 10);
  disp2.println("Y = ");
  disp2.setCursor(25, 10);
  disp2.println(a.acceleration.y + y_cor);

  disp2.display();
}

void zero_out(){
  disp1.clearDisplay();
  disp1.setTextSize(1);
  disp1.setTextColor(WHITE);
  disp1.setCursor(40, 0);
  disp1.println("Gyro Mode");
  disp1.setCursor(5, 20);
  disp1.println("Press JSW when ready");
  disp1.display();

  mpu.getEvent(&a, &g, &temp);

  x_cor = 0 - a.acceleration.x;
  y_cor = 0 - a.acceleration.y;

  if(digitalRead(4) == 0){
    flag=1;
  }
}

void calc_0(){
  data.spot = 0;
  data.x    = analogRead(A0);
  data.y    = analogRead(A1);
  data.jsw  = digitalRead(4);
  data.trim = analogRead(A2);
}

void calc_1(){
  data.spot = analogRead(A5);
  data.x    = analogRead(A0);
  data.y    = analogRead(A1);
  data.jsw  = digitalRead(4);
  data.trim = analogRead(A2);
}

void calc_2(){
  data.spot = analogRead(A5);
  if(a.acceleration.x + x_cor >= -5 && a.acceleration.x + x_cor <= 5){
    data.y = map(a.acceleration.x + x_cor, -5, 5, 800, 200);
  }
  else if(a.acceleration.x + x_cor < -5){
    data.y = 800;
  }
  else if(a.acceleration.x + x_cor >  5){
    data.y = 200;
  }

  if(a.acceleration.y + y_cor >= -8   && a.acceleration.y + y_cor <= 8){
    data.x = map(a.acceleration.y + y_cor, -8, 8, 1023, 0);
  }
  else if(a.acceleration.y + y_cor < -8){
    data.x = 1023;
  }
  else if(a.acceleration.y + y_cor >  8){
    data.x = 0;
  }
  data.jsw  = digitalRead(4);
  data.trim = analogRead(A2);
}

void serial_debug(){
  Serial.print(data.spot);
  Serial.print("  ");
  Serial.print(data.x);
  Serial.print("  ");
  Serial.print(data.y);
  Serial.print("  ");
  Serial.print(data.jsw);
  Serial.print("  ");
  Serial.print(data.trim);
  Serial.print("  ");
  Serial.print(stat.batt);
  Serial.println("  ");
}

Working of Project –

The working of this project is pretty simple. Upon connecting all the components as per the circuit diagram and upload the the above code. The remote should start working.

And after the remote is turned on, wait for few seconds. Till the other side also pairs up and follows commands given from the remote.

The above code which is given, has been developed for a RC car. However the above code can modified to control a RC Plane, or a quadcopter or anything. Imagination is the limit.

RC transmitter

If there’s no major error till this point. Then congratulation, you’ve successfully made a Remote for your upcoming RC projects. And the remote will cover most of the basic needs of any similar RC project.

 

– For more such Arduino and Raspberry Pi Pico based projects,
check out our Arduino Playlist and Raspberry Pi Pico Playlist

– And for other more interesting projects, check our main YouTube Channel