Dron Controller Listing Program
Dron Controller Listing Program
Dron Controller Listing Program
Before starting this project, I knew almost noting about multi-rotor aircraft and how
they work. In an effort to really understand the mechanics of the flight control system,
I have decided to design and implement the software myself using an Arduino rather
than purchasing an off-the-shelf flight controller.
In What is a Quadcopter, I covered the physics of quadcopter flight. Here, well dive
into a deeper understanding of how to implement this control with an Arduino.
ROL_Union.b[3] = data[3];
// Copy the float value from the union to our angle variable
if(isnan(ROL_Union.fval) != 1)
{
angleX = ROL_Union.fval;
}
There are four signals we need to read from the receiver; Roll, Pitch, Yaw, and
Throttle. The receiver produces these PWM signals from the joystick values
specified by the operator and we read each of these signals on a digital input on the
Arduino.
PWM works by varying the width of the on signal (read Duty Cycle) within a fixed
signal frequency or period of time. So what we are really looking for is the length of
time the signal remains high for each cycle. You can read more about different ways
to read a PWM signal with an Arduino here. I am using Pin Change Interrupts
to trigger a specified Interrupt Service Routine (ISR) on RISING and FALLING signal
edges.
#include
#define MY_PIN 5 // we could choose any pin
volatile int pwm_value = 0;
volatile int prev_time = 0;
uint8_t latest_interrupted_pin;
void setup() {
pinMode(MY_PIN, INPUT); digitalWrite(MY_PIN, HIGH);
PCintPort::attachInterrupt(MY_PIN, &rising, RISING);
}
void rising()
{
latest_interrupted_pin=PCintPort::arduinoPin;
PCintPort::attachInterrupt(latest_interrupted_pin, &falling, FALLING);
prev_time = micros();
}
void falling() {
latest_interrupted_pin=PCintPort::arduinoPin;
PCintPort::attachInterrupt(latest_interrupted_pin, &rising, RISING);
pwm_value = micros()-prev_time; // now we have the latest PWM value
}
using the measured error over time to achieve a minimum output error. For more on
how the PID controller works, read here.
// Project the received throttle signal into a valid motor speed range
throttle=map(throttle_rx,THROTTLE_RMIN,THROTTLE_RMAX,MOTOR_ZERO_LEVEL,MOTOR_MAX_LEVEL);
// Update our setpoints from the receiver. I also do some basic DSP here to
// allow for noise and sensitivity on the RX controls...
setpoint_update();
// Update the measured angle values in the PID Controller.
pid_update();
// Calculate PID output
pid_compute();
//
//
m0
m1
m2
m3
Apply our Roll and Pitch signals to the throttle value to calculate the
new motor output values. Yaw control disabled during stabilization testing...
= throttle + pid_pitch_out ; //+ pid_yaw_out;
= throttle + pid_roll_out ; //- pid_yaw_out;
= throttle - pid_pitch_out ; //+ pid_yaw_out;
= throttle - pid_roll_out ; //- pid_yaw_out;
Source Code
I hope that made sense. Take a look at the full source code here.
Flight Testing
Here is a video of my first flight stabilization test. For testing, Ive fixed one axis for
testing so only one axis of rotation is active at a time.
This flight is only using the throttle. The Roll, Pitch, and Yaw signals on the receiver
are all set to zero. The quadcopter therefore, should remain level. As you can see,
the quadcopter is reading the sensor values and compensating for the measured
error. However, it is severely overcompensating and also it is applying the
compensation a little bit to slowly. It looks like I need to tune the PID values before
trying a real flight.