Mission Impossible: Cruise Control

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);
 

Leave a Reply

Your email address will not be published. Required fields are marked *

Facebook
YouTube
× Contact us