Instructables

Easy Android controllable, PC Interfaceable Relatively Cheap Mini Quadcopter (or Octocopter!) Drone...

Picture of Easy Android controllable, PC Interfaceable Relatively Cheap Mini Quadcopter (or Octocopter!) Drone...
Or how to become a drone developer without mortgaging your house.

Here is how to make a small, indoor/outdoor quadcopter that you can
fly with either:
* an android phone or tablet
* a legitimate remote
* via your own processing (http://processing.org) sketches on a PC
  (or Android device)

There are lots of optional steps in this project - for example, you
can skip building the quadcopter, and buy one instead - you will still
be to use the Arduino based radio to control it from your
phone/laptop/tablet.  However if you go this route you will miss the
satisfaction of combining the ancient chinese arts of bamboo lashing
and cheap mass manufactured electronic toys...

However you go about it, this is a reasonably cheap project, the most
expensive part other than my laptop and tablet is an Arduino DUE and a
cheaper device could be used if desired.

The ability to write your own code to fly the copter make this more of
a drone than many remote control projects, but you will need to
develop your own code to actually decide what throttle, rudder,
aileron and elevator commands to send it when - a work in progress
based upon a 'Ground station' camera tracking the copter from
underneath is included, but it doesn't fly it yet!

As a simpler exercise for the reader, you can also look into adding
forward/backward/left/right FLIP buttons to the android remote.

Taster video 1: Drone controlled by tablet:
https://www.dropbox.com/s/fesrc4n9tjhul1p/2013-06-27%2022.01.41.mp4

Taster video 2: Onboard footage from flipping (and crashing)
octo-droner:
https://www.dropbox.com/s/cy0xmmbytiqymw7/copter-fpv-flip-flipped.mp4

This work was inspired by the 18$ quadcopter thread on rcgroups
(http://www.rcgroups.com/forums/showthread.php?t=1710948) - take a
look at rcgroups for plenty more inspiration.

It also makes use of plenty of other people's work, but most
immediately the processing-serial-android library
(https://github.com/inventit/processing-android-serial/) and the
hubsan X4 and A7105 code from the deviation project
(http://www.deviationtx.com/)
 
Remove these adsRemove these ads by Signing Up
1-40 of 67Next »
Venman_551 month ago

When buying the motors do they have to be clockwise/counter-clockwise or is there a way to wire it that makes it rotate a certain direction?

NicholasH1 made it!2 months ago

This is cool! I haven't built a custom quadcopter yet, but I have been using these Arduino instructions to control an Estes Syncro / Proto X.

I went ahead and set this up slightly differently--I got it working using 4-wire SPI, rather than 3-wire. This made it a lot easier to interface with the 5v arduinos, and also removed the guesswork from the resistor values. For a Due (or other 3.3v arduinos), 4-wire SPI doesn't require any resistors at all; for an Uno (or other 5v arduinos), a simple voltage divider (11k from MOSI to SPIO, 22k from SPIO to ground) handles writing, and reading (from GPIO1 on the left side of the radio board) doesn't require any resistors.

Three aspects of this took me a while to work out. First, there's commented-out code in the A7105_Setup function that claims to set it into 4-wire mode, but there's an error in it. It writes the value 0b0110 to register 0x0b. This is the correct register, but the wrong bit pattern--the bit pattern should be 0b011001, where the final two bits are 0 for non-inverted output and 1 for enable output. In hex, this value is 0x19. I probably would have caught this sooner, but the error codes in the Hubsan initialization routine all check for specific error flags set to 1...so if all your "read" calls are returning 0, the system thinks initialization has passed.

I added this routine to read the chip's "ID" register. This value is 32 bits long, so I write it into an array of uint8_t variables:

void A7105_ReadChipID(uint8_t chipID[]) {
CS_LO();
SPI.transfer(0x46); // 0x40 | 0x06
for (int i = 0; i < 4; ++i) {
chipID[i] = SPI.transfer(0);
}
CS_HI();
}

You call it like this:

uint8_t chipID[4];
A7105_ReadChipID(chipID);
If all four blocks of that are zero, there's something definitely wrong with the connection to the chip. I think this is akin to the MAC address for the chip--it should be constant for any specific a7105 chip, but it should be different for any two a7105s.
Third, and perhaps most importantly, you can't rely on Serial.print in this sketch. Other people have pointed this out as well. Any Serial.print instructions in the sketch will make it unstable. You should comment out any Serial.print instructions before testing the sketch. When the sketch was half-working--talking to the radio correctly, but getting interference from the Serial.print commends--the front two lights on the Estes Syncro would blink in sync with each other, rather than the alternating flash they do when the craft can't find any radio. If you get to this point, persist! You've almost got it working.
I'm planning to use this to build a more useful controller for the Syncro. In particular, I'm going to separate the throttle control from the yaw controls, because on the stock controller it's hard to turn without also bumping the throttle; I'm going to make the throttle control relative rather than absolute, but add a "panic" button to set the throttle to zero; and I'm going to add buttons for extra features, like buttons to adjust rate settings, buttons for flips, and so on. The Hubsan controller offers most of these features, but I'm confident I can produce something superior now that I have the freedom to tweak it to my heart's content.
Here's a photo of my setup. (The thing under the radio is just a little board I etched to make the radio breadboard-friendly, as mine's pin connections were spaced wrong for my breadboards, and the thing in the corner is a pot I wired up to act as a throttle input for testing.)
arduino_copter.jpg

so i'm working with the Proto X. i'm able to get the lights to stop blinking, that all,

i am geting a ChipID.

There are a couple of things I forgot to mention in my comment. I thought I'd posted an additional note to cover that stuff, but apparently I forgot. First, there are a lot of calls to A7105_Reset in the code. That in itself isn't a problem, but I think the radio forgets about 4-wire SPI after a reset. I fixed this by adding an A7105_Setup call after each call to A7105_Reset, but it probably makes more sense to chain a call to A7105_Setup at the end of A7105_Reset, which would guarantee it always resets to the known-good state. Otherwise Read calls will go back to getting zero at all times if you're using 4-wire. In particular, there's a call to A7105_Reset in initialize() in hubsan.ino. This could be the problem, because initialize() will still complete if the Reads are all zero--it only looks for zero values as an "okay" state--and will probably finish binding the copter, so the lights will stop blinking. But since the code will never detect error states from the radio, it's unlikely to keep communicating properly with the copter after this. (I'm not certain if hubsan_cb() requires any nonzero values, but if it does, this would also prevent it from communicating with the copter if the wire mode was reset.)

The second thing is that the configuration of the sketch in main.ino seemed weird to me too, so I rearranged that--I moved the setup and initialization to a setup() function, and made the while(1) loop body into the entire loop() function. That made more sense to me.  Finally, I didn't use the Serial.read value settings that the original author did--I was having enough trouble with Serial changing the timing of things that I decided to just hook up a potentiometer to analog zero and use that for the throttle setting as a proof of concept. That's what worked for me. I haven't used the original author's Processing sketches with the code or with the proto-X.

The entirety of my altered "main.ino" code, then:

void setup() {
  Serial.begin(115200);
  A7105_Setup();
  delay(2000);  // gives two seconds to open serial monitor to see chip id
  uint8_t chipID[4];
  A7105_ReadChipID(chipID);
  Serial.print("Chip ID: ");
  for (int i = 0; i < 4; ++i) {
    Serial.print(chipID[i]);
    Serial.print("\t");
  }
  Serial.println();
  initialize();


void loop() {
    int throttlereading = analogRead(0);

    // set global control variables for the quadcopter
    throttle = throttlereading / 4;  // Scale 0-1023 down to 0-255
    rudder = 0x7f;      // Midpoint setting
    aileron = 0x7f;     // Midpoint setting
    elevator = 0x7f;    // Midpoint setting
   
    int hubsanWait = hubsan_cb();
    delayMicroseconds(hubsanWait);
}

Once again, note that I altered "initialize" so that it would call A7105_Setup after A7105_Reset, so that the code would read error states correctly.

Hope this helps.
-Nick

Hey Nick,

Thanks for the help! so for no go :(

One thing I tried printing the id be for and after paring, is this normal?

Id be for paring is all was,

ID: :85:32:16:65

if after paring is,

ID: :0:0:65:167

-tPt

I was ablet to get woking, using a teensy 3.1 https://www.pjrc.com/teensy/teensy31.html

my testing loop

void loop() {

startTime = micros();

boundcnt = Get_state() >= 8 ? boundcnt + 1 : 0;

hubsanWait = hubsan_cb();

Serial.println(boundcnt);

finishTime = micros();

waitTime = hubsanWait - (finishTime - startTime);

delayMicroseconds(waitTime);

startTime = micros();

}

i allso in hubsan_build_packet() i set,

packet[10] = 0x19; vs 0x64

used this to test the lights and throttle

if( cnt < 100 )

{

packet[9] = 0x0e; // LEDs on, flip on for the 100 first frames

cnt++;

}

else{

packet[9] = 0x02; // LEDs off, flips off

packet[2] = 0xaa;

}

and i have lift off,!!

shinyshez (author)  NicholasH12 months ago
Hey that's great work and will really help others who try and reproduce, thanks for contributing!
Cheers
Shez
VladB13 months ago

Thanks for DYI it is great,

i just don't understand why you need the resistor for 20K?

and can you please explain how to connect it to arduino nano/leonardo?

starflyer374 months ago

Thanks for the awesome project. I've managed to build it. I am interested in the android processing serial library you've used. I've tweaked your processing code to reverse the controls as they were backwards when using it on a Nook HD. I can't seem to get the app to connect to the Due. Having gone to inventit processing android serial github, i noticed you had had the same issue as well, but have hacked the library to get it working. I was wondered if you might be willing to share your hacked library. Thanks!

allowishus5 months ago

For those interested, i've just flown my Hubsan x4 with my laptop using this tutorial. But instead of the DUE i tried to make it work with the Sparkfun Arduino Micro Pro 3.3v which by comparison to the DUE is amazingly tiny, about the double the size of the A7105 radio,

And it seems to work, further testing is of course requiered and i will return with my finding. Now to wait 'till after exam to dig into the coding :P

Thanks for a great guide!

Isigo made it!8 months ago

Hi everyone !

Thanks to the awesome work of shinyshez, andy_m and drdanny, i've been able to control my hubsan x4 fpv version with my leap motion controller. Here's the link for the github repository : https://github.com/Isigo/LeapCopter

Bug report and pull request are of course welcome. Soft still buggy, and harsh to read ( have to improve this as well ), and remember that it's a work in progress ;)

DSC_0074.JPG
shinyshez (author)  Isigo7 months ago

That's awesome! Do you have any video of it in action?

Cheers

Shez

Isigo shinyshez7 months ago

For sure ! Got this one (throttle control is still buggy ^^) :

https://drive.google.com/file/d/0B4rfrvVIld3WQXI3S01adU50YVk/edit?usp=sharing

vahokif made it!8 months ago

Hi everyone. I've been working with andy_m but I've taken a different approach and used an MPSSE cable to interface directly with the A7105. I've got binding and control working quite reliably. You can find the code here: https://github.com/vahokif/hubsan Also included is an example script that uses an Xbox 360 controller to control the quadcopter. Bug reports/pull requests are welcome.

IMG_20140214_170318.jpg
andy_m8 months ago

My previous comment was a bit premature - I have encountered a
number of issues with this method, both with the wiring and the code.

Firstly,
I cannot get 3 wire SPI to work. When there are no resistors, the MOSI
holds the SDIO pin high, so that the MISO channel can't seize it to
transmit the contents of the register back - this is why we have been
reading 0s off the registers, they are just the 0 we are transmitting as
the second part of a read transaction. When I make the line high
impedance, however, the signal is getting garbled, and it is not being
parsed as a command, and this is resulting in garbage output - the 128s
and the 196s.

Then, with 4-wire SPI, it took a bit of
troubleshooting - in shez's code there is a commented out line saying to
write 0x06 to register 0x0b - this is incorrect, due to an unclear
piece of phrasing in the chip spec. In fact, we need to write 0x19 to
register 0x0b.

My current issue is that I am having problems getting the binding to work. I shall be putting some hours into that over the weekend and early next week.


I am currently refactoring the code and adding a
number of diagnostic functions, including a sniffer and a shouter for
testing packet transmission (I have two of these rigs, and am using each of them
to debug the other). I will let you know as and when I get somewhere. I
am developing this as part of an academic research project and we are against a deadline, so it would
be reasonable to expect some progress in the next two weeks. It is my intent to pull all this together into an arduino library, to make it easy for people who want to hack about with these chips to do so without having to mess about with raw opcodes and things.

Shez- if you are reading this, ignore my earlier messages, and thank you for all your hard work!

drdanny andy_m8 months ago

Hi Andy & Shez,

First off, thanks for the excellent instructable. I think you saved me many days of trial & error.

I am using a Due & XL7105 module with an off-the-shelf Estes Dart (aka Hubsan X4) device. I succeeded in getting the 3-wire SPI interface working with more or less the A7105 code from Shez. However I did figure out how to overcome a few problems on the way. Here are some notes on what I did:

  • you do need to experiment, perhaps radically, with the resistor. I was able to make 2.2K (Red-Red-Red) and 4.7K work, but not 10K or 22K.
  • timing is quite critical I think, so adding Serial.println debug statements was interfering with the binding. I tried using a circular buffer and delaying output for a while, but even the character processing to stuff the buffer could cause binding to fail. Often the quad would think it was bound (lights solid) but the code would not recognize this and would fall back to a lower state. Perhaps a LED tied to a Due pin that switches on when state is 8 or above would be a good idea? In the end I found the binding part was working anyway and my problems were elsewhere.
  • throttle values below 10 (YMMV) will not make the motors spin
  • there is a safety feature in the Quad software: nothing will happen unless the throttle is brought down to zero and held there for a bit (say 80 times round the loop) before raising it

Here is some code to insert before the "hubsanWait = hubsan_cb();" line in the loop to test:

rudder = aileron = elevator = 0x7F; // midpoints?
if (boundcnt >= 80 && throttle < 12) throttle += 1;
if (loopcnt > 280) throttle = 0; // end test
loopcnt += 1;
boundcnt = state >= 8 ? boundcnt + 1 : 0;

and, of course, declare loopcnt and boundcnt as "int"s and init to 0 before the while loop. You may need to play with the constants to get this to work. Remember to tie the beast down before you start testing!

I had quite a time trying to solder the tiny castellated connectors. After I wrecked my first module I upgraded my soldering skills using youtube, learned how to do reflow soldering by hand, and got myself some finer solder & wire (22 AVG). How did you manage to get such beautiful neat connections?

Raspberry Pi's also have 3.3V SPI, I think, and they cost about the same as a Due, so I may rewrite the code to work with one of those later on. Will post if I do.

Now to start in on the camera business!

andy_m drdanny8 months ago

Oh, thank you!

Now you have said that, it makes complete intuitive sense. I have liftoff now, revisions pushed to my git.

I was lucky with the soldering - one of the people on my team is an ex R&D bod, so we left it all to him. I do not envy you.

JohannesH andy_m8 months ago

Hey Andy, any chance of open source? Github?

andy_m JohannesH8 months ago

But of course! :-) I shall put a link to the repo at the end of this post.

I have managed to get the thing to bind - it is not yet taking commands, but I think this is because the timing and sequencing which the arduino is giving out does not match with the timing and sequencing of the Tx.

The code here is a bit of a dog's dinner - it is half refactored, and half commented - my style is a bit different from shez's, and I have been putting it all in my own, which is a lot more verbose. Things which it might be useful to look at include the new functions in a7105.ino include the scanchannels function, which takes an array of channel numbers and tells you what traffic is on each of them (bear in mind that if the ID does not match, you will get no packets or garbled packets) and eavesdrop() which is designed for use with the hubsan protocol.

eavesdrop() scans all the hubsan channels until it finds a Tx which is transmitting prebinding packets, prints the content and timing of those to serial, and extracts the forthcoming session ID and switches over to that. Once this has happened, you can turn on the quad and allow it to bind. You can then scroll back over and see the content and spacing of all the binding and control packets. It's quite fun, with autoscroll on, to twiddle the controls and see the packet contents change.

Anyway - the code is at https://github.com/andy-may/a7105

Enjoy, and let me know how you get on!

--A

shinyshez (author)  andy_m8 months ago

Hey Andy,

Sorry i've not been about to help, sounds like your doing great work! Glad you got 4 wire SPI working should be more reliable for others, looks like my spec reading skilz aren't as mad as they could be!

Cheers

Shez

andy_m shinyshez8 months ago

Also - it's not your spec reading skills, those bits are actually in the wrong order in the spec. I only spotted it after about 4 hours of staring blankly at the page. :)

andy_m shinyshez8 months ago

Hi Shez,

Good to have you back! Yes - the 4-wire SPI seems to be much happier. I cracked out an oscilloscope, and the signal degradation on the high-impedence bit of the 3-wire was so bad that nothing was getting through.

Anyway - there seems to be some stuff which is different between the V1s and the V2s, as detailed here -

http://www.deviationtx.com/forum/protocol-developm...

Anyway, the binding is going great, and it's sitting in the data cycle very happily, but the motors still won't start. What worked for you, can I ask? By my watch, the Tx is sending packets about every 6ms, and I have tried fiddling with the timing up and down a bit, and changing the packet payload to what a V2 would expect.

Sorry to be badgering you to death, by the way!

Isigo andy_m8 months ago
I am also working on this as a part of high school project, and therefore, we are against a deadline too. I work mostly on the PC software, but i have to get something that flies. Thus i hope you'll get your stuff done, thanks for the help, i am waiting for your librairy! ;)
andy_m Isigo8 months ago

See my comment in response to Johannes above - bear in mind that this is a work in progress!

Good luck with your project! What cool things are you trying to do?

Isigo andy_m8 months ago

I managed to get it bind. But it doesn't bind if the while(1) of the main.ino code is commented, and it binds if it is not commented. I don't understand that fact, since there's nothing related to binding in this parT. I must be wrong and have misunderstood that piece of the code...

andy_m Isigo8 months ago

The binding is all done by hubsan_cb(), line 33.

Sorry for leaving that bit commented - I have been having one arduino eavesdropping, and the other binding, so I just keep commenting and uncommenting.

Isigo andy_m8 months ago

Hey Andy, thank you for all the great work.

I am currently reading your updated code. If i understood, i have to wire gio1 on the chip to miso on the arduino in order to get 4 wire SPI to work ? Is the wiring totally different than the one Shez made ?

I am trying to control that quad with a LeapMotion controller. All the PC software is finished ( relatively ^^ ).

I based the code on GroundStation one, because it is always nice to start from somewhere ^^ the problem is that i couldn't have it working for real, because of that little SPI problem ^^

Expecting it to work with your code ( and some tweaks for it to be actually able to take commands ) !

andy_m9 months ago

Hi guys,

So, I have been mucking about with this for most of
today, and I have got to the stage where the transmitter has gone
through initialise() and is running through loop - the problem I am
currently wrestling with is that the transmitter thinks it has paired
with the X4, but the lights are still blinking away. I shall have a look
at this in the morning.

The reason I am posting is this - there
is an error in the instructable. According to the datasheet, SDIO needs
to take between 0.8 and 1.0 times the voltage that VDD is receiving -
this means that the register reads always come back as invalid values. I
have found that it works fine with a 10k resistor.

Isigo andy_m9 months ago

HI, andy_m,

How did you pull the prog on the arduino ?

I am building the a7105 one as the main one, but nothing is happening...

andy_m Isigo9 months ago

Be sure all the files are in the same folder, which is called a7105. Also, some teething problems with the hardware are to be expected. Is it compiling?

Isigo andy_m9 months ago

Yeah, i can pull the prog onto the arduino, but it doesn't work at all. I will test different resistor values, because i d'ont have one of 10K. Thanks for your help.

andy_m Isigo9 months ago

Yes - I am having some teething problems as well. Are you having a thing where you are getting 128 off all the registers? I found that I can only get 0 or 128 off them, depending on the resistance, but I cannot find any information about anybody else having this issue.

Isigo andy_m8 months ago

That's it, i am getting 128 off all the registers, using a 10kohms resistor. I had 196 for a 22kohms resistor.

andy_m Isigo8 months ago

See my above comment - things are not quite as simple as I thought!

Isigo9 months ago

Hey, that's really awesome !

I am waiting for my A7105 board, and i was wondering if, since the zip for arduino software is named a7105, i have to upload the a7105 file onto the arduino as the main file ?

Thanks for this awesome work, it's giving me some ideas :D

ishan5539 months ago

can you plz inform me about the total cost for the project (final expenditure)

plz plz plz plz

my email ID is ishanphansalkar@gmail.com

krekr1 year ago
Great guide and software!
However, is there any reason why this would not work on another type of arduino (e.g. fio or Mega with level shifter)? I've been at it for a few hours now... I can't get the quad to bind. Any ideas?
shinyshez (author)  krekr1 year ago
Hey,

None that I know of, but I haven't actually tried it myself, so don't have first hand experience.

The resister value may need changed - the values that work with the unshifted Due may not work with the level shifter. Note that as 3 wire SPI is being used the data pin is BI-directional - i.e. if your only level shifting the three wires you will need to make sure that the level shifter is bi-directional. I could give a schematic or diagram of the circuit a look see if that helps.

You can try reading from the A7105 registers (there's a few with known values in the data sheet) and see if you get the expected value - this will let you know if your talking to the A7105 succesfully or not.

Hope that helps!
Cheers
Shez
Hey, thanks for your reply! I'm using Adafruit's BSS138 bi-directional level shifter. I've tried both level-shifting on the 3-wire side ("before the resistor") and on the 4-wire side ("after the resistor").
I'll try to read the register values, but I'm not an EE so this is a little challenging :P

Good to know that this should work on another type of Arduino. You'll see it'll turn out to be a DOA module or something...
krekr krekr10 months ago
Just a quick update: I received a Due this week and decided I had some time to test if this worked. I had also received a new A7105 module about a month ago.
I still can't get it to work, with both modules. Assuming I don't have 2 DOA modules, I'm starting to think that my copter runs different firmware, uses another protocol or something.
Haven't had the time to dive into this properly (with logic analyser etc.) but I might some day :)

Shinyshez: could you post a dump of the SPI messages between your Due and the module, if that's not too much work? Would help a lot when debugging this! Thanks
1-40 of 67Next »