Retrudio

Испытательный стенд для проверки двигательной установки и системы защиты электропитания дронов

Бесплатно
Arduino UNO Сложный cat_Робототехника Автор: adminrahmatulloh Опубликовано: 2026-10-10 Версия: 1.0 Лицензия: CC0

Автор подтвердил проверку на оборудовании.

Испытательный стенд для проверки двигательной установки и системы защиты электропитания дронов

Компоненты

Предупреждения

Всегда перепроверяйте все ли правильно мы не несем ответственности

Описание

Испытательный стенд для проверки двигательной установки и системы защиты электропитания дронов Встроенная система Arduino Обзор проекта В этом проекте моделируется система движения и управления питанием дрона с использованием Arduino Uno. Два двигателя постоянного тока представляют собой левый и правый двигатели дрона, а потенциометр управления дроссельной заслонкой регулирует требуемую скорость вращения двигателей. Второй потенциометр имитирует напряжение трехэлементной литиевой батареи. Два датчика температуры TMP36 контролируют имитируемые температуры цепей управления левым и правым двигателями. Arduino непрерывно считывает значения этих датчиков и регулирует выходную мощность двигателя с помощью широтно-импульсной модуляции (ШИМ). В обычном режиме работы зеленый светодиод остается включенным, и оба двигателя реагируют на входной сигнал управления дроссельной заслонкой. Если имитируемое напряжение батареи становится низким или температура любого из двигателей повышается, система ограничивает выходную мощность двигателя, активирует желтый предупреждающий светодиод, включает пьезоэлектрический зуммер и отображает предупреждение на ЖК-дисплее. Если напряжение или температура батареи достигают критического уровня, система отключает оба двигателя, включает красный светодиод и звуковой сигнал, а также отображает сообщение «НЕИСПРАВНОСТЬ БАТАРЕИ» или «ОТКЛЮЧЕНИЕ ИЗ-ЗА ПЕРЕГРУЗКИ ИЗ-ЗА ПЕРЕГРУЗКИ». Этот проект демонстрирует встроенное программирование, аналоговый сбор данных с датчиков, управление двигателем на транзисторах, ШИМ, мониторинг батареи, тепловую защиту, обнаружение неисправностей и отображение состояния системы в реальном времени. Это скорее испытательный стенд для силовой установки и защиты, чем полноценный летающий дрон.

Сборка и проверка

  1. Соберите цепь по таблице при отключённом USB.
  2. Подключите плату и загрузите скетч

Код

Скачать .ino
#include <LiquidCrystal.h>

// DRONE PROPULSION AND POWER PROTECTION TESTBENCH

// Analog sensor pins
const int THROTTLE_PIN = A0;
const int BATTERY_PIN = A1;
const int LEFT_TEMP_PIN = A2;
const int RIGHT_TEMP_PIN = A3;

// Motor PWM pins
const int LEFT_MOTOR_PIN = 5;
const int RIGHT_MOTOR_PIN = 6;

// Status indicators
const int GREEN_LED = 13;
const int YELLOW_LED = 2;
const int RED_LED = 4;
const int BUZZER_PIN = 3;

// LCD pins
// LiquidCrystal(RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

// BATTERY SETTINGS

// Simulated three-cell lithium battery voltage range
const float MIN_SIMULATED_VOLTAGE = 9.0;
const float MAX_SIMULATED_VOLTAGE = 12.6;

// Low-battery warning threshold
const float LOW_BATTERY_VOLTAGE = 10.8;

// Critical-battery shutdown threshold
const float CRITICAL_BATTERY_VOLTAGE = 9.9;

// Hysteresis values help prevent rapidly switching modes
const float LOW_BATTERY_RECOVERY = 11.1;
const float CRITICAL_RECOVERY = 10.2;

// TEMPERATURE SETTINGS

// Motor output begins to be limited at this temperature
const float DERATE_TEMPERATURE = 45.0;

// Motors shut down at this temperature
const float SHUTDOWN_TEMPERATURE = 60.0;

// Temperature must fall below this value to recover
const float RECOVERY_TEMPERATURE = 55.0;

// MOTOR SETTINGS

// Maximum Arduino PWM value
const int MAX_PWM = 255;

// Maximum output allowed during a warning
const int DERATED_PWM = 150;

// Maximum PWM change during each program cycle
// This creates a soft-start and soft-stop effect.
const int PWM_STEP = 4;

// TIMING SETTINGS

const unsigned long SENSOR_INTERVAL = 100;
const unsigned long DISPLAY_INTERVAL = 500;
const unsigned long BUZZER_INTERVAL = 500;

// SYSTEM STATES

enum SystemState
{
  NORMAL,
  LOW_BATTERY,
  THERMAL_DERATING,
  CRITICAL_FAULT
};

SystemState systemState = NORMAL;

// GLOBAL VARIABLES

int throttleRaw = 0;
int requestedPWM = 0;
int targetPWM = 0;
int currentPWM = 0;

float batteryVoltage = 0.0;
float leftTemperature = 0.0;
float rightTemperature = 0.0;
float highestTemperature = 0.0;

bool buzzerOn = false;

unsigned long previousSensorTime = 0;
unsigned long previousDisplayTime = 0;
unsigned long previousBuzzerTime = 0;

// SETUP

void setup()
{
  // Configure motor pins as outputs
  pinMode(LEFT_MOTOR_PIN, OUTPUT);
  pinMode(RIGHT_MOTOR_PIN, OUTPUT);

  // Configure status indicators as outputs
  pinMode(GREEN_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);

  // Analog pins are inputs by default, but declaring them
  // makes the intended purpose of each pin clearer.
  pinMode(THROTTLE_PIN, INPUT);
  pinMode(BATTERY_PIN, INPUT);
  pinMode(LEFT_TEMP_PIN, INPUT);
  pinMode(RIGHT_TEMP_PIN, INPUT);

  // Ensure motors and alarms are off during startup
  analogWrite(LEFT_MOTOR_PIN, 0);
  analogWrite(RIGHT_MOTOR_PIN, 0);
  noTone(BUZZER_PIN);

  // Initialize LCD
  lcd.begin(16, 2);
  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("DRONE POWER SYS");

  lcd.setCursor(0, 1);
  lcd.print("INITIALIZING...");

  // Initialize Serial Monitor for data logging
  Serial.begin(9600);

  delay(2000);
  lcd.clear();
}

// MAIN LOOP

void loop()
{
  unsigned long currentTime = millis();

  // Read sensors every 100 milliseconds
  if (currentTime - previousSensorTime >= SENSOR_INTERVAL)
  {
    previousSensorTime = currentTime;

    readSensors();
    determineSystemState();
    calculateMotorOutput();
    updateMotorSpeed();
    updateStatusIndicators();
    printSerialData();
  }

  // Update the LCD every 500 milliseconds
  if (currentTime - previousDisplayTime >= DISPLAY_INTERVAL)
  {
    previousDisplayTime = currentTime;
    updateLCD();
  }

  // Control warning buzzer without blocking the program
  updateBuzzer(currentTime);
}

// SENSOR READING FUNCTIONS

void readSensors()
{
  // Read the pilot throttle command
  throttleRaw = analogRead(THROTTLE_PIN);

  // Convert throttle from 0-1023 to PWM 0-255
  requestedPWM = map(throttleRaw, 0, 1023, 0, MAX_PWM);

  // Read simulated battery voltage
  batteryVoltage = readBatteryVoltage();

  // Read both TMP36 temperature sensors
  leftTemperature = readTMP36(LEFT_TEMP_PIN);
  rightTemperature = readTMP36(RIGHT_TEMP_PIN);

  // Determine which motor temperature is higher
  highestTemperature = max(leftTemperature, rightTemperature);
}

// Read and average the battery potentiometer
float readBatteryVoltage()
{
  long total = 0;

  // Average ten readings to reduce measurement noise
  for (int i = 0; i < 10; i++)
  {
    total += analogRead(BATTERY_PIN);
  }

  float averageReading = total / 10.0;

  // Convert potentiometer reading to simulated 9.0-12.6 V
  float voltage =
      MIN_SIMULATED_VOLTAGE +
      (averageReading / 1023.0) *
      (MAX_SIMULATED_VOLTAGE - MIN_SIMULATED_VOLTAGE);

  return voltage;
}

// Read and convert a TMP36 sensor value to degrees Celsius
float readTMP36(int sensorPin)
{
  long total = 0;

  // Average ten readings for a more stable temperature value
  for (int i = 0; i < 10; i++)
  {
    total += analogRead(sensorPin);
  }

  float averageReading = total / 10.0;

  // Convert Arduino reading into voltage
  float sensorVoltage = averageReading * (5.0 / 1023.0);

  // TMP36 output is 0.5 V at 0 degrees Celsius
  // It increases by 0.01 V per degree Celsius.
  float temperatureC = (sensorVoltage - 0.5) * 100.0;

  return temperatureC;
}

// STATE-MACHINE LOGIC

void determineSystemState()
{
  // Critical faults have the highest priority.
  if (batteryVoltage <= CRITICAL_BATTERY_VOLTAGE ||
      highestTemperature >= SHUTDOWN_TEMPERATURE)
  {
    systemState = CRITICAL_FAULT;
    return;
  }

  // Remain in critical mode until conditions recover enough.
  if (systemState == CRITICAL_FAULT)
  {
    bool batteryRecovered =
        batteryVoltage > CRITICAL_RECOVERY;

    bool temperatureRecovered =
        highestTemperature < RECOVERY_TEMPERATURE;

    if (!batteryRecovered || !temperatureRecovered)
    {
      return;
    }
  }

  // Apply thermal derating when either motor becomes hot.
  if (highestTemperature >= DERATE_TEMPERATURE)
  {
    systemState = THERMAL_DERATING;
  }

  // Apply low-battery derating.
  else if (batteryVoltage <= LOW_BATTERY_VOLTAGE)
  {
    systemState = LOW_BATTERY;
  }

  // Use recovery hysteresis before returning to normal.
  else if (systemState == LOW_BATTERY &&
           batteryVoltage < LOW_BATTERY_RECOVERY)
  {
    systemState = LOW_BATTERY;
  }

  else
  {
    systemState = NORMAL;
  }
}

// MOTOR CONTROL

void calculateMotorOutput()
{
  switch (systemState)
  {
    case NORMAL:
      // Normal mode allows full requested throttle.
      targetPWM = requestedPWM;
      break;

    case LOW_BATTERY:
      // Limit motor output to reduce battery demand.
      targetPWM = min(requestedPWM, DERATED_PWM);
      break;

    case THERMAL_DERATING:
      // Limit output to reduce heating.
      targetPWM = min(requestedPWM, DERATED_PWM);
      break;

    case CRITICAL_FAULT:
      // Shut both motors off.
      targetPWM = 0;
      break;
  }
}

void updateMotorSpeed()
{
  // Gradually increase motor speed toward the target.
  if (currentPWM < targetPWM)
  {
    currentPWM += PWM_STEP;

    if (currentPWM > targetPWM)
    {
      currentPWM = targetPWM;
    }
  }

  // Gradually decrease motor speed toward the target.
  else if (currentPWM > targetPWM)
  {
    currentPWM -= PWM_STEP;

    if (currentPWM < targetPWM)
    {
      currentPWM = targetPWM;
    }
  }

  // Apply the same output to both motors.
  analogWrite(LEFT_MOTOR_PIN, currentPWM);
  analogWrite(RIGHT_MOTOR_PIN, currentPWM);
}

// LED STATUS INDICATORS

void updateStatusIndicators()
{
  // Turn all LEDs off before selecting the active one.
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(RED_LED, LOW);

  switch (systemState)
  {
    case NORMAL:
      digitalWrite(GREEN_LED, HIGH);
      break;

    case LOW_BATTERY:
    case THERMAL_DERATING:
      digitalWrite(YELLOW_LED, HIGH);
      break;

    case CRITICAL_FAULT:
      digitalWrite(RED_LED, HIGH);
      break;
  }
}

// BUZZER CONTROL

void updateBuzzer(unsigned long currentTime)
{
  // No buzzer in normal mode
  if (systemState == NORMAL)
  {
    noTone(BUZZER_PIN);
    buzzerOn = false;
    return;
  }

  // Toggle the buzzer at regular intervals
  if (currentTime - previousBuzzerTime >= BUZZER_INTERVAL)
  {
    previousBuzzerTime = currentTime;
    buzzerOn = !buzzerOn;

    if (buzzerOn)
    {
      if (systemState == CRITICAL_FAULT)
      {
        // Higher frequency for critical fault
        tone(BUZZER_PIN, 1200);
      }
      else
      {
        // Lower frequency for warnings
        tone(BUZZER_PIN, 700);
      }
    }
    else
    {
      noTone(BUZZER_PIN);
    }
  }
}

// LCD DISPLAY

void updateLCD()
{
  lcd.clear();

  // First LCD row: battery and throttle
  lcd.setCursor(0, 0);
  lcd.print("B:");
  lcd.print(batteryVoltage, 1);
  lcd.print("V ");

  lcd.print("T:");
  int throttlePercent = map(currentPWM, 0, 255, 0, 100);
  lcd.print(throttlePercent);
  lcd.print("%");

  // Second LCD row: operating state
  lcd.setCursor(0, 1);

  switch (systemState)
  {
    case NORMAL:
      lcd.print("SYSTEM NORMAL");
      break;

    case LOW_BATTERY:
      lcd.print("LOW BATTERY");
      break;

    case THERMAL_DERATING:
      lcd.print("THERMAL LIMIT");
      break;

    case CRITICAL_FAULT:
      if (batteryVoltage <= CRITICAL_BATTERY_VOLTAGE)
      {
        lcd.print("BATTERY FAULT");
      }
      else
      {
        lcd.print("TEMP SHUTDOWN");
      }
      break;
  }
}

// SERIAL MONITOR DATA LOGGING

void printSerialData()
{
  Serial.print("Throttle Raw: ");
  Serial.print(throttleRaw);

  Serial.print(" | PWM: ");
  Serial.print(currentPWM);

  Serial.print(" | Battery: ");
  Serial.print(batteryVoltage, 2);
  Serial.print(" V");

  Serial.print(" | Left Temp: ");
  Serial.print(leftTemperature, 1);
  Serial.print(" C");

  Serial.print(" | Right Temp: ");
  Serial.print(rightTemperature, 1);
  Serial.print(" C");

  Serial.print(" | State: ");

  switch (systemState)
  {
    case NORMAL:
      Serial.println("NORMAL");
      break;

    case LOW_BATTERY:
      Serial.println("LOW BATTERY");
      break;

    case THERMAL_DERATING:
      Serial.println("THERMAL DERATING");
      break;

    case CRITICAL_FAULT:
      Serial.println("CRITICAL FAULT");
      break;
  }
}

Комментарии и оценки

Войдите, чтобы продолжить.

Похожие проекты