2

I am trying to create a class (Arm) that controls an arm. The arms have 2 motors, each with an encoder, so I pass 4 integers for the pins and I am trying to pass 2 pointers (one for each encoder object).

the .ino file is:

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

//motor driver pins #define ShoulderUP 7 #define ShoulderDW 8

#define ElbowUP 9 #define ElbowDW 10

#define encoderShoulderPinA 20 #define encoderShoulderPinB 21

#define encoderElbowPinA 22 #define encoderElbowPinB 23

//make encoder objects Encoder ElbowEncoder(encoderElbowPinA, encoderElbowPinB); Encoder ShoulderEncoder(encoderShoulderPinA, encoderShoulderPinB);

//make arm object Arm Arm1(ShoulderUP, ShoulderDW, ElbowUP, ElbowDW, ElbowEncoder, ShoulderEncoder);

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

void loop() {

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

the .h file is:

#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);

//pins connected to your encoder: // Best Performance: both pins have interrupt capability // Good Performance: only the first pin has interrupt capability // Low Performance: neither pin has interrupt capability

void ShoulderMoveTime(int dir, int speed, int time); //dir = 0 means up, dir = 1 means down; speed between 0-255 void ElbowMoveTime(int dir, int speed, int time); //dir = 0 means up, dir = 1 means down; speed between 0-255

//Moves arm to poition given void ArmMovePosition(int shoulderPos, int elbowPos);

// calibrates current arm position to zero void ZeroArm();

//returns position of the arm void getArmPosition();

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

#endif

and the .cpp file is:

#include "Arduino.h"
#include "Encoder.h"
#include "Arm.h"

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; //_ShoulderEncoderPinA = ShoulderEncoderPinA; //_ShoulderEncoderPinB = ShoulderEncoderPinB; //_ElbowEncoderPinA = ElbowEncoderPinA; // _ElbowEncoderPinB = ElbowEncoderPinB; ElbowEncoder = ElbowEncoder; ShoulderEncoder = ShoulderEncoder; //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 shoulderPos, int elbowPos) { int ShoulderinitialPos = ShoulderEncoder.read(); int ElbowinitialPos = ElbowEncoder.read();

//TODO:I think this will only move one joint at a time

//Move shoulder------------------------------------------------------------------------------------- if (shoulderPos > ShoulderinitialPos) { //check to see which direction arm needs to move

while (shoulderPos &gt; ShoulderEncoder.read()) {  //while the target position is greater than the motor's actual position, move the shoulder up
  digitalWrite(_ShoulderUpPin, HIGH);           //THIS MAY BE REVERSED
}
digitalWrite(_ShoulderUpPin, LOW);  //stop the arm from moving up

} else if (shoulderPos < ShoulderinitialPos) {

while (shoulderPos &lt; ShoulderEncoder.read()) {
  digitalWrite(_ShoulderDownPin, HIGH);
}
digitalWrite(_ShoulderDownPin, LOW);

} else { Serial.print("Error: invalid shoulder target position"); }

//Move elbow------------------------------------------------------------------------------------- if (elbowPos > ElbowinitialPos) { //check to see which direction arm needs to move

while (elbowPos &gt; ElbowEncoder.read()) {  //while the target position is greater than the motor's actual position, move the elbow up
  digitalWrite(_ElbowUpPin, HIGH);        //THIS MAY BE REVERSED
}
digitalWrite(_ElbowUpPin, LOW);  //stop the arm from moving up

} else if (elbowPos < ElbowinitialPos) {

while (elbowPos &lt; ElbowEncoder.read()) {
  digitalWrite(_ElbowDownPin, HIGH);
}
digitalWrite(_ElbowDownPin, LOW);

} else { Serial.print("Error: invalid elbow target position"); } }

void Arm::ZeroArm() { ShoulderEncoder.write(0); ElbowEncoder.write(0); Serial.println("Arm has been tared"); }

void Arm::getArmPosition() { Serial.print("Shoulder Position: "); Serial.print(ShoulderEncoder.read()); Serial.print("Elbow Position: "); Serial.println(ElbowEncoder.read()); }

Unfortunately, there appears to be some sort of problem with passing the Encoder object. I am getting the error:

Compilation error: no matching function for call to 'Arm::Arm(int, int, int, int, Encoder&, Encoder&)'

I am definitely a noob when it comes to coding, so thanks in advance for what is probably a simple problem.

Rohit Gupta
  • 618
  • 2
  • 5
  • 18

1 Answers1

1

You're jumping backwards and forwards between pointers and the objects themselves. Change it to pass pointers to the arm constructor and consistently use pointers (or pass a reference and always use that, just be consistent). This would be something like:

    // main code, pass a pointer rather than the object itself
    Arm Arm1(ShoulderUP, ShoulderDW, ElbowUP, ElbowDW, &ElbowEncoder, &ShoulderEncoder);
// header
public:
  Arm(int ShoulderUpPin, int ShoulderDownPin, int ElbowUpPin, int ElbowDownPin, Encoder *ElbowEncoder, Encoder *ShoulderEncoder);


// cpp
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; // use 'this.' to indicate the class private variable since it's the same name as the passed parameter.
  this.ShoulderEncoder = ShoulderEncoder;
}

And then within your class, since ElbowEncoder is a pointer rather than the encoder itself, use ElbowEncoder->method() rather than ElbowEncoder.method()

Personally, I'd restructure it a little. Why create the encoders at the top level when they are only used within the arm class? Create them in the arm class instead:

    //in .h
    public:
      Arm(int ShoulderUpPin, int ShoulderDownPin, int ShoulderEncoderPinA,int ShoulderEncoderPinB,
          int ElbowUpPin, int ElbowDownPin, int ElbowEncoderPinA, int ElbowEncoderPinB);
private:
  Encoder ShoulderEncoder;
  Encoder ElbowEncoder;


// in .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) {
   // constructor code
}

This will create the encoders as private to the arm as soon as you call the arm constructor. Especially handy if you want to have more than one arm.

Rohit Gupta
  • 618
  • 2
  • 5
  • 18
Andrew
  • 1,060
  • 5
  • 8