Introduction: Autonomous Drone That You Already Have in Your Pocket!

In this tutorial i want to learn you something, maybe change your mind. And make autonomous drones available for everyone.

Simple question is: What do you need to make your drone autonomous?
.
Answer:
- GPS
- Accelerometer
- Gyroscope
- Telemetry wireless system
- Camera
- Some better micro processor

Its expensive right?

Real answer: Its cheap, and you already have it in your pocket!!!

Modern Android phones provides many possibilities, so we can make drones from them too. All you need is simple frame and simple hardware. And if you are worry about your super modern android phone, you can buy some old one from ebay and use your super modern one to control the drone remotely.

Step 1: Frame

You can find lot of guides how to make proper frame, buy adequate brushless motor, ESC , prop etc.. The truth is: take some lightweight material (aluminum, wood, glass fiber, carbon fiber etc..) and make tri/quad/hexa/octo from that. Just select material that you are able to work with and keeps same distance between motors.
I had some old parts from my X525 that i bought on goodluckbuy. Don't buy exact same motors and ESCs, they are pretty terrible quality. I changed them on my x525 for better, so they lay on my table and they are ideal for testing  (it means lot of crashing :)).

My part list for frame: 
3x Polaris 20A esc (don't buy it, thy another)
3x A2212 1000KV motor (don't buy it, thy another)
3 x Aluminum Square Boom from x525
2x X525 V3 Glass Fiber Main Frame Upper Plate
1x 3,4Ah turnigy nanotech lipo
1x turnigy voltage alarm

I decided to make tricopter, because i have only 3x ESC, you can make multicopter of your choice.

First step is to put the frame together with some bolts. You will need to drill two holes for rear boom.

Second step is to mount motors with motor mounts. If you are interested how i made this fancy motor mounts, you can check my tutorial on flitetest website http://flitetest.com/articles/fiberglass-supply-from-computer-parts Or siply use the original once.

Last step is to handle the weak spot of tricopter = yaw control. I recommend you to make something like well known RCExplorer.se guy do.

And you have very simple and powerful tricopter, weight is about 1,03kg. At this step you can perform frame test with kk board.
And as you can see here http://www.youtube.com/watch?v=9xf6285N5qE&feature=player_detailpage#t=138s it flies.

It was easy? lets check out next step...

Step 2: The Circuits

If you want to control something with android phone you will need some outputs. Simplest way is to use Android IOIO or Arduino board. I prefer IOIO in my projects, because it is powerful and easy to use. You can see lot of IOIO examples at my youtube channel http://www.youtube.com/watch?v=XSAzSw3QTOY&list=PL0B750CE7BBFA3EAB

You can use simple shield for IOIO (see in pictures), that break out the PWM pins. I make the shield form universal PCB. Jumper connects power form servo connectors to VIN or 5V pin on IOIO board. Idea is: you can supply servo connectors from IOIO regulator. And on other hand, you can supply IOIO board form servo connectors with UBEC or some ESC.

The wiring is simple, put M1, M2, M3 and servo to IOIO pins 10.11.12.13. If you are good programmer you can finish with this setup. Because i want to test step by step and want be able to control my UAV with my Turnigy 9x i connect receiver to digital pits 3, 4, 5, 6, 7(Stabilization features first and autonomous next).

Good thing is that your phone will by charged by on-board lipo. 

For test proposes we will use only receiver connected to digital pits 3, 4, 5, 6, 7, one ESC with ubec (connected to pin10) and one servo (connected to pin 11). You can see bluetooth dongle connected to android ioio USB port, i use bluetooth for simple debugging. Your phone can be still connected to PC via USB and can communicate with ioio over the bluetooth. Its better to use cable connection between ioio and phone during on-board testings and flights (hopefully) :)

I made little research about pulse modulation from receiver. I used logic analyzer made from arduino. Modulated signal has 20ms period (50Hz) and HIGH pulse width is 1 to 2 ms (1,5 ms is center). Now we can read and represent signal with this knowledge.

The hardware part is relay simple, isn't it? Next step is software part. Because this drone depends at software at 99%, everything depends at yours and mine programming skills.

Step 3: Software - Analyzing

In this step, we want to analyze if we are able to:
1) read stick position from receiver
3) control servo
2) control ESC

For this propose we will use test setup mentioned on page 2. The components are:
1) Android IOIO with shield from page 2.
2) Receiver connected to digital pins 3-7
3) ESC connected to pin terminal 10
4) servo connected to pin terminal 11
My ESC includes BEC, that mean you can supply IOIO board form connected ESC. In this case, black lumper on our shield will be placed on left side, VIN pin on IOIO board will be connected to servo terminals (ESC will supply IOIO board).

For software development, you will need to install standard Android development environment and include IOIO libraries to your project. You can find tutorial here: https://www.sparkfun.com/tutorials/280 and doc umentation for Android IOIO project here: https://github.com/ytai/ioio/wiki

Our test application have simple gui, we will need:
2x slider to control servo and ESC (control PWM pins 10, 11)
5x label showing values from receiver (reed pulse width on pins 3-7)

Android IOIO offers Pulse Input. This type of input allows you to read width of incoming pulse, so its ideal for reading pulses form receiver. IOIO have 6 available ones (3 single-precision, 3 double-precision) you cant use 6 single or 6 double precision, you must split them. We will use PWM for driving ESCs and Servos. You can find functions for each individual pin here https://github.com/ytai/ioio/wiki/Getting-To-Know-The-Board


This test app have relay simple code:

public class MainActivity  extends IOIOActivity  {
private TextView ch1, ch2, ch3, ch4, ch5;
private SeekBar seekBar1, seekBar2;
private int seekBar1_val, seekBar2_val;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

  ch1=(TextView)findViewById(R.id.ch1_text);
  ch2=(TextView)findViewById(R.id.ch2_text);
  ch3=(TextView)findViewById(R.id.ch3_text);
  ch4=(TextView)findViewById(R.id.ch4_text);
  ch5=(TextView)findViewById(R.id.ch5_text);

  seekBar1 = (SeekBar) findViewById(R.id.seekBar1);
  seekBar2 = (SeekBar) findViewById(R.id.seekBar2);

  seekBar1_val = 1000;
  seekBar2_val = 1500;

  seekBar1.setMax(1000);
  seekBar2.setMax(1000);

  seekBar2.setProgress(500);

  seekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {
   }
   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
   }
   @Override
   public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    seekBar1_val = progress + 1000;
   }
  });

  seekBar2.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {
   }
   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {
   }
   @Override
   public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    seekBar2_val = progress + 1000;
   }
  });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
}

class Looper extends BaseIOIOLooper {
  private PulseInput pulse_ch1;
  private PulseInput pulse_ch2;
  private PulseInput pulse_ch3;
  private PulseInput pulse_ch4;
  private PulseInput pulse_ch5;

  private PwmOutput M1;
  private PwmOutput Servo;

  public Float ch1_val;
  public Float ch2_val;
  public Float ch3_val;
  public Float ch4_val;
  public Float ch5_val;

  private DigitalOutput led_;

  @Override
  protected void setup() throws ConnectionLostException {
   pulse_ch1 = ioio_.openPulseInput(3, PulseMode.POSITIVE);
   pulse_ch2 = ioio_.openPulseInput(4, PulseMode.POSITIVE);
   pulse_ch3 = ioio_.openPulseInput(5, PulseMode.POSITIVE);
   pulse_ch4 = ioio_.openPulseInput(new DigitalInput.Spec(6),
                 PulseInput.ClockRate.RATE_250KHz,
                 PulseInput.PulseMode.POSITIVE,
                  false);
   pulse_ch5 = ioio_.openPulseInput(new DigitalInput.Spec(7),
                 PulseInput.ClockRate.RATE_250KHz,
                 PulseInput.PulseMode.POSITIVE,
                  false);

   M1 = ioio_.openPwmOutput(10, 50);
   Servo = ioio_.openPwmOutput(11, 50);


   led_ = ioio_.openDigitalOutput(0, true);
  }

  @Override
  public void loop() throws ConnectionLostException {
   led_.write(false); 
   try {
    ch1_val = pulse_ch1.getDuration() * 1000;
    ch2_val = pulse_ch2.getDuration() * 1000;
    ch3_val = pulse_ch3.getDuration() * 1000;
    ch4_val = pulse_ch4.getDuration() * 1000;
    ch5_val = pulse_ch5.getDuration() * 1000;

    M1.setPulseWidth(seekBar1_val);
    Servo.setPulseWidth(seekBar2_val);

    Thread.sleep(100);
   } catch (InterruptedException e) {
   }
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     ch1.setText(String.format("%.2f", ch1_val));
     ch2.setText(String.format("%.2f", ch2_val));
     ch3.setText(String.format("%.2f", ch3_val));
     ch4.setText(String.format("%.2f", ch4_val));
     ch5.setText(String.format("%.2f", ch5_val));
    }
    });
  }
}

@Override
protected IOIOLooper createIOIOLooper() {
  return new Looper();
}

}

Our analysis went well, we can:
1) read stick position from receiver via digital inputs
3) control servo
2) control ESC

Test video:

Step 4: Test Stand

Test stand is easy and safe way how to test your prototype. Test can be only rough but it will be good for basic testing.

I used:
- TV stand as base. (i have my TV stand unused because my TV is mounted on the wall).
- Two parts from curtain rail holder. First part (normally mounted to the wall) is mounted to tricpoter base with zip ties. The second part that holds the pipe is mounted to the TV stand.
- I placed aluminum stripe on top of the hole of the curtain pipe holder and drill smaller hole to it.
- The O ring hook is placed to this hole and screwed to the piece of wood that is inserted to part that is mounted to the tricopter.

The idea was to create ball joint that is able to move to all directions and rotate.

If you want create this stand i recommend use higher stand to reduce the ground effect. Some telescopic rod will be great,

I made test with KK multicopter board on board:

Step 5: Implementing Basic Functions

In this step we will try to write some basic functions. GUI contains two tables, status label and check box.

First table shows values from receiver, reading is same as in step 3 in this tutorial. You can trim your transmitter to 1500 witch is middle position (1ms is min, 2ms is max, 1500 = 1,5ms witch is center).

Status label shows if we are connected to IOIO board and if we are in armed or disarmed mode. There is sample code that switch to armed and disarmed:
if (ch3_val < throttle_min && ch4_val < disarm_pos){
//disarm
armed = false;

  } else if (ch3_val < throttle_min && ch4_val > arm_pos){
//arm
armed = true;
}


ch3_val is value from throttle and ch4_val is ruddler (yaw), arming is shown on main picture i use mode3 on mi transmitter. throttle_min, arm_pos and disarm_pos are positions where stick must be to arm or disarm.

Second table show up output data, value is exact pulse length send to outputs.

In first step i tried to fly without PID ( we will discuss PID later), logic was simple:
- because of tricopter M1 and M2 (front motors) must work on half speed than M3, because M3 is lonely on the back. 
- if i want go to the ahead i will put more throttle to rear M3 and less to front M1 and M2 (backwards is opposite)
- if i want go to right i put more throttle to M1 and less to M2 (left is opposite)
- yaw - rotation is controlled by servo

My implementation looks like this (don't use it i will discuss it later):
//yaw servo controll
servo_val = ch4_val;

//throttle controll
m1_val = 1000 + (ch3_val - 1000)/2;
m2_val = 1000 + (ch3_val - 1000)/2;
m3_val = ch3_val;

//pitch controll
m1_val += - (ch2_val - 1500)/2;
m2_val += - (ch2_val - 1500)/2;
m3_val += + (ch2_val - 1500);

//roll controll
m1_val += + (ch1_val - 1500);
m2_val += - (ch1_val - 1500);


mx_val and servo_val are output values calculated from input values. Problem with this implementation is stick sensitivity, if you pull to the elevator to the front in slow speed (throttle) the M1, M2 is decreased more than throttle is set, so they stop. The feeling in test stand is really aggressive, you cant fly with this implementation. So i add the check box to the GUI, that switch to only incremental mode. That means, program doesn't decrement motors on one side, only increment on the other side. Behavior of these modes is shown in the following video:

So as you can see I have not been able to fly stable as in step 4, when i test my stand with KK board. The proper way is to use accelerometer and PID regulation.

Step 6: Conclusion and TODOs

I was writing this tutorial for drone contest here on instructables. I didn't finish it because of deadline and small amount time that i had. Therefore, I would like to summarize what we need to do and what other things android phone offers.

What we did:
- we made proof that we can use Android phone and Android IOIO for controlling multicopters
- we made proof that we must implement some regulation algorithm like PID

To be done:
- reed accelerometer data
- calibrate accelerometer (set center position)
- use PID regulation algorithm

You can reed some basics about PID regulation here http://en.wikipedia.org/wiki/PID_controller
Get some inspiration in opensource projects like Ardupilot git hub.
I fount interesting java implementation here http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

Whats next:
- Implement GPS functions and make it autonomous
- Remote control with another Android phone (telemetry, way points etc...)
- Use camera for FPV and capturing videos
- Add other hardware sensors like voltage sensor, barometer etc..

I am sorry that i wasn't be able to make it fly before end of this drone contest. But I hope I inspired someone at least.

If you liked it please vote for me, or subscribe my youtube channel for more updates.

Drones Contest

Runner Up in the
Drones Contest

Battery Powered Contest

Participated in the
Battery Powered Contest

Remote Control Contest

Participated in the
Remote Control Contest