Загрузка данных


ARDUINO IDE CODE:

#include <Servo.h>

// --- НАСТРОЙКА СЕРВОПРИВОДА И ДАТЧИКА ---
Servo servoYaw;          // Сервопривод для разворота влево/вправо
const int trigPin = 12;  // Датчик: Trig
const int echoPin = 13;  // Датчик: Echo

// --- НАСТРОЙКА ШАГОВОГО МОТОРА (ПО ФОТО) ---
const int IN1 = 8;  const int IN2 = 9;
const int IN3 = 10; const int IN4 = 11;

// --- ПЕРЕМЕННЫЕ СОСТОЯНИЯ ---
int stepDelay = 3;       // Пауза мотора в мс (скорость/высота дрона)
int yaw = 90;            // Угол сервопривода (разворот)
char mode = 'M';         // Режим: 'M' - ручной, 'A' - автомат
int stepCounter = 0;

// Матрица шагов для ULN2003
const int steps[4][4] = {
  {1, 0, 0, 1}, {1, 1, 0, 0}, {0, 1, 1, 0}, {0, 1, 1, 1}
};

void setup() {
  Serial.begin(9600);
  
  servoYaw.attach(3);    // Подключите сигнальный провод сервопривода к Pin 3!
  servoYaw.write(yaw);
  
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
  pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT);
}

// Функция одного микрошага для мотора высоты (1 - вперед, -1 - назад)
void moveStep(int dir) {
  stepCounter += dir;
  if (stepCounter > 3) stepCounter = 0;
  if (stepCounter < 0) stepCounter = 3;
  digitalWrite(IN1, steps[stepCounter][0]);
  digitalWrite(IN2, steps[stepCounter][1]);
  digitalWrite(IN3, steps[stepCounter][2]);
  digitalWrite(IN4, steps[stepCounter][3]);
  delay(stepDelay);
}

void loop() {
  // 1. Измерение расстояния датчиком
  digitalWrite(trigPin, LOW); delayMicroseconds(2);
  digitalWrite(trigPin, HIGH); delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH);
  int dist = constrain(duration * 0.034 / 2, 0, 150);
  
  Serial.print("DIST:");
  Serial.println(dist);

  // 2. Ручной режим управления от Python
  if (Serial.available() > 0) {
    char cmd = Serial.read();
    if (cmd == 'M') mode = 'M';
    if (cmd == 'A') mode = 'A';
    
    if (mode == 'M') {
      if (cmd == 'U') stepDelay = max(1, stepDelay - 1);  // Газ + (набор высоты)
      if (cmd == 'D') stepDelay = min(10, stepDelay + 1); // Газ - (снижение)
      if (cmd == 'L') { yaw = max(0, yaw - 15);   servoYaw.write(yaw); } // Разворот влево
      if (cmd == 'R') { yaw = min(180, yaw + 15); servoYaw.write(yaw); } // Разворот вправо
    }
  }

  // 3. Автоматический режим полета
  if (mode == 'A') {
    if (dist < 30) {
      // Препятствие близко: экстренно рулим влево и тормозим мотор
      servoYaw.write(45);
      stepDelay = 10; 
      moveStep(1); 
    } else {
      // Путь свободен: летим прямо и быстро крутим мотор (набираем высоту)
      servoYaw.write(90);
      stepDelay = 2;  
      moveStep(1);   
    }
  }
}

PYTHON CODE:

import os, serial
import tkinter as tk

# --- ПОДКЛЮЧЕНИЕ К ARDUINO ---
port = 'COM3'  # Измените на порт вашей Arduino (например, 'COM4'), если он другой
try: ser = serial.Serial(port, 9600, timeout=0.01)
except Exception: ser = None

def send(cmd):
    if ser: ser.write(cmd.encode())
    else: print(f"[Демо] Отправлено: {cmd}")

def update_dist():
    if ser:
        while ser.in_waiting:
            try:
                line = ser.readline().decode().strip()
                if line.startswith("DIST:"):
                    # Четко забираем число сантиметров после двоеточия
                    dist_value = line.split(":")[1]
                    dist_label.config(text=f"{dist_value} см")
            except Exception: pass
    root.after(50, update_dist)

root = tk.Tk()
root.title("Управление дроном"); root.geometry("340x440")

# --- ЗАГРУЗКА КАРТИНОК ИЗ ПАПКИ ПРОЕКТА ---
def load_img(name):
    return tk.PhotoImage(file=name) if os.path.exists(name) else None

img_L = load_img("BCleft.png")      # Разворот влево (Сервопривод)
img_R = load_img("BCright.png")     # Разворот вправо (Сервопривод)
img_D = load_img("BCbottom.png")    # Снижение высоты (Шаговый мотор медленнее)
img_U = load_img("BCvertical.png")  # Набор высоты (Шаговый мотор быстрее)

# --- ИНТЕРФЕЙС GUI ---
tk.Label(root, text="Расстояние до препятствия:", fg="gray").pack(pady=(10,0))
dist_label = tk.Label(root, text="0 см", font=("Arial", 20, "bold")); dist_label.pack()

mode_frame = tk.Frame(root); mode_frame.pack(pady=10)
tk.Button(mode_frame, text="Ручной", command=lambda: [send('M'), status.config(text="Ручной", fg="blue")], width=10).pack(side="left", padx=5)
tk.Button(mode_frame, text="Автомат", command=lambda: [send('A'), status.config(text="Автомат", fg="green")], width=10).pack(side="left", padx=5)
status = tk.Label(root, text="Ручной", fg="blue"); status.pack()

# --- КРЕСТОВИНА ДЖОЙСТИКА (4 НАПРАВЛЕНИЯ) ---
btn_frame = tk.Frame(root); btn_frame.pack(pady=20)

def create_btn(row, col, txt, cmd, img):
    btn = tk.Button(btn_frame, command=lambda: send(cmd))
    if img: btn.config(image=img)
    else: btn.config(text=txt, width=10, height=2)
    btn.grid(row=row, column=col, padx=6, pady=6)

create_btn(0, 1, "Вверх",  'U', img_U)  # Шаговый мотор быстрее
create_btn(1, 0, "Влево",  'L', img_L)  # Сервопривод влево
create_btn(1, 2, "Вправо", 'R', img_R)  # Сервопривод вправо
create_btn(2, 1, "Вниз",   'D', img_D)  # Шаговый мотор медленнее

root.after(100, update_dist)
root.mainloop()