I am trying to control a 2DOF SCARA arm that will interpret g codes. I split the code into 3 classes : ArmController, Kinematics and CmdProcessor. In my main file I make an instance of ArmController then an instance of CmdProcessor. CmdProcessor needs to be able to access ArmController to call armctl.moveTo(). I am used to c# so this may not be how it's done in c++. I have no idea on how to even start fixing this or which parts of the code may be important, so I just posted the entire code.
Main file:
//#include <AccelStepper.h>
#include "ArmController.h"
#include "CommandProcessor.h"
ArmCtl armctl(220, 205);
CmdProcessor cmd(armctl);
void setup() {
armctl.Calibrate();
}
void loop() {
armctl.Tick();
cmd.ProcessSerial();
}
ArmController.h:
#define ArmController_h
#include <Arduino.h>
#include "Kinematics.h"
class ArmCtl{
public:
ArmCtl(float len1, float len2);
void moveTo(float x, float y, float z);
void Calibrate();
void Reset();
void Joystick();
void Tick();
void CheckSteppers();
Kinematics kinematics;
AccelStepper s1;
AccelStepper s2;
AccelStepper s3;
float l1;
float l2;
float x; //
float y; // X Y and Z coordinates of end effector
float z; //
float x1(); //
float y1(); //X and Y coordinates of elbow
float a; //
float b; //Raw stepper angles
float c; //
};
ArmCtl::ArmCtl(float len1, float len2) : kinematics(len1, len2){
s1 = AccelStepper(8, 2, 4, 3, 5);
s2 = AccelStepper(8, 6, 8, 7, 9);
s3 = AccelStepper(8, 10, 12, 11, 13);
s1.setMaxSpeed(500);
s1.setAcceleration(4000);
s2.setMaxSpeed(1500);
s2.setAcceleration(4000);
s2.setCurrentPosition(46194);
s3.setMaxSpeed(2000);
s3.setAcceleration(4000);
l1 = len1;
l2 = len2;
}
void ArmCtl::Tick(){
if(analogRead(2) < 2){
Calibrate();
}
Joystick();
s1.run();
s2.run();
s3.run();
}
void ArmCtl::CheckSteppers(){
if(abs(s1.distanceToGo()) == 0)
s1.disableOutputs();
if(abs(s2.distanceToGo()) == 0)
s2.disableOutputs();
if(abs(s3.distanceToGo()) == 0)
s3.disableOutputs();
}
void ArmCtl::moveTo(float x_, float y_, float z_){
x = x_;
y = y_;
z = z_;
a = kinematics.calcAngle1(x,y);
b = kinematics.calcAngle2(x,y);
s1.moveTo((92389 / 360) *a);
s2.moveTo((92389 / 360) *b);
Serial.println(String(x) + " " + String(y) + " " + String(z));
}
void ArmCtl::Calibrate(){
Reset();
while(analogRead(2) > 2){
CheckSteppers();
int xr = analogRead(0);
if(xr > 768){
s1.setSpeed((xr - 768)*4);
s1.runSpeed();
}
else if( xr < 256){
s1.setSpeed((xr - 256)*4);
s1.runSpeed();
}
int yr = analogRead(1);
if(yr > 768){
s2.setSpeed((yr - 768)*4);
s2.runSpeed();
}
else if( yr < 256){
s2.setSpeed((yr - 256)*4);
s2.runSpeed();
}
if(analogRead(3)<256){
s3.setSpeed(1024);
s3.runSpeed();
}
else if(analogRead(4)<256){
s3.setSpeed(-1024);
s3.runSpeed();
}
}
delay(1000);
s1.setCurrentPosition(0);
s2.setCurrentPosition(46194);
s1.setSpeed(500);
s2.setSpeed(500);
}
void ArmCtl::Reset(){
s1.moveTo(0);
s2.moveTo(46194);
s3.moveTo(0);
while(!(s1.distanceToGo() == 0 && s2.distanceToGo() == 0 && s3.distanceToGo() == 0)){
s1.run();
s2.run();
s3.run();
}
CheckSteppers();
}
void ArmCtl::Joystick(){
if(abs(s1.distanceToGo()) < 5000 && abs(s2.distanceToGo()) < 5000 && abs(s3.distanceToGo()) < 5000){
if(analogRead(0)>768){
x+=(analogRead(0) - 768)/32;
moveTo(x,y,z);
}
else if(analogRead(0)<256){
x-=(256 - analogRead(0))/32;
moveTo(x,y,z);
}
if(analogRead(1)>768){
y+=(analogRead(1) - 768)/32;
moveTo(x,y,z);
}
else if(analogRead(1)<256){
y+=(256 - analogRead(0))/32;
moveTo(x,y,z);
}
if(analogRead(3)<256){
z+=5;
moveTo(x,y,z);
}
else if(analogRead(4)<256){
z-=5;
moveTo(x,y,z);
}
}
}
CmdProcessor.h:
#define CommandProcessor_h
#include "ArmController.h"
#include <Arduino.h>
class CmdProcessor{
public:
CmdProcessor(ArmCtl armc);
void ProcessSerial();
ArmCtl ctl;
private:
String cmd;
void G0(); //go to pos
void G1(); //home
void G2(float a1,float a2, float a3); //Set raw stepper angles
};
CmdProcessor::CmdProcessor(ArmCtl& armc){
Serial.begin(9600);
ctl = armc;
}
void CmdProcessor::ProcessSerial(){
if(Serial.available()){
cmd += (char)Serial.read();
if(cmd == "G0"){
cmd = "";
Serial.println("ok G0");
G0();
}
else if(cmd == "G1"){
cmd = "";
Serial.println("ok G1");
G1();
}
if(cmd.length() == 2){
Serial.println("command unrecognized: " + cmd);
cmd = "";
}
}
}
void CmdProcessor::G0(){
float x = Serial.parseFloat();
float y = Serial.parseFloat();
ctl.moveTo(x,y,0);
}
void CmdProcessor::G1(){
ctl.Reset();
}
Kinematics.h:
#define Kinematics_h
#include <Arduino.h>
class Kinematics{
public:
Kinematics(float l1, float l2){
length1 = l1;
length2 = l2;
}
float calcAngle1(float x,float y){
float distance = sqrt(x*x + y*y);
float D1 = RadToDeg(atan2(y, x));
float D2 = RadToDeg(LawOfCosines(distance, length1, length2));
if(x<0){
return -(180 - abs(90 - (D1 + D2)));
}
return 90 - (D1 + D2);
}
float calcAngle2(float x,float y) {
float distance = sqrt(x*x + y*y);
if(x<0){
return 180 + RadToDeg(LawOfCosines(length1, length2, distance));
}
return 180 - RadToDeg(LawOfCosines(length1, length2, distance)); //Subtract from 180 because this stepper is upside down so the angles have to be reversed
}
private:
float length1;
float length2;
float RadToDeg(double rad) {
return float (rad * 180 / 3.1416);
}
float LawOfCosines(float a, float b, float c){
return acos((a*a + b*b - c*c) / (2 * a * b));
}
};
When I try to compile all this I get this:
In file included from sketch\CommandProcessor.h:2:0,
from C:\Users\Alp D\Desktop\Coding\Armatron_S\Armatron_S\Armatron_S.ino:3:
sketch\ArmController.h: In constructor 'ArmCtl::ArmCtl()':
ArmController.h:44: error: no matching function for call to 'Kinematics::Kinematics()'
ArmCtl::ArmCtl(){
^
sketch\ArmController.h:44:16: note: candidates are:
In file included from sketch\ArmController.h:3:0,
from sketch\CommandProcessor.h:2,
from C:\Users\Alp D\Desktop\Coding\Armatron_S\Armatron_S\Armatron_S.ino:3:
sketch\Kinematics.h:5:5: note: Kinematics::Kinematics(float, float)
Kinematics(float l1, float l2){
^
sketch\Kinematics.h:5:5: note: candidate expects 2 arguments, 0 provided
sketch\Kinematics.h:3:7: note: constexpr Kinematics::Kinematics(const Kinematics&)
class Kinematics{
^
sketch\Kinematics.h:3:7: note: candidate expects 1 argument, 0 provided
sketch\Kinematics.h:3:7: note: constexpr Kinematics::Kinematics(Kinematics&&)
sketch\Kinematics.h:3:7: note: candidate expects 1 argument, 0 provided
C:\Users\Alp D\Desktop\Coding\Armatron_S\Armatron_S\Armatron_S.ino: In function 'void loop()':
Armatron_S:11: error: 'cmd' was not declared in this scope
cmd.ProcessSerial();
^
exit status 1
no matching function for call to 'Kinematics::Kinematics()'
Also English isn't my primary language so I may make some mistakes.