GPS-Guided Self-Leveling Aircraft

I always wanted to design and build an Robot Airplane that could fly itself.
Now they're called Unmanned Autonamous Vehicles (UAVs),
Some other people on the Web figured out how to do it really cheap, so I built one based on their ideas, and then modified and shared the info to move the state-of-the art forward.

I started with a Magpie AP (from Mountain Models) It's an electric powered foam airplane.
It has a cut-out in the fuselage for a camera system, perfect for the UAV electronics.

I started with an Arduino board and ATMega328 chip as the CPU, added a GPS receiver, the ArduPilot board for Infa-Red Horizon sensing, servo fail-safe and pitot tube speed sensor, then added another Arduino Mini CPU, an XBee radio transceiver, and a Gyro to improve navigation and air to ground telemetry.



I set up the Magpie AP airplane to use the ArduPilot UAV controller, but found I needed a faster and easier way to setup the PID and trim values so that the plane would fly straight and level on it's own. The old method consisted of test flying, then re-coding the firmware, then test fly...

So I made a 2-way ground station that can send new trim values up to the plane while it's in flight. That made trimming easy - only took two flights to get it flying straight, level, and stable.

The ground station consists of an ATMega168 running the code, an XBee pro for the radio transceiver, a box full of buttons, a rotary pot to adjust values, a serial LCD for the display and a 1700 mah NiMh battery.

The ArduPilot code was changed to put many of the adjust and trim constants into EEPROM settings and code variables so they could be changed, and stored on the fly as tuning progressed.

The ground station allows me to send up new PID values (Kp, Ki, Kd, Min/Max) and trim settings (roll_trim, pitch_trim) as well as any other variables I'm adjusting (Fly_by_Wire_Roll_Gain, Fly_by_Wire_Throttle_Set_Point, etc)

The ArduPilot code only required a small change to add the code required to receive the messages from the ground. (The GPS was removed, and the XBee on the plane was connected to both Rx & Tx for send/receive to/from the ground station during the trimming process)

The commands from the ground are very simple. I only send one value at a time. ( Roll_Kp = 0.3 ) The ground station controller uses a Menu system to scroll thru the various commands available. Each screen shows the variable being adjusted, it's current value (sent from the plane via the std ArduPilot Print_Data sequence) The rotary pot is used to dial in a new value. Once the value is set via the pot, one of the red buttons is pressed to actually transmit the command to the airplane. The code in the plane sends back an "ack" and the ground station beeps 3 times to signal a successful transmission of the data to the plane. That way I KNOW the new value is in place. I can also confirm the new value via the display - the aircraft is always transmitting the current values - and these show up in the ground station display in real time.

Using this ground station to up-link data to the aircraft made setup and trimming a breeze.

In general, here is the sequence I followed:

1. Do ground testing of the UAV control stuff - test the sensors to confirm control surfaces move in the proper direction when tilting the aircraft.
2. Get the aircraft flying under manual control. Adjust and trim for straight, level flight.
3. Switch to "Fly by Wire" mode and watch what happens.
(Be ready to quickly switch back to manual control)
Does the aircraft dive?, climb?, Roll?, wobble?, Stall?, all of the above?
4. My aircraft oscillated about the roll axis, and wanted to dive.
I knew this meant the roll PID was set too high, and the pitch trim was off.
5. I decided to work on the roll values first.
- I turned off the pitch PID (by setting pKp and pKi to zero.)
- I turned off the roll Ki (set it to very low: .04), so I could first tune Kp.

Oscillations mean Kp is set too high. The PID is overshooting it's mark.
There are some good articles on tuning PIDs.

The current EasyStar Kp value was 0.7. I started dropping by 0.1 to 0.6, 0.5, and at 0.4 the oscillations stopped. I took manual control of the airplane, placed it in a steep roll, and turned on the AutoPilot. The plane immediately righted itself, and returned to almost straight flight. Increasing the roll Ki to 0.1 brought the aircraft to a more stable level position. (adjust Kp for quick, gross response without oscillations. Adjust Ki to fine tune the setting)

6. I needed to adjust the pitch trim. The aircraft wanted to dive.
I turned the pitch PID values back on (Kp = 1.3, Ki = 0.7)
The current trim setting was zero. I sent up the value pitch_trim = 10. From manual straight and level flight, I switched into Fly by Wire mode, aircraft immediately dove. Back to manual control. Sent up the value pitch_trim = -10. Entered Fly by Wire, and the aircraft was flying straight and level.

I had been hoping I could read the pitch & roll data real time during flight via the ground station, but I kept getting radio interference during flight, and unreliable radio connection while the aircraft was overhead. We had to glide the aircraft low and slow (no motor) near the ground station to send up commands. I have since switched to 900mhz XBees and now have no problem with two way communications.


After getting the airplane to fly level on it's own, I added software to steer using GPS to follow waypoints.
Here's a sample of the aircraft's path around 3 way points on a windy day:

Back to Pete's Robo-Page