Programming an Autopilot with Arduino
In this project we are required to program a scenario in which a helicopter pivoted to a potentiometer is being controlled by Arduino and motor driver module L298N. There are some other elements like the height limit switch and a light sensor to help out the flight control. The use is required to follow the following flow in to achieve the required functionality.
Circuit Diagram
The following circuit diagram is used to program the scenario.
Arduino Code
Following is the code for this project
// This code is a sketch for controlling a device such as a drone or similar airborne apparatus to achieve a target height using altitude sensors and an autopilot system.
// Define integer variables to represent pin numbers and other parameters
int enA = 9; // Motor driver enable pin
int in1 = 6; // Motor driver control pin 1
int in2 = 10; // Motor driver control pin 2
int Lt_Switch = 7; // Limit switch pin
unsigned long Time = 0; // Variable to hold elapsed time
double currentMillis; // Variable to hold current time in milliseconds
unsigned long previousMillis = 0; // Variable to hold the previous time in milliseconds
float Target_Height = 0.2; // Target height in meters
float Take_off_Height = 0; // Variable to hold the take-off height
int LDR_Status; // Variable to hold the status of the light-dependent resistor (LDR)
int If_Status = 0; // Status flag for tracking if conditions
int Limit_Switch; // Variable to hold the status of the limit switch
float Vmax = 748; // Maximum voltage reading from altitude sensor
float M = 0; // Slope of the calibration curve
float Theta = 38; // Angle of elevation
float C = 0; // Intercept of the calibration curve
int Duty_Cycle = 51; // Duty cycle for motor speed control (20%)
// Setup function runs once when the microcontroller starts
void setup() {
Serial.begin(9600); // Initialize serial communication
pinMode(enA, OUTPUT); // Set motor enable pin as output
pinMode(in1, OUTPUT); // Set motor control pin 1 as output
pinMode(in2, OUTPUT); // Set motor control pin 2 as output
pinMode(2, OUTPUT); // Set output pin for LED 1
pinMode(3, OUTPUT); // Set output pin for LED 2
pinMode(4, OUTPUT); // Set output pin for LED 3
pinMode(5, OUTPUT); // Set output pin for LED 4
pinMode(Lt_Switch, INPUT); // Set limit switch pin as input
digitalWrite(in1, LOW); // Set initial state for motor control pin 1
digitalWrite(in2, LOW); // Set initial state for motor control pin 2
previousMillis = millis(); // Record the initial time
}
// Loop function continuously executes the main program logic
void loop() {
//Get_Height(); // Commented out; function not currently used
Take_off(); // Execute the take-off procedure
}
// Function to obtain target height from user input (not currently used)
void Get_Height() {
Serial.print("Please Enter Target Height: ");
for (;;) {
if (Serial.available() > 0) {
Target_Height = Serial.read();
if (Target_Height > 0 && Target_Height < 10)
break;
}
}
}
// Function to execute the take-off procedure
void Take_off() {
for (;;) {
currentMillis = millis(); // Record the current time
// Check if 2 seconds have elapsed and light up LED 2 accordingly
if ((currentMillis - previousMillis) > 2000)
digitalWrite(3, HIGH);
else
digitalWrite(3, LOW);
delay(1000); // Delay for 1 second
LDR_Status = analogRead(A5); // Read LDR status for take-off
digitalWrite(2, HIGH); // Light up LED 1 to indicate take-off
analogWrite(enA, Duty_Cycle); // Set motor speed
digitalWrite(in1, HIGH); // Turn on motor in one direction
digitalWrite(in2, LOW); // Turn off motor in the other direction
Serial.println("1. Take-off"); // Print take-off status
// Check if take-off altitude is reached
if (LDR_Status > 500 && If_Status == 0) {
If_Status = 1; // Update status flag
Serial.println("2. Reached Take-off Altitude");
Calibrate(); // Calibrate altitude sensor
Height(); // Display target height
Auto_pilot(); // Engage autopilot
break; // Exit take-off loop
}
}
}
// Function to calibrate altitude sensor
void Calibrate() {
float Vo = analogRead(A0); // Read voltage output from altitude sensor
M = 38 / (748 - Vo); // Calculate slope of calibration curve
C = -1 * (M) * Vo; // Calculate intercept of calibration curve
Serial.print("3. Calibrated Altimeter: M = ");
Serial.print(M);
Serial.print(", C = ");
Serial.println(C);
}
// Function to display target height
void Height() {
Serial.print("Target Height = ");
Serial.print(Target_Height);
Serial.println("m");
}
// Function to engage autopilot and control altitude
void Auto_pilot() {
Serial.println("4. Auto-pilot Starting:");
Serial.println("Time, Height Current, Height Error, Motor Control%");
Duty_Cycle = 127; // Set initial motor duty cycle to 50%
for (;;) {
delay(200); // Delay for 200 milliseconds
currentMillis = millis(); // Record the current time
// Check if 2 seconds have elapsed and light up LED 2 accordingly
if ((currentMillis - previousMillis) > 2000)
digitalWrite(3, HIGH);
else
digitalWrite(3, LOW);
Time = currentMillis - previousMillis; // Calculate elapsed time
int T_ime = Time / 1000; // Convert time to seconds
Serial.print(T_ime);
Serial.print(", ");
float Vout = analogRead(A0); // Read voltage output from altitude sensor
float Theta_current = (M * Vout) + C; // Calculate current angle of elevation
float Current_Height = sin(Theta_current) * 0.485; // Calculate current height
Serial.print(Current_Height);
Serial.print(", ");
float Height_Error = Target_Height - Current_Height; // Calculate height error
Serial.print(Height_Error);
Serial.print(", ");
// Adjust motor control based on height error
if (Current_Height < 0.2) {
Duty_Cycle = Duty_Cycle + 1;
analogWrite(enA, Duty_Cycle); // Adjust engine speed
Serial.print("Engine_Load++");
Serial.println(Duty_Cycle);
} else if (Current_Height > 0.2) {
Duty_Cycle = Duty_Cycle - 1;
analogWrite(enA, Duty_Cycle); // Adjust engine speed
Serial.print("Engine_Load--");
Serial.println(Duty_Cycle);
}
}
}
// Function to handle bonus situation (not currently used)
void Bonus() {
Serial.print("Situation Under Control");
digitalWrite(5, HIGH);