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 > 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 < 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 > 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 < 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
6122 gold badges5 silver badges18 bronze badges
asked Mar 15, 2023 at 19:38
4
  • What happens when you pass the Encoder object as pointer via &ElbowEncoder? Commented Mar 15, 2023 at 20:30
  • I get "Compilation error: no match for 'operator=' (operand types are 'Encoder' and 'Encoder*')" Commented Mar 15, 2023 at 22:17
  • please copy all of the error message and paste it into your question ... do not put it into a comment like you just did ... also, no pictures of text ... format the text as code Commented Mar 15, 2023 at 22:49
  • 1
    you can use reference. member and parameter as Encoder& type and in constructor initialization list you set the value of the member from the value of the parameter. MyClass::MyClass(Encoder& _encoder) : encoder(_encoder) {} Commented Mar 16, 2023 at 4:58

1 Answer 1

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
6122 gold badges5 silver badges18 bronze badges
answered Mar 23, 2023 at 9:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.