Как передать объект Encoder конструктору другого класса

Я пытаюсь создать класс (Arm), который управляет рукой. У рук есть 2 двигателя, каждый с энкодером, поэтому я передаю 4 целых числа для контактов и пытаюсь передать 2 указателя (по одному для каждого объекта энкодера).

файл .ino:

#include "Arm.h"
#include <Encoder.h>

// контакты драйвера двигателя
#define ShoulderUP 7
#define ShoulderDW 8

#define ElbowUP 9
#define ElbowDW 10

#define encoderShoulderPinA 20
#define encoderShoulderPinB 21

#define encoderElbowPinA 22
#define encoderElbowPinB 23

//создаем объекты энкодера
Encoder ElbowEncoder(encoderElbowPinA, encoderElbowPinB);
Encoder ShoulderEncoder(encoderShoulderPinA, encoderShoulderPinB);

//создаем объект рука
Arm Arm1(ShoulderUP, ShoulderDW, ElbowUP, ElbowDW, ElbowEncoder, ShoulderEncoder);

void setup() {
  Serial.begin(9600);
}

void loop() {

  Arm1.ShoulderMoveTime(1, 255, 1000);
}

файл .h:

#ifndef Arm_h
#define Arm_h

#include <Arduino.h>
#include <Encoder.h>

class Arm {

public:
  Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder);

  //контакты, подключенные к вашему энкодеру:
  // Лучшая производительность: оба вывода имеют возможность прерывания
  // Хорошая производительность: только первый вывод имеет возможность прерывания
  // Низкая производительность: ни один из выводов не имеет возможности прерывания

  void ShoulderMoveTime(int dir, int speed, int time);
  //dir = 0 означает вверх, dir = 1 означает вниз; скорость между 0-255
  void ElbowMoveTime(int dir, int speed, int time);
  //dir = 0 означает вверх, dir = 1 означает вниз; скорость между 0-255

  //Перемещает руку в заданное положение
  void ArmMovePosition(int shoulderPos, int elbowPos);

  // калибрует текущее положение руки до нуля
  void ZeroArm();

  //возвращает положение руки
  void getArmPosition();

private:
  Encoder *ElbowEncoder;
  Encoder *ShoulderEncoder;
  int _ShoulderUpPin;
  int _ShoulderDownPin;
  int _ElbowUpPin;
  int _ElbowDownPin;
};

#endif

и файл .cpp:

#include "Arduino.h"
#include "Кодировщик.h"
#include "Arm.h"

Arm::Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder) {

pinMode(ShoulderUpPin, ВЫХОД);
pinMode(ShoulderDownPin, ВЫХОД);
pinMode(ElbowUpPin, ВЫХОД);
pinMode(ElbowDownPin, ВЫХОД);

_ShoulderUpPin = ПлечоВверх;
_ShoulderDownPin = ПлечоВнизPin;
_ElbowUpPin = ЛокотьВверх;
_отвод вниз штифт = отвод вниз штифт;
//_ShoulderEncoderPinA = ShoulderEncoderPinA;
//_ShoulderEncoderPinB = ShoulderEncoderPinB;
//_Отводной кодировщикPinA = Отводной кодировщикPinA;
// _КоленоккодировщикPinB = КоленоЭнкодерPinB;
кодировщик локтя = *энкодер локтя;
Кодировщик Плеча = *Кодировщик Плеча;
//ElbowEncoder(_ElbowEncoderPinA, _ElbowEncoderPinB);
//ShoulderEncoder(_ShoulderEncoderPinA, _ShoulderEncoderPinB);
}

void Arm::ShoulderMoveTime(int dir, int speed, int time) {
...
}

void Arm::ElbowMoveTime(int dir, int speed, int time) {
...
}

void Arm:: ArmMovePosition (int плечоPos, int локотьPos) {
int ShoulderinitialPos = ShoulderEncoder.read();
int ElbowinitialPos = ElbowEncoder.read();

// TODO: я думаю, что это будет перемещать только один сустав за раз

//Двигаем плечо----------------------------------------------------------- ---------------------------------------
if (shoulderPos > ShoulderinitialPos) { //проверить, в каком направлении должна двигаться рука

while (shoulderPos > ShoulderEncoder.read()) { //пока целевое положение больше фактического положения мотора, перемещаем плечо вверх
digitalWrite(_ShoulderUpPin, ВЫСОКИЙ); // ЭТО МОЖЕТ БЫТЬ ОБРАТНО
}
digitalWrite(_ShoulderUpPin, НИЗКИЙ); //остановить движение руки вверх

} иначе если (плечоПос < ПлечоначальноеПос) {

в то время как (shoulderPos < ShoulderEncoder.read()) {
digitalWrite(_ShoulderDownPin, ВЫСОКИЙ);
}
digitalWrite(_ShoulderDownPin, НИЗКИЙ);

} еще {
Serial.print("Ошибка: неверная целевая позиция плеча");
}

//Двигаем локтем------------------------------------------------------------- ---------------------------------------
if (elbowPos > ElbowinitialPos) { // проверяем, в каком направлении должна двигаться рука

while (elbowPos > ElbowEncoder.read()) { //пока целевое положение больше фактического положения мотора, двигаем колено вверх
digitalWrite(_ElbowUpPin, ВЫСОКИЙ); // ЭТО МОЖЕТ БЫТЬ ОБРАТНО
}
digitalWrite(_ElbowUpPin, НИЗКИЙ); //остановить движение руки вверх

} иначе если (elbowPos < ElbowinitialPos) {

в то время как (elbowPos < ElbowEncoder.read()) {
digitalWrite(_ElbowDownPin, ВЫСОКИЙ);
}
digitalWrite(_ElbowDownPin, НИЗКИЙ);

} еще {
Serial.print("Ошибка: неверная целевая позиция локтя");
}
}

пустота Arm:: ZeroArm () {
ПлечоЭнкодер.write(0);
ElbowEncoder.write(0);
Serial.println("Рука тарирована");
}

пустота Arm::getArmPosition() {
Serial.print("Положение плеча: ");
Serial.print(ShoulderEncoder.read());
Serial.print("Положение локтя:");
Serial.println(ElbowEncoder.read());
}

К сожалению, возникла проблема с передачей объекта Encoder. Я получаю сообщение об ошибке: "Ошибка компиляции: нет соответствующей функции для вызова 'Arm::Arm(int, int, int, int, Encoder&, Encoder&)'"

Я определенно новичок в программировании, поэтому заранее спасибо за, вероятно, простую проблему.

, 👍2

Обсуждение

Что происходит, когда вы передаете объект Encoder в качестве указателя через & ElbowEncoder?, @chrisl

Я получаю сообщение "Ошибка компиляции: нет соответствия оператору =" (типы операндов "Кодировщик" и "Кодировщик*")", @EricWeissman

пожалуйста, скопируйте все сообщение об ошибке и вставьте его в свой вопрос ... ** не ** помещайте его в комментарий, как вы только что сделали ... также ** нет изображений текста ** ... отформатируйте текст как код, @jsotola

вы можете использовать ссылку. член и параметр как тип Encoder, а в _списке инициализации конструктора_ вы устанавливаете значение члена из значения параметра. MyClass::MyClass(Encoder& _encoder) : encoder(_encoder) {}, @Juraj


1 ответ


1

Вы прыгаете вперед и назад между указателями и самими объектами. Измените его, чтобы передавать указатели на конструктор руки и последовательно использовать указатели (или передавать ссылку и всегда использовать ее, просто будьте последовательны). Это будет что-то вроде:

// основной код, передать указатель, а не сам объект
Arm Arm1(ShoulderUP, ShoulderDW, ElbowUP, ElbowDW, &ElbowEncoder, &ShoulderEncoder);

// заголовок
public:
  Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder);


// цена за тысячу показов
Arm::Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder) {

  pinMode(ShoulderUpPin, OUTPUT);
  pinMode(ShoulderDownPin, OUTPUT);
  pinMode(ElbowUpPin, OUTPUT);
  pinMode(ElbowDownPin, OUTPUT);

  _ShoulderUpPin = ShoulderUpPin;
  _ShoulderDownPin = ShoulderDownPin;
  _ElbowUpPin = ElbowUpPin;
  _ElbowDownPin = ElbowDownPin;
  this.ElbowEncoder = ElbowEncoder; // использовать это.' чтобы указать частную переменную класса, так как это то же имя, что и переданный параметр.
  this.ShoulderEncoder = ShoulderEncoder;
}

И затем внутри вашего класса, поскольку ElbowEncoder является указателем, а не самим кодировщиком, используйте ElbowEncoder->method(), а не ElbowEncoder.method()

Лично я бы немного изменил структуру. Зачем создавать энкодеры на верхнем уровне, если они используются только в классе arm? Создайте их в классе рук внутри:

//в .h
public:
  Arm(int ShoulderUpPin, int ShoulderDownPin, int ShoulderEncoderPinA,int ShoulderEncoderPinB,
      int ElbowUpPin, int ElbowDownPin, int ElbowEncoderPinA, int ElbowEncoderPinB);

private:
  Encoder ShoulderEncoder;
  Encoder ElbowEncoder;


// в .cpp
Arm::Arm(int ShoulderUpPin, int ShoulderDownPin, int ShoulderEncoderPinA,int ShoulderEncoderPinB,
         int ElbowUpPin, int ElbowDownPin, int ElbowEncoderPinA, int ElbowEncoderPinB) :
             ShoulderEncoder(ShoulderEncoderPinA,ShoulderEncoderPinB),
             ElbowEncoder(ElbowEncoderPinA,ElbowEncoderPinB) {
   // код конструктора
}

Это создаст кодировщики как частные для руки, как только вы вызовете конструктор руки. Особенно удобно, если вы хотите иметь более одной руки.

,