Передача ссылки как переменной

У меня есть функция для ручного толчка шагового двигателя с использованием библиотеки AccelStepper. В начале функции я хотел бы, чтобы выбранный двигатель был выбран до тех пор, пока не будет получен сигнал остановиться.

Вот как я себе это представляю:

AccelStepper X_Axis(AccelStepper::DRIVER, 3, 2);
AccelStepper Y_Axis(AccelStepper::DRIVER, 5, 4);
AccelStepper Z_Axis(AccelStepper::DRIVER, 7, 6);

void ManualJog(int Dir, int Spd, int axis)
{
  int i;
  if (Dir == 0){i = 1;}else{i =- 1;}
  setSpeed(i * Spd);
  switch(axis)
    {
      case 1:
      axis = X_Axis;
      break;

      case 2:
      axis = Y_Axis;

      case 3:
      axis = Z_Axis
    }
  while (!Serial.available()){

      axis.runSpeed();
    }
  }

Переменная оси должна соответствовать вызываемой оси и таким образом управлять нужным шаговым двигателем.

Как мне этого добиться?

Примечание: Я отправил это на StackOverflow, но ответа не получил. Любая помощь будет оценена по достоинству

, 👍0

Обсуждение

[Не допускайте перекрестного постинга.](https://meta.stackexchange.com/q/64068) Вы уже [задавали этот вопрос на SO](https://stackoverflow.com/q/51993345)., @gre_gor


2 ответа


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

0

Как насчет использования массива?

const int x = 0;
const int y = 1;
const int z = 2; 

AccelStepper axis[] = { {AccelStepper::DRIVER, 3, 2}, ... };

void ManualJog(int Dir, int Spd, int axisIdx)
{
   axis[axisIdx].runSpeed();
}
,

1

Чтобы сделать это в той форме, в которой вы находитесь, вам понадобится указатель.

void ManualJog(int Dir, int Spd, int axis)
{
  int i;
  AccellStepper *thisAxis = NULL;

  if (Dir == 0) {
    i = 1;
  } else {
    i =- 1;
  }
  setSpeed(i * Spd);
  switch(axis)
  {
    case 1:
      thisAxis = &X_Axis;
      break;

    case 2:
      thisAxis = &Y_Axis;
      break;

    case 3:
      thisAxis = &Z_Axis
      break
  }

  if (thisAxis != NULL) {
    while (!Serial.available()) {
      thisAxis->runSpeed();
    }
  }
}

Вкратце: & перед именем переменной в присваивании означает «Дайте мне адрес этой переменной». * перед переменной при объявлении этой переменной означает «Заставьте эту переменную хранить адрес другой переменной этого типа». Затем вы заставляете переменную адреса хранить адрес выбранного вами акселя, а затем «разыменовываете» его с помощью «оператора разыменования указателя» -> (вместо использования .).

Добавлена проверка, чтобы увидеть, было ли thisAxis действительно назначено что-либо или нет, хотя вместо этого вы можете использовать случай default: в вашем переключателе, чтобы прервать операцию при неверном номере оси.

Однако в зависимости от того, как работает остальная часть вашей программы, может оказаться возможным вообще не использовать целое число «axis», а передать в функцию ссылку на правильный степпер:

void ManualJog(int Dir, int Spd, AccelStepper &axis) {
  int i;
  if (Dir == 0) {
    i = 1;
  } else {
    i =- 1;
  }
  setSpeed(i * Spd);
  while (!Serial.available()) {
    axis.runSpeed();
  }
}

В этом примере & перед переменной axis в прототипе функции означает "Передай мне адрес переменной", и новая переменная создается в том же пространстве памяти. Это оператор передачи по ссылке в C++.

,

Мне очень не нравится использовать "магические числа" для выбора оси. Было бы гораздо лучше (и быстрее) не передавать int axis в метод ManualJog, а передавать ссылку на AccellStepper, чтобы код был более читабельным., @Filip Franik

@FilipFranik Я полностью согласен, однако, судя по формулировке вопроса и по тому, как выглядит функция, которая должна работать, в какой-то момент придется «выбрать» правильную ось, а это, вероятно, будет означать установку указателя в какой-то точке последовательности., @Majenko

Великолепно, спасибо за это. Указатели — это то, с чем я раньше не сталкивался. Вы правы в том, что я хочу выбрать ссылку двигателя в зависимости от входа. Я попробую это и отвечу своим рабочим кодом., @MJ2507