Go Down

Topic: BlueCopter - Arduino Quadcopter (Read 123270 times) previous topic - next topic

baselsw

Aug 25, 2013, 11:01 pm Last Edit: Sep 15, 2013, 12:33 pm by baselsw Reason: 1
Hey,

I spent the summer working with a new hobby of mine, Quadcopters =D! The quadcopter board is homemade (atmega32u4). Because my board has the same pinout as a leonardo, I decided to go with the multiwii firmware. So I etched a shield for my board containing headers for the receiver, motors and the IMU (cheap chinese found on ebay, ADXL345, L3G4200D, HMC5883 and BMP085).

I was happy with the quadcopter, it flew very nicely (after some PID changes of course).. But in the end I'm the type that likes to write my own code.. Trying to look at multiwii's code to see how they made it work (just to get a hunch), I directly noticed that the code isn't very, hmm how do I put it, reader friendly... So I trashed Multiwii, and there my summer began learning the dynamics and physics of quadcopters.

Three days later, I got a working code.. Three weeks after that I finally managed to find the optimal PID values for my quadcopter =P (yes it took three weeks of tweaking)..

Anyhow I'm not going to bore you out with my story. Instead I'm going to share my code with the arduino community and a video of the quadcopters first flight with my code..

If there is a big demand for a code explanation/theory about quadcopters and how everything works, shout out here, and I'll come up with something for you...

Here is the code: https://github.com/baselsw/BlueCopter

See attachment for pinout..

And here is the video:
http://www.youtube.com/watch?v=J7V1K-8xw6c

Edit: I've updated the code.. Made the sketch run more efficiently and reduced code size.. With this change I managed to find better PID values and thus get better/faster stabilization.. For those interested I've added pictures of the main board and hardware setup..

//Basel

Nick Gammon

Very nice, but I think I'll move it to Exhibition / Gallery.

Thanks for sharing the video and the code.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baselsw


Very nice, but I think I'll move it to Exhibition / Gallery.

Thanks for sharing the video and the code.

Hey, thanks Nick =)..  Couldn't figure out where to start the topic..  Good thing you moved it..

//Basel

Jantje

Tweeking takes time. Very good job I would say. Though the drawings are not clear to me at all.
Thats probably cause by my lack of knowledge
Jantje
Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

baselsw


Tweeking takes time. Very good job I would say. Though the drawings are not clear to me at all.
Thats probably cause by my lack of knowledge
Jantje


Thx =).. By drawing I assume you mean the pinout? Well, it's simple.. I used the X-configuration (meaning the quad is flying in a X shape).. If you look at the pinout the motor pins should be,

Left upper motor: Pin 6
Left bottom motor: Pin 5
Right upper motor: Pin 10
Right bottom motor: Pin 9

For RX (receiver), PPM signal (Pulse-position modulation), The pins are as follows:
Roll: Pin 16
Pitch: Pin 14
Yaw: Pin 15
Throttle: Pin 7
AUX1: Pin 8
AUX2: Pin 0

I've also got a LED on pin 13, that indicates if the quad is in rate or level/angle mode..

And of course SDA/SCL for the sensors...

Currently the code only uses the accelerometer and gyrometer to make the quad stable during rate- and angle mode..

In the future I may implement heading hold (magnetometer) and altitude hold (barometer).. Not sure yet, cause I didn't have any need for them...

Arvis

Awesome project! How much did it cost to build it?

baselsw


Awesome project! How much did it cost to build it?


Thanks bro =)..! Well, for the quadcopter parts without the main board (home made btw), around 150 USD. I bought all the parts (frame, ESC, motors, propellers...etc) from hobbyking.

//Basel

robtillaart

Well done,

many questions pop up
- how high can it fly?
- how long can it stay in the air?
- what does it do when it looses contact with remote?
- ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

baselsw


Well done,

many questions pop up
- how high can it fly?
- how long can it stay in the air?
- what does it do when it looses contact with remote?
- ...


-- Pretty high.. I didn't measure the distance yet.. But it's so high that it starts to look like a small fly in the sky (cant see the orientation of the quad, nothing)..
-- I'm using a double 2200mAh (3 cells, LiPo, coupled in parallell).. It gave me approx. 15min of flight..
-- Well I lost contact with it when I pushed the throttle to the max! (meaning it flew very high).. Nothing special happens.. It will stay leveled in the air until battery begins to run out, and it will descend (depending on the ESC ur using, it can descend slowly(ESC cutting power slowly) or it will suddenly stop (ESC cuts the power alltogether)).

And here's my parts list (all from hobbyking.com):












Item/PartPcs
20CM Male to Male Servo Lead (JR) 26AWG (10pcs/set)
1
Hobby King 2.4Ghz 6Ch Tx & Rx V2 (Mode 2)
1
Turnigy 2200mAh 3S 25C Lipo Pack
2
NTM Prop Drive 28 Series Accessory Pack
4
Hobby King Quadcopter Power Distribution Board
1
NTM Prop Drive 28-26 1350KV / 310W
4
HobbyKing 30A BlueSeries Brushless Speed Controller
4
Hobbyking X666 Glass Fiber Quadcopter Frame 666mm
1
8045 SF Props 2pc Standard Rotation/2 pc RH Rotation (Blue)
1


And consider buying spares of ex. propellers and such (if you're a beginner you'll need it)..

//Basel

Nick Gammon

Do you need an additional device to "bind" or "register" the receiver to the transmitter, or does the one you listed do that?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

baselsw


Do you need an additional device to "bind" or "register" the receiver to the transmitter, or does the one you listed do that?


The packages comes with a transmitter and receiver..

No, you get a 'special' wire that shorts the signal line on the PWR-input to ground (on the receiver).. This will put it in binding mode (Led will start to blink once per second)... In the transmitter all you have to do is hold the bind button and turn it on.. One second later the connection is accomplished, and the led on the receiver will stop blinking =D!

//Basel

i have made quadcopter with arduino uno and gy_80 sensor i have ppm 4channel radio controller and it is not sum every single channel is ppm . i tried to use your program for this but receiver dont work when i want it to fly .....
" when i connect my ppm receiver to single motor with esc radio control work perfectly but when i use it as quadcopter with code does not work
.........
help me plz . help :(
faramarz.zareian@gmail.com

baselsw

#12
Sep 05, 2013, 06:40 pm Last Edit: Sep 05, 2013, 09:37 pm by baselsw Reason: 1

i have made quadcopter with arduino uno and gy_80 sensor i have ppm 4channel radio controller and it is not sum every single channel is ppm . i tried to use your program for this but receiver dont work when i want it to fly .....
" when i connect my ppm receiver to single motor with esc radio control work perfectly but when i use it as quadcopter with code does not work
.........
help me plz . help :(
faramarz.zareian@gmail.com


Well, it won't work, I'd be surprised if it did.. This sketch is written for the arduino leonardo (atmega32u4), meaning it won't work on the UNO directly, specially the receiver part. The receiver is using the PCINT (pin change interrupts), and because there is no built-in library for arduino I had to address the registers directly, the atmega32u4 registers (which is not the same for the UNO atmega328p)..

For a beginner I recommend the use of MultiWii's code (http://www.multiwii.com/software), my code is "kind of" for people that wants to write their own code and needs some starting ground..

Edit: Another thing I would like to add.. If you decide to modify my code to work with your quadcopter, you'd have to make sure that your ESC supports PWM at a frequency of ~480-500Hz... Most ESC are made to only support PPM.. PPM isn't the same as PWM, the signal looks different and in most ESC is made to run on a frequency of 50Hz...

Here is a whole discussion about the difference: http://forum.arduino.cc/index.php/topic,14146.0.html

And if you decide to replace the 480Hz PWM with 50Hz PPM, you'll have a lot of trouble getting the quadcopter to be stable... With a little luck, you'll maybe be able to fly it in rate mode.. Angle/Level mode needs a faster update rate...



Tweeking takes time. Very good job I would say. Though the drawings are not clear to me at all.
Thats probably cause by my lack of knowledge
Jantje


Thx =).. By drawing I assume you mean the pinout? Well, it's simple.. I used the X-configuration (meaning the quad is flying in a X shape).. If you look at the pinout the motor pins should be,

Left upper motor: Pin 6
Left bottom motor: Pin 5
Right upper motor: Pin 10
Right bottom motor: Pin 9

For RX (receiver), PPM signal (Pulse-position modulation), The pins are as follows:
Roll: Pin 16
Pitch: Pin 14
Yaw: Pin 15
Throttle: Pin 7
AUX1: Pin 8
AUX2: Pin 0

I've also got a LED on pin 13, that indicates if the quad is in rate or level/angle mode..

And of course SDA/SCL for the sensors...

Currently the code only uses the accelerometer and gyrometer to make the quad stable during rate- and angle mode..

In the future I may implement heading hold (magnetometer) and altitude hold (barometer).. Not sure yet, cause I didn't have any need for them...


For RX (receiver), PPM signal (Pulse-position modulation), The pins are as follows:
you mean ppm receiver work with your code ?

baselsw

#14
Sep 08, 2013, 12:13 am Last Edit: Sep 08, 2013, 12:54 am by baselsw Reason: 1

For RX (receiver), PPM signal (Pulse-position modulation), The pins are as follows:
you mean ppm receiver work with your code ?


Yes, the receiver sends ordinary servo pulses/PPM to the arduino (one signal per axis/control-rod, a total of 6 pins/signals). And because the signals are ordinary servo signals (50Hz update rate), I used interrupts in order to read these when they change and thus avoid getting my loop rate (~800Hz) draged down by these signals..

Here is a example of how these signals looks like:



Edit: I just read your other post about needing a code that reads PPM. I'll try to explain how I did it code-wise:

Let me begin by stating the problem ahead.. If we take the throttle-rod as an example, when the throttle-rod is in the (0% position) the receiver will send a signal that's ~21ms long (a high pulse for 1ms and a low pulse for 20ms).. And when its in the (100% position) the receiver will send a signal that's ~22ms long (a high pulse for 2ms and a low pulse for 20ms).. As you noticed the 20ms part is just a "synchronization part" and doesn't provide anything useful in our case..

What we need is to measure how long the "high pulses" are. And to do that we need to know when a pulse starts and when it ends. The simplest way of doing this is using External interrupts (very few pins on arduino!!)..

Here is a example code:

Code: [Select]

#define RX_INT_PIN_THROTTLE 0
volatile int rxPrev = 0; //variable that will contain the previous time
volatile int rxVal = 0; //variable that will contain the current throttle pulse length

void rxGoesHigh(){
/* As soon as we get into this function we measure the current time (with micros)
and put that value in our variable rxPrev. After that we re-attach the same interrupt
but this time we want it to fire when the pin goes low "FALLING". When that happens it
will call the function rxGoesLow */
  rxPrev=micros();
  attachInterrupt(RX_INT_PIN_THROTTLE,rxGoesLow,FALLING);
}
void rxGoesLow(){
/* As soon as we get into this function we measure the current time (with micros) and
subtract the previous time (rxPrev). By doing that we will get the length of the pulse,
from start to the end. We end this process by re-attaching the throttle pin to a RISING
interrupt, which will repeat the process again... */
  rxVal=micros()-rxPrev; 
  attachInterrupt(RX_INT_PIN_THROTTLE,rxGoesHigh,RISING);
}

void setup(){
attachInterrupt(RX_INT_PIN_THROTTLE,rxGoesHigh,RISING); /*We begin by attaching a interrupt
to the throttle pin. the interrupt will fire when the pin goes high "RISING" (meaning the
start of the pulse). When that happens it will call the function rxGoesHigh.*/
}
void loop(){
//Nothing to do here!
}


Begin by reading the comments in setup, then go to the function rxGoesHigh and continue to the function rxGoesLow. Because interrupts are handling your pulse-length changes, all you have to do to get the latest pulse-length is read the variable rxVal.

If you need to read a lot of pins I can write something similar to explain how you can use PIN-CHANGE-INTERRUPTS instead..

Go Up