| //Скетч для модели управляемый по bluetooth. #include Servo.h // Добавляем библиотеку для работы с сервомеханизмами Servo myservoH; // Горизонтальная серва углы от 25 до 145 (центровка 85) Servo myservoV; // Вертикальная серва углы от 0 до 35 const int H_SERVO_PIN = 9; // Горизонтальная серва подключена к пину 11 const int V_SERVO_PIN = 10; // Пин вертикального сервопривода const float H_L_ANGLE = 145; // Максимальные угол поворота башни налево const float H_R_ANGLE = 25; // Максимальные угол поворота башни направо const float H_DEF_ANGLE = 85; // Дефолтный угол (центровка) const float V_U_ANGLE = 55; // Максимальные угол поворота башни вверх const float V_D_ANGLE = 0; // Максимальные угол поворота башни вниз const float V_DEF_ANGLE = 25; // Дефолтный угол (центровка) //Размер шага V_STEP и H_STEP подбираем экспериментально для достижения нужной скорости поворота серв const float V_STEP = 0.007; // Шаг - значение отвечающее за скорость вращения по вертикали. const float H_STEP = 0.007; // Шаг - значение отвечающее за скорость вращения по горизонтали float curVAngle = V_DEF_ANGLE; // Переменная текущего угла вертик. сервы float curHAngle = H_DEF_ANGLE; // Переменная текущего угла гориз. сервы bool moveServoVUp = false; // Флаг движения верт. сервы вверх bool moveServoVDown = false; // Флаг движения верт. сервы вниз bool moveServoHLeft = false; // Флаг движения гориз. сервы влево bool moveServoHRight = false; // Флаг движения гориз. сервы вправо const int TIMEOUT_TIME_MS = 150; unsigned long lastPilotSymbolTime; char symbol; int val; int IN1 = 5; // выводы для мотор - шилда подключены к следующим пинам Arduino int IN2 = 6; int IN3 = 7; int IN4 = 8; // Для удобства подключения, затвор мосфета подключен к аналоговому входу A0, однако, // входы A0-A6 можно использовать как цифровые, в коде будут нумероваться как 14-19 int SHOT = 14; // пин А0 на Arduino int LED = 4; // Используем встроенный светодиод для индикации работы enum States { WAITING, READING, RUNNING, ERROR, TIMEOUT }; States state; States onWait(); States onRead(); States onRun(); States onError(); States onTimeout(); void performServo(); void setup() { Serial.begin(9600); // скорость связи с компьютером lastPilotSymbolTime = 0; pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); pinMode(SHOT, OUTPUT); myservoH.attach(H_SERVO_PIN); // устанавливаем пин как вывод управления сервой myservoV.attach(V_SERVO_PIN); myservoH.write(curHAngle); myservoV.write(curVAngle); pinMode(LED, OUTPUT); // используем 4 пин как индикатор включённой ардуины digitalWrite(LED, HIGH); } void loop() { switch (state) { case WAITING: state = onWait(); break; case READING: state = onRead(); break; case RUNNING: state = onRun(); break; case TIMEOUT: state = onTimeout(); break; default: state = onError(); } performServo(); } States onWait() { if (Serial.available() 0) { return READING; } if (lastPilotSymbolTime && (millis() - lastPilotSymbolTime TIMEOUT_TIME_MS)) { return TIMEOUT; } return WAITING; } States onRead() { symbol = Serial.read(); return RUNNING; } States onRun() { switch (symbol) { case 'W': //начало действий при полученном символе 'W' (вперед) digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); break; case 'w': //начало действий при полученном символе 'w' (стоп вперед) digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 'S': //начало действий при полученном символе 'S' (назад) digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); break; case 's': //начало действий при полученном символе 's' (назад стоп) digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 'A': //начало действий при полученном символе 'A' (влево) digitalWrite(IN1, LOW); digitalWrite(IN2, HIGH); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); break; case 'a': //начало действий при полученном символе 'a' (влево стоп) digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 'D': //начало действий при полученном символе 'D' (вправо) digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, HIGH); break; case 'd': //начало действий при полученном символе 'd' (вправо стоп) digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); break; case 'Z': //начало действий при полученном символе 'Z' (вкл пушка) digitalWrite(SHOT, HIGH); break; case 'z': //начало действий при полученном символе 'z' (выкл пушка) digitalWrite(SHOT, LOW); break; // Сервы case 'I': // servoV вверх moveServoVUp = true; break; case 'K': // servoV вниз moveServoVDown = true; break; case 'i': // servo V стоп moveServoVUp = false; moveServoVDown = false; break; case 'L': // servo H движется к 25 moveServoHRight = true; break; case 'J': // servo H движется к 145 moveServoHLeft = true; break; case 'l': // servo H стоп moveServoHLeft = false; moveServoHRight = false; break; case 'U': curVAngle = V_DEF_ANGLE; curHAngle = H_DEF_ANGLE; myservoV.write(curVAngle); myservoH.write(curHAngle); break; case 'T': //начало действий при полученном символе 'T' (остановка) digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); digitalWrite(SHOT, LOW); break; case 'P': //получили контрольный символ, не изменяйте этот код lastPilotSymbolTime = millis(); break; default: return ERROR; } return WAITING; } States onError() { //Получены неоговоренные символы. Очищаем ввод и продолжаем. //Здесь можно добавить какие-то действия для этой ситуации. while (Serial.available()) { Serial.read(); } return WAITING; } States onTimeout() { //Действия при таймауте. Вероятно, связь утеряна, но при получении контрольного символа она будет восстановлена. //Здесь, например, уместно выключить двигатели digitalWrite(IN1, LOW); // На пары выводов IN поданы сигналы одинакового уровня, моторы не работают digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); digitalWrite(SHOT, LOW); if (Serial.available()) { return READING; } return TIMEOUT; } //Функция управления сервоприводами (вызывается в теле loop на каждой итерации) //Выполняет изменения положения серв на подобранный шаг согласно установленным флагам движения //Флаги устанавливаются согласно поступившим символам управления сервами void performServo() { // Установлен флаг движения вверх и текущий угол не максимальный if (moveServoVUp && curVAngle + V_STEP { // К текущему верт. углу прибавляем шаг curVAngle += V_STEP; } // Установлен флаг движения вниз и текущий угол не минимален else if (moveServoVDown && curVAngle - V_STEP = V_D_ANGLE) { // От текущего верт. угла отнимаем шаг curVAngle -= V_STEP; } // Установлен флаг движения влево и текущий угол не максимален if (moveServoHLeft && curHAngle + H_STEP { // К текущему гор. углу прибавляем гор. шаг curHAngle += H_STEP; } // Установлен флаг движения вправо и текущий угол не минимален else if (moveServoHRight && curHAngle - H_STEP = H_R_ANGLE) { // От текущего угла отнимаем гор. шаг curHAngle -= H_STEP; } // Если было движние по вертикали if (moveServoVUp || moveServoVDown) { myservoV.write(curVAngle); } // Если было движение по горизонтали if (moveServoHLeft || moveServoHRight) { myservoH.write(curHAngle); } } |