Arduino Servo не будет двигаться при использовании классов

Я пытаюсь заставить класс работать с Arduino, но, похоже, он не запускается должным образом. Код компилируется идеально, и предполагается, что он управляет ногой шестиногого ножа. Кроме того, пример развертки работает на этом сервоприводе, так что здесь нет проблем. Однако на самом деле сервопривод не движется. Я думаю, это как-то связано с порядком объявления переменных:

#include <Servo.h>

// Абстрагируем каждую ветвь, поэтому возможен доступ только к этим функциям
class Leg {
  // Действия, которые могут быть вызваны извне
  public:
    Leg(int hipPin, int kneePin);
    void up();

  // Они должны быть доступны только для ноги
  private:
    Servo hip;
    Servo knee;
  };

Leg::Leg(int hipPin, int kneePin) {
  hip.attach(hipPin);
  knee.attach(kneePin);
  }

// Тестируем ногу: двигаем ее вверх
void Leg::up() {
  for(int pos = 0; pos < 180; pos += 1) {
    hip.write(pos);
    delay(15);
    }
  }


// Инициализируем ногу
Leg topLeft(9, 10);

void setup() {
  }

// Тестируем функцию up()
void loop() {
  topLeft.up();
  }

Я проверяю только контакт 9 (оставляю 10 пустым). Ему кажется больно, то есть вы можете видеть, как сервопривод дрожит, но на самом деле не движется при 0 градусах.

, 👍7

Обсуждение

Примечание: аналогичный вопрос [к этому](http://stackoverflow.com/q/18160980/938236), но поскольку решение не сработало для меня, я предполагаю, что это не та же самая проблема. Любая помощь в отладке также приветствуется (:, @Francisco Presencia

Работает ли та же настройка с тем же пином, когда вы тестируете только код сервопривода бедра вне класса? Проблема возникает только тогда, когда код находится внутри класса Leg?, @Omer

Ваша проблема может быть похожа на этот вопрос: http://arduinoprosto.ru/q/830/timer2-does-not-work-as-it-should, @jfpoilpret


1 ответ


Лучший ответ:

5

Похоже, эта проблема может быть связана с неправильным порядком вызовов инициализаторов для глобальных переменных.

В C++ порядок инициализации глобальных переменных непредсказуем в разных единицах компиляции (т. е. исходных файлах C++, а не заголовочных файлах). Порядок инициализации соблюдается только внутри одной единицы компиляции.

В вашей программе есть несколько глобальных переменных, инициализация которых в неправильном порядке приведет к сбою вашей программы:

  • Нога верхняя левая; это ваш экземпляр класса
  • servo_t сервоприводы[MAX_SERVOS];, int8_t Channel[_Nbr_16timers ]; и uint8_t ServoCount = 0; все определены в Servo.cpp

Вызов Servo.attach() требует, чтобы 3 указанные выше переменные уже были инициализированы, в чем вы не можете быть уверены.

Как это можно исправить?

Не выполняя attach() в конструкторе Leg, а делегируя его какому-либо методу init(), который можно вызвать из setup():

class Leg {
    // Действия, которые могут быть вызваны извне
    public:
    void init(int hipPin, int kneePin);
    void up();

    // Они должны быть доступны только для ноги
    private:
    Servo hip;
    Servo knee;
};

Leg::init(int hipPin, int kneePin) {
    hip.attach(hipPin);
    knee.attach(kneePin);
}

// Тестируем ногу: поднимите ее
void Leg::up() {
    for(int pos = 0; pos < 180; pos += 1) {
        hip.write(pos);
        delay(15);
    }
}

// Объявляем ногу
Leg topLeft;

void setup() {
    // Инициализируем ногу
    topLeft.init(9, 10);
}

// Тест функции up()
void loop() {
    topLeft.up();
}
,

Для ясности: порядок инициализации глобальных переменных определяется не только между разными единицами трансляции. В одной и той же единице трансляции это порядок их определений., @Omer

+1 это золото, объяснение только что решило около 100% нерешенных проблем, которые у меня когда-либо были с arduino и C++. Спасибо, я протестирую это, когда приду домой., @Francisco Presencia

@Omer спасибо за разъяснение, которое я забыл включить. Я только что отредактировал свой ответ., @jfpoilpret