Following the drone project (with an off-the-shelf flight controller), it was decided that a custom flight controller was required. This custom flight controller will allow for customized control and can be used as a development platform for further projects.
Initially an Arduino Nano IOT was used as it includes an Inertial Measurement Unit. This Arduino Uno IOT however takes more space than neccessary also does not contain a pressure sensor required for this project. Another new module was released and this contains many more sensors, including a pressure sensor, in a smaller form factor.
This new module is the Arduino Nicla Sense ME and has been chosen to be used for the flight controller. The Arduino Nicla Sense ME contains a gas sensor, a barometer, magnetometer, accelerometer and gyroscope. It is also packaged in a very small form factor, perfect for this application.
The Flight Controller is used to take readings from the inertial measurement unit and turn them into signals to control 4 motors at different RPMs. These different RPMs depend on the orientation of the IMU. The motor signals produced are to try and keep the Pitch, Roll, Yaw and Altitude of the drone to a desired angle or set point. This is also acheived by the use of PID controllers.
\[\begin{bmatrix} m_1\\ m_2\\ m_3\\ m_4 \end{bmatrix} = \begin{bmatrix} -\theta_{Roll}-\theta_{Pitch}+\theta_{Yaw}+\delta_{Altitude}\\ +\theta_{Roll}-\theta_{Pitch}-\theta_{Yaw}+\delta_{Altitude}\\ +\theta_{Roll}+\theta_{Pitch}+\theta_{Yaw}+\delta_{Altitude}\\ -\theta_{Roll}+\theta_{Pitch}-\theta_{Yaw}+\delta_{Altitude}\\ \end{bmatrix}\]
However, If theses signals were directly used by the motors, the system would not be stable. A PID controller must be used on each of the axes to makesure that the motors don't overcompensate the angles.
PID_LOOP::PID_LOOP(float p_value, float i_value, float d_value) {
_p_value = p_value;
_i_value = i_value;
_d_value = d_value;
current_error = 0;
previous_error = 0;
proportional = 0;
integral = 0;
differential = 0;
pid_output = 0;
}
float PID_LOOP::compute_loop(float desired_value, float actual_value){
current_error = desired_value - actual_value;
proportional = current_error;
integral += current_error;
differential = current_error - previous_error;
pid_output = (proportional*_p_value) + (integral*_i_value) + (differential*_d_value);
previous_error = current_error;
return pid_output;
}
This PID class can be used for each of the axes, shown below.
motor1 = altitude_pid_output-x_pid_output-y_pid_output+z_pid_output;
motor2 = altitude_pid_output+x_pid_output-y_pid_output-z_pid_output;
motor3 = altitude_pid_output+x_pid_output+y_pid_output+z_pid_output;
motor4 = altitude_pid_output-x_pid_output+y_pid_output-z_pid_output;
The drones attitude can be visualised in 3D using the visualiser as shown in the video below.