#1 2025-08-31 15:41:48

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 23

Arduino vs Servo

Вітаю
Знайомий купив сервотестер за 400 грн,взяв спробувати ...не сподобався
Зробив свій ,може кому знадобиться

servotst.jpg




#include <Servo.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// === OLED 128x64 (измени на 32, если у тебя 0.91") ===
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// === Пины ===
const int BUTTON_PIN = A1;     // ADKeyboard
const int POT_PIN = A3;        // Потенциометр
const int SERVO_PIN = 9;

// === Диапазоны ШИМ ===
const int MIN1 = 900,  MAX1 = 2100;  // Режим 1
const int MIN2 = 700,  MAX2 = 2300;  // Режим 2
const int MIN3 = 500,  MAX3 = 2500;  // Режим 3

// === ADC значения ADKey (QYF-995) ===
const int ADC_MODE1  = 786;  // Переключает: MANUAL → AUTO → R-POS
const int ADC_LEFT   = 145;  // Влево
const int ADC_MODE2  = 493;  // Меняет скорость в AUTO
const int ADC_MODE3  = 0;    // Переключает режимы 1→2→3
const int ADC_RIGHT  = 304;  // Вправо
const int ADC_TOLERANCE = 50;

// === Режимы управления ===
enum ControlMode { MANUAL, AUTO, RPOS };
ControlMode controlMode = MANUAL;

// === Переменные ===
Servo myservo;
int mode = 1;                    // 1,2,3 — диапазон
int pos1 = 1500, pos2 = 1500, pos3 = 1500;
int currentMicros = 1500;

// === Авто-режим ===
unsigned long lastAutoMove = 0;
bool autoDirection = true;
int autoStep = 10;

// === Скорость в AUTO ===
int autoSpeedIndex = 1;
int autoSpeeds[3] = {300, 150, 80}; // ms

// === Тихий режим (отключение сервы при покое) ===
unsigned long lastMoveTime = 0;
bool isDetached = false;

// === Для удержания кнопок ===
int lastButton = -1;
unsigned long lastPressTime = 0;
const int DEBOUNCE_DELAY = 200;

// === Прототипы функций ===
int readButton(int adcValue);
void switchMode(int newMode);
int getMin();
int getMax();
void updateDisplay();

void setup() {
  Serial.begin(9600);
  Serial.println("=== Servo Tester: Final Build ===");

  // === OLED ===
  delay(100);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED not found!");
    while (1);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Starting...");
  display.display();
  delay(1000);

  switchMode(1);
  currentMicros = 1500;
  myservo.writeMicroseconds(currentMicros);
  lastMoveTime = millis();
  updateDisplay();
}

void loop() {
  int adcValue = analogRead(BUTTON_PIN);
  int button = readButton(adcValue);

  // === Обработка нажатий ===
  if (button != -1 && button != lastButton) {
    lastPressTime = millis();
    lastButton = button;

    // === MODE 3: смена диапазона ===
    if (button == 3) {
      mode = (mode % 3) + 1;
      switchMode(mode);
      updateDisplay();
    }

    // === MODE 2: смена скорости в AUTO ===
    else if (button == 2 && controlMode == AUTO) {
      autoSpeedIndex = (autoSpeedIndex + 1) % 3;
      updateDisplay();
    }

    // === MODE 1: смена режима управления ===
    else if (button == 0) {
      if (controlMode == MANUAL)      controlMode = AUTO;
      else if (controlMode == AUTO)   controlMode = RPOS;
      else if (controlMode == RPOS)   controlMode = MANUAL;
      updateDisplay();
    }
  }

  // === Выход из AUTO или R-POS при LEFT/RIGHT ===
  if (controlMode != MANUAL && (button == 1 || button == 4)) {
    controlMode = MANUAL;
    updateDisplay();
  }

  // === Ручное управление ===
  if (controlMode == MANUAL) {
    if (button == 1 && currentMicros > getMin()) {
      if (millis() - lastPressTime > 100) {
        currentMicros -= (millis() - lastPressTime > 500) ? 20 : 10;
        if (currentMicros < getMin()) currentMicros = getMin();
        attachAndWrite(); // включает серву, если была отключена
        lastMoveTime = millis();
        updateDisplay();
        lastPressTime = millis();
      }
    }
    if (button == 4 && currentMicros < getMax()) {
      if (millis() - lastPressTime > 100) {
        currentMicros += (millis() - lastPressTime > 500) ? 20 : 10;
        if (currentMicros > getMax()) currentMicros = getMax();
        attachAndWrite();
        lastMoveTime = millis();
        updateDisplay();
        lastPressTime = millis();
      }
    }
  }

  // === Авто-режим ===
  if (controlMode == AUTO) {
    if (millis() - lastAutoMove > autoSpeeds[autoSpeedIndex]) {
      lastAutoMove = millis();
      if (autoDirection) {
        currentMicros += autoStep;
        if (currentMicros >= getMax()) {
          currentMicros = getMax();
          autoDirection = false;
        }
      } else {
        currentMicros -= autoStep;
        if (currentMicros <= getMin()) {
          currentMicros = getMin();
          autoDirection = true;
        }
      }
      attachAndWrite();
      lastMoveTime = millis();
      updateDisplay();
    }
  }

  // === Управление от потенциометра ===
  if (controlMode == RPOS) {
    int potValue = analogRead(POT_PIN);
    int target = map(potValue, 0, 1023, getMin(), getMax());
    if (abs(currentMicros - target) > 5) {
      currentMicros += (currentMicros < target) ? 5 : -5;
      attachAndWrite();
      lastMoveTime = millis();
      updateDisplay();
    }
  }

  // === Авто-отключение сервы при покое (тихий режим) ===
  if (!isDetached && millis() - lastMoveTime > 3000) {
    myservo.detach();
    isDetached = true;
  }

  // === Сброс кнопки ===
  if (button == -1 && lastButton != -1) {
    lastButton = -1;
  }

  delay(5);
}

// === Функция: включить серву и отправить сигнал ===
void attachAndWrite() {
  if (isDetached) {
    myservo.attach(SERVO_PIN, getMin(), getMax());
    isDetached = false;
  }
  myservo.writeMicroseconds(currentMicros);
}

// === Определение кнопки ===
int readButton(int adcValue) {
  if (abs(adcValue - ADC_MODE1)  < ADC_TOLERANCE) return 0;
  if (abs(adcValue - ADC_LEFT)   < ADC_TOLERANCE) return 1;
  if (abs(adcValue - ADC_MODE2)  < ADC_TOLERANCE) return 2;
  if (abs(adcValue - ADC_MODE3)  < ADC_TOLERANCE) return 3;
  if (abs(adcValue - ADC_RIGHT)  < ADC_TOLERANCE) return 4;
  return -1;
}

// === Переключение режима ===
void switchMode(int newMode) {
  if (mode == 1) pos1 = currentMicros;
  if (mode == 2) pos2 = currentMicros;
  if (mode == 3) pos3 = currentMicros;
  mode = newMode;
  if (mode == 1) {
    myservo.attach(SERVO_PIN, MIN1, MAX1);
    currentMicros = pos1;
  } else if (mode == 2) {
    myservo.attach(SERVO_PIN, MIN2, MAX2);
    currentMicros = pos2;
  } else if (mode == 3) {
    myservo.attach(SERVO_PIN, MIN3, MAX3);
    currentMicros = pos3;
  }
  myservo.writeMicroseconds(currentMicros);
  lastMoveTime = millis();
  isDetached = false;
}

// === Мин/макс текущего режима ===
int getMin() { return (mode == 1) ? MIN1 : (mode == 2) ? MIN2 : MIN3; }
int getMax() { return (mode == 1) ? MAX1 : (mode == 2) ? MAX2 : MAX3; }

// === Обновление дисплея ===
void updateDisplay() {
  display.clearDisplay();

  display.setCursor(0, 0);
  display.print("Control:");
  if (controlMode == MANUAL) display.println("MANUAL");
  else if (controlMode == AUTO) display.println("AUTO");
  else if (controlMode == RPOS) display.println("R-POS ");

  display.setCursor(0, 12);
  display.print("Range:");
  display.print(getMin());
  display.print("-");
  display.print(getMax());

  display.setCursor(0, 24);
  display.print("Position:");
  display.print(currentMicros);

  if (controlMode == AUTO) {
    display.setCursor(0, 36);
    display.print("Spd:");
    if (autoSpeedIndex == 0) display.println("Slow");
    else if (autoSpeedIndex == 1) display.println("Medium");
    else display.println("Fast");
  } else {
    display.setCursor(0, 36);
    display.println("Speed:---");
  }

  // Прогресс-бар
  int bar = map(currentMicros, getMin(), getMax(), 0, 126);
  display.drawRect(1, 54, 126, 6, SSD1306_WHITE);
  display.fillRect(2, 55, bar, 4, SSD1306_WHITE);

  display.display();
}

Інструкція з використання тестера сервоприводу

Цей пристрій призначений для тестування сервоприводів з можливістю зміни діапазону керування, режимів роботи та візуальним відображенням на дисплеї OLED.

Підключення:

Підключіть сервопривід до піну PWM (сигнальний дріт — жовтий/білий).
Підключіть живлення:Бажано використовувати окреме джерело 5–12 В для сервоприводу.
Загальна "земля" (GND) повинна бути спільною з Arduino.
         
     


Керування кнопками ADKeyboard

Кнопка MODE 1:
   
Перемикає режим керування:
MANUAL-AUTO-R-POSITION

Кнопка MODE 3:
Перемикає діапазон ШІМ:
900–2100 us
700–2300
500–2500

Кнопка MODE 2:
   
У режимі AUTO: змінює швидкість руху:
повільно > середньо > швидко

Кнопка LEFT у режимі MANUAL: переміщує сервопривід вліво
Кнопка RIGHT у режимі MANUAL: переміщує сервопривід вправо

Режими керування
1. MANUAL (ручний режим)

Керування кнопками LEFT і RIGHT.
При короткому натисканні — малий крок (10 мкс).
При довгому утриманні — плавне прискорення (до 20 мкс за крок).
Вихід з режимів AUTO або R-POSITION — натисніть LEFT або RIGHT.
     

2. AUTO (автоматичний режим)

Сервопривід автоматично рухається від мінімального до максимального положення і назад.
Швидкість змінюється кнопкою MODE 2.
Вихід: натисніть LEFT або RIGHT.
     

3. R-POS (керування від потенціометра)

Оберіть потенціометр на A3, щоб керувати положенням сервоприводу.
Вихід: натисніть LEFT або RIGHT.
     


Інформація на OLED-дисплеї

На дисплеї відображається:

Ctrl: поточний режим керування (MANUAL, AUTO, R-POSITION)
Range: діапазон ШІМ (наприклад, 900-2100)
Position: поточне положення сервоприводу в мікросекундах (мкс)
Speed: швидкість у режимі AUTO (Slow, Medium, Fast)
Прогрес-бар: візуальне відображення положення сервоприводу
     


Тихий режим (автоматичне відключення):

Якщо сервопривід не рухається 3 секунди, він автоматично відключається (detach),
щоб не гудів.При наступному керуванні він автоматично підключається назад.
     


Поради та зауваження:

Якщо сервопривід гудить у спокої — це нормально для дешевих моделей (SG90, MG996R).
Він намагається утримати положення.Для стабільної роботи використовуйте окреме джерело
живлення.

Остання редакція nickjust (2025-08-31 15:52:19)

Неактивний

#2 2025-08-31 15:58:35

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 23

Re: Arduino vs Servo

Маю запитання !
Хто мав справу с сервоприводами з літаючих "тварин"
наприклад SERV 01.02-150-15-PWM
Не можу запустити ,веде себе не адекватно
Візуально цілий
Живлення 12В. BLDC-сервопривід с енкодером з PWM

Неактивний

#3 2025-08-31 21:12:49

jokeer
Гість

Re: Arduino vs Servo

У вас талант ставити питання розпливчато wink Неадекватно це як?
Гуглиться відео про підключення серви від Шахеда.

#4 Вчора 11:25:51

jokeer
Гість

Re: Arduino vs Servo

Сорян, те що гуглиться - просто обзор. Дивіться, тут червоний проводок а тут аж 2 чорних.
хттпс://www.youtube.com/shorts/_nfCpUB943s

#5 Вчора 15:03:49

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 23

Re: Arduino vs Servo

ха...неадекватно ,починаю керувати ,добре повертає вліво-вправо...а потім може поїхати казна-куди..ще падло пищить і гріється
в мене підозра ,що його тре калібрувати...

Неактивний

#6 Вчора 15:09:47

jokeer
Гість

Re: Arduino vs Servo

Після падіння може що завгодно бути.від мікротріщини до пошкодження резистора що міряє кут.

#7 Вчора 16:02:32

jokeer
Гість

Re: Arduino vs Servo

Про сервотестер. Все значно простіше wink. Коли мені був потрібен, я припаяв резистор і конденсатор до ардуїни, залив Examples - Servo - Knob. Така конструкція як у вас може мати смисл, коли цих приводів треба крутити 100 штук в день.

#8 Вчора 19:16:02

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 23

Re: Arduino vs Servo

там енкодер стоїть
може ви і праві ..."Поскользнулся,упал,потерерял сознание,очнулся,ГИПС"
нарахунок конструкції ...це просто нехер робити

Неактивний

#9 Вчора 20:42:52

jokeer
Гість

Re: Arduino vs Servo

А живлення ви нормальне подаєте? Від двигуна можуть бути непогані імпульсні завади. Зашунтуйте живлення low esr конденсатором на 1000 мкф.

#10 Сьогодні 07:55:36

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 23

Re: Arduino vs Servo

живлення від компа ...5 і 12 в,обіцяли такий самий ...спробую його
Вчора дросельний-сірий запустив ...оцей норм працює,хоча дротів 9 шт.

Неактивний

#11 Сьогодні 09:53:42

jokeer
Гість

Re: Arduino vs Servo

В мене при живленні від USB серва іноді може ребутнути ардуїну. Там завади нормальні. Спробуйте з конденсатором. Воно ж на роботу від акумулятора розраховане, там внутрішній опір мізерний.

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму