Arduino + Servo SG90

Тема в разделе "Моторы, сервоприводы, робототехника", создана пользователем omadonex, 12 мар 2014.

  1. Мимино

    Мимино Нуб

    То есть правильно понимаю, что не нужно подключать ногу питания SG90 на 5V arduino, а нужно питание от sg90 пустить через реле, а управляющий сигнал подачи питания, сделать через digitalWrite(D[x], HIGH); Где х - номер какого-нибудь цифрового пина?
    В данном случае я могу надеяться, что при подаче питания, серво вновь не устроит себе самокалибровку через потенциометр?
    Или как я могу обратиться к ноге 5V и из кода отключить её до нужного мне момента?
     
  2. bsrgin

    bsrgin Нерд

    Купил сей замечательный девайс в Китае, столкнулся с проблемами, которые были обозначены в самом начале топика: серво поворачивалось на 0 и 90 градусов и этот поворот действительно был под прямым углом, но при попытке повернуть серво в позицию 180 градусов - отчётливо слышался скрёжет и натужный гул движка, при этом угол между 90 и 180 не был прямым.
    Выбор другой ноги и метода запитывания сервы проблему не решили. Разбирать серву "для калибровки угла поворота" не стал.

    Помогла следующая методика: подбор длительности импульса для крайних позиций 0 и 180.
    Значения по умолчанию у метода Servo::attach(pin, 544, 2400).
    Мне же подошли значения Servo::attach(pin, 640, 2260).
    При этом угол поворота между 0 и 180 (по транспортиру) действительно стал соответствовать 180 градусам, а в позицию 90 градусов серво поворачивает под прямым углом из позиций в 0 и из 180 градусов.

    Алгоритм для подбора следующий:
    Код (C++):

    #include <Servo.h>
    Servo sonar_servo;
    void setup()
    {
      sonar_servo.attach(PIN_SG90_CONTROL, 640, 2260); // подбираем эти min- и max-значения
    }
    void loop()
    {
      unsigned positions[6] = {1,0,1,179,180,179};
      while (1)
      {
        for (int i = 0; i < sizeof(positions)/sizeof(positions[0]); i++)
        {
          sonar_servo.write(positions[i]);
          delay(1000);
        }
      }
    }
    После запуска и правильного подбора значений серва не должна гудеть, скрипеть и издавать посторонних звуков. Также позиционирование из одного крайнего положения в другое крайнее положение не должно сопровождаться подпрыгиванием незакреплённой сервы, как будто шестерни бьются о какой-то ограничитель и такой удар отражается в корпус сервы.

    Рекомендую начать подбор с сильно "загрублённых" значений, таких при которых не появляется описанных выше проблем, в моём случае серва отчётливо гудела как в позиции max=2400, так и в max=2300, я её сбросил до max=2200 и стал плавно повышать значение параметра следя за углами поворота. Ещё моя серва "улетала" в отрицательные значения угла поворота при min=484, при этом не было гудения, но корпус вздрагивал! В итоге я подобрал значение max=2260 при котором серва не гудела и не вздрагивала при повороте и относительно max=2260 подобрал min=640 по транспортиру.

    Также следите за тем, чтобы серва меняла угол поворота в позициях 179 и 180, а также 0 и 1. Например, если между позициями 0 и 1 наблюдается значительный поворот сервы, который явно не соответствует одному градусу, то min-значение подобрано неправильно. Также, если, например между позициями 179 и 180 серва не двигается, то max-значение также подобрано неправильно.

    Здесь следует сказать, что поскольку угол поворота считается как angle*(max-min)/180, то приведённый выше код только тогда поможет подобрать правильные значения, когда вы одновременно подберёте и min, и max. Думаю сказываются погрешности в округлении при расчёте угла таким образом, что серва может не двигаться из позиции 0 в позицию 1, либо же из 179 в 180.
     
    Последнее редактирование: 6 ноя 2016
    avex, sevalob и acos нравится это.
  3. sevalob

    sevalob Нуб

    СПАСИБО ТЕБЕ ОГРОМНОЕ =)

    Просто спас =) Все супер работает теперь, ни единого шороха, у кого SG90 трещит, гудит строго по этому гайду.
     
  4. Darwinian

    Darwinian Нуб

    Чтобы было удобней подбирать значения, написал такую программку.
    Код (C++):
    #include <Servo.h>
    Servo servo;
    const int SERVO_PIN = 9;
    void setup()
    {
      servo.attach(SERVO_PIN, 640, 2600); // подбираем эти min- и max-значения
      Serial.begin(9600);
      printHelp();

    }
    int minValue = 640;
    int maxValue = 2600;
    int minLoopAngle = 45;
    int maxLoopAngle = 135;
    int loopStep = 1;
    int loopSleep = 15;
    int angle = 90;

    int value;
    void loop()
    {
      while(Serial.available()) {
        processInput();
        printHelp();
      }
    }

    void processInput() {
        int variant = Serial.parseInt();

        if (Serial.available()) {
          value = Serial.parseInt();
        }
        Serial.print("Got "); Serial.print(variant);
        Serial.print(" and value "); Serial.println(value);
       
        switch (variant) {
          case 1:
            minValue = value;
            servo.attach(SERVO_PIN, minValue, maxValue);
            servo.write(angle);
            break;
          case 2:
            maxValue = value;
            servo.attach(SERVO_PIN, minValue, maxValue);
            servo.write(angle);
            break;
          case 3:
            minLoopAngle = value; break;
          case 4:
            maxLoopAngle = value; break;
          case 5:
            loopStep = value; break;
          case 6:
            loopSleep = value; break;
          case 7:
            for (angle = minLoopAngle; angle <= maxLoopAngle; angle += loopStep) {
              servo.write(angle);
    //          Serial.print("Current angle is "); Serial.println(angle);
              delay(loopSleep);
            }
            break;
          case 8:
            angle = value;
            servo.write(angle);
            break;
          case 9:
            angle += value;
            servo.write(angle);
            break;
          default:
            Serial.println("Unknown command.");
        }
    }

    void printHelp() {
        Serial.print("1 - minValue (now is "); Serial.print(minValue); Serial.println(")");
        Serial.print("2 - maxValue (now is "); Serial.print(maxValue); Serial.println(")");
        Serial.print("3 - minLoopAngle (now is "); Serial.print(minLoopAngle); Serial.println(")");
        Serial.print("4 - maxLoopAngle (now is "); Serial.print(maxLoopAngle); Serial.println(")");
        Serial.print("5 - loopStep (now is "); Serial.print(loopStep); Serial.println(")");
        Serial.print("6 - loopSleep (now is "); Serial.print(loopSleep); Serial.println(")");
        Serial.println("7 - start loop");
        Serial.print("8 - absolute angle (now is "); Serial.print(angle); Serial.println(")");
        Serial.print("9 - relative angle (now is "); Serial.print(angle); Serial.println(")");
        Serial.println("Enter your choise and after a space enter a value");
    }


     
    Основная идея: ввод значений с терминала. Чтобы не попутать команды, регулярно выводится помощь по ним. Ввод происходит в формате: номер пункта, пробел, значение. Например, для установки верхней границы в 2800 нужно написать "2 2800" и нажать Enter.
    Краткое описание пунктов:
    1 и 2 - собственно, нижнее и верхнее значения.
    3 - 6 - установка параметров цикла. То есть можно поворачивать на заданный угол с паузами. Параметры: от угла, до угла (всё включительно), шаг, длительность паузы между поворотами на один шаг.
    7 - запуск цикла. Предварительно лучше сделать перевод на начальный угол вручную.
    8 - поворот в заданное значение угла.
    9 - поворот на заданное значение градусов относительно текущей позиции. Может хавать отрицательные значения угла здесь.

    Прямо в отображаемой подсказке о пунктах меню можно видеть текущие значения параметров. Рекомендуется их записать на бумажку перед тем, как закрывать терминал :)

    Но лично мне свой серво настроить на угол 90 градусов относительно крайних значений так и не удалось. Относительно нуля получается больше 90 градусов поворот. Хотя мне не то, чтобы и сильно важно здесь, но всё же обидно немного. :confused:
     
  5. avex

    avex Нерд

    Сколько у Вас уходило времени на подбор пары max и min? Там же с ума сойти, сколько вариантов да плюс учёт формулы в последнем абзаце.