new project robotic arm

I am starting a new project and need a little help, programming has never been my strong point, i am making a 4 axis are with a claw on the end, I intend to use 28byj-48 stepper motors and either uln2003 drivers or modify the motors and use a4988 drivers, either is an option at this point, I am planning on using 2 joysticks to control the 4 steppers so joystick 1 x-axis will move motor one y-axis motor 2, joystick 2 x-axes will move the motor and y-axis will move motor 4, with 2 buttons to open and close a sg90 servo controlling claw. i have an uno or mega to use, I've seen samples codes the can control 2 steppers but nothing for 4 and a servo, once I get it up and running id like to add limit switches, or add homing switches and program the hard limit in the other direction from home as to not destroy its self any help with this would be much appreciated, I am designing the robotic arm from scratch and can provide 3d printing files once i have something together

This is a guide i found to running 2 steppers with the uln2003 and a single joystick. So I want to double it and add a servo control with 2 buttons

https://create.arduino.cc/projecthub/mitov/arduino-nano-control-2-stepper-motors-with-joystick-52b391

this is the sample code from the above link

``
#define VISUINO_ARDUINO_NANO

#include <OpenWire.h>
#include <Mitov.h>
#include <Mitov_Stepper.h>
#include <Mitov_Math.h>

// Shared Component Member Variables

namespace ComponentVariables
{
class
{
public:
 uint32_t Value1 : 4;
 uint32_t Value2 : 4;

} BitFields;

class Variable1
{
public:
 inline static uint32_t GetValue() { return BitFields.Value1; }
 inline static void SetValue( uint32_t AValue ) { BitFields.Value1 = AValue; }

};
class Variable2
{
public:
 inline static uint32_t GetValue() { return BitFields.Value2; }
 inline static void SetValue( uint32_t AValue ) { BitFields.Value2 = AValue; }

};
} // ComponentVariables

// Arduino Constant Declarations

namespace VisuinoConstants
{
class FloatValue0
{
public:
   inline static constexpr float GetValue() { return 0; }
};

class FloatValue6
{
public:
   inline static constexpr float GetValue() { return -300; }
};

class FloatValue3
{
public:
   inline static constexpr float GetValue() { return 0.5; }
};

class FloatValue5
{
public:
   inline static constexpr float GetValue() { return 1; }
};

class FloatValue1
{
public:
   inline static constexpr float GetValue() { return -100000; }
};

class FloatValue4
{
public:
   inline static constexpr float GetValue() { return 0.100000001490116; }
};

class FloatValue7
{
public:
   inline static constexpr float GetValue() { return 300; }
};

class FloatValue2
{
public:
   inline static constexpr float GetValue() { return 100000; }
};

} // VisuinoConstants

// Pin Call Declarations

namespace PinCalls
{
class PinCallerReceive0
{
public:
 void Notify( void *_Data );

};
class PinCallerReceive1
{
public:
 void Notify( void *_Data );

};
class PinCallerReceive2
{
public:
 void Notify( void *_Data );

};
class PinCallerReceive3
{
public:
 void Notify( void *_Data );

};
} // PinCalls

// Arduino Board Declarations

namespace BoardDeclarations
{
namespace Types
{
typedef Mitov::ArduinoAnalogInputChannel<0, Mitov::AnalogPin_EmbeddedPinImplementation<1, ::PinCalls::PinCallerReceive0 >> ArduinoAnalogInputChannel_0;
} // Types

namespace Instances
{
Types::ArduinoAnalogInputChannel_0 ArduinoAnalogInputChannel_0;
} // Instances

namespace Types
{
typedef Mitov::ArduinoAnalogInputChannel<1, Mitov::AnalogPin_EmbeddedPinImplementation<1, ::PinCalls::PinCallerReceive1 >> ArduinoAnalogInputChannel_1;
} // Types

namespace Instances
{
Types::ArduinoAnalogInputChannel_1 ArduinoAnalogInputChannel_1;
} // Instances

} // BoardDeclarations

// Declarations

namespace Declarations
{
namespace Types
{
typedef Mitov::StepperMotor4Wire<
 Mitov::ConstantProperty<8, bool, true >, // Enabled
 Mitov::TypedVariable<0, uint32_t, ::ComponentVariables::Variable1 >, // FStep
 Mitov::ConstantProperty<1, bool, true >, // HalfStep
 Mitov::DigitalPin_DirectBoardPinImplementation<2 >, // OutputPins_0
 Mitov::DigitalPin_DirectBoardPinImplementation<3 >, // OutputPins_1
 Mitov::DigitalPin_DirectBoardPinImplementation<4 >, // OutputPins_2
 Mitov::DigitalPin_DirectBoardPinImplementation<5 >, // OutputPins_3
 Mitov::ConstantProperty<9, bool, false >, // Reversed
 Mitov::StepperMotorSpeed, // Speed_Implementation
 Mitov::VariableMinMaxPropertyFloat<10, float, ::VisuinoConstants::FloatValue0, ::VisuinoConstants::FloatValue1, ::VisuinoConstants::FloatValue2 > // StepsPerSecond
  > Stepper1;
} // Types

namespace Instances
{
Types::Stepper1 Stepper1;
} // Instances

namespace Types
{
typedef Mitov::StepperMotor4Wire<
 Mitov::ConstantProperty<8, bool, true >, // Enabled
 Mitov::TypedVariable<0, uint32_t, ::ComponentVariables::Variable2 >, // FStep
 Mitov::ConstantProperty<1, bool, true >, // HalfStep
 Mitov::DigitalPin_DirectBoardPinImplementation<6 >, // OutputPins_0
 Mitov::DigitalPin_DirectBoardPinImplementation<7 >, // OutputPins_1
 Mitov::DigitalPin_DirectBoardPinImplementation<8 >, // OutputPins_2
 Mitov::DigitalPin_DirectBoardPinImplementation<9 >, // OutputPins_3
 Mitov::ConstantProperty<9, bool, false >, // Reversed
 Mitov::StepperMotorSpeed, // Speed_Implementation
 Mitov::VariableMinMaxPropertyFloat<10, float, ::VisuinoConstants::FloatValue0, ::VisuinoConstants::FloatValue1, ::VisuinoConstants::FloatValue2 > // StepsPerSecond
  > Stepper2;
} // Types

namespace Instances
{
Types::Stepper2 Stepper2;
} // Instances

namespace Types
{
typedef Mitov::AnalogDeadZoneScaled<
 Mitov::ConstantProperty<3, bool, true >, // Enabled
 Mitov::NestedProperty<6, Mitov::ValueRange<
   Mitov::ConstantPropertyFloat<6, float, ::VisuinoConstants::FloatValue5 >, // Value_Max
   Mitov::ConstantPropertyFloat<5, float, ::VisuinoConstants::FloatValue0 > // Value_Min
    > >, // InputRange
 Mitov::AnalogPin_EmbeddedPinImplementation<11, ::PinCalls::PinCallerReceive2 >, // OutputPin
 Mitov::NestedProperty<9, Mitov::ValueRange<
   Mitov::ConstantPropertyFloat<9, float, ::VisuinoConstants::FloatValue7 >, // Value_Max
   Mitov::ConstantPropertyFloat<8, float, ::VisuinoConstants::FloatValue6 > // Value_Min
    > >, // OutputRange
 Mitov::ConstantPropertyFloat<2, float, ::VisuinoConstants::FloatValue4 >, // Span
 Mitov::ConstantPropertyFloat<1, float, ::VisuinoConstants::FloatValue3 > // Value
  > DeadZoneScaled1;
} // Types

namespace Instances
{
Types::DeadZoneScaled1 DeadZoneScaled1;
} // Instances

namespace Types
{
typedef Mitov::AnalogDeadZoneScaled<
 Mitov::ConstantProperty<3, bool, true >, // Enabled
 Mitov::NestedProperty<6, Mitov::ValueRange<
   Mitov::ConstantPropertyFloat<6, float, ::VisuinoConstants::FloatValue5 >, // Value_Max
   Mitov::ConstantPropertyFloat<5, float, ::VisuinoConstants::FloatValue0 > // Value_Min
    > >, // InputRange
 Mitov::AnalogPin_EmbeddedPinImplementation<11, ::PinCalls::PinCallerReceive3 >, // OutputPin
 Mitov::NestedProperty<9, Mitov::ValueRange<
   Mitov::ConstantPropertyFloat<9, float, ::VisuinoConstants::FloatValue7 >, // Value_Max
   Mitov::ConstantPropertyFloat<8, float, ::VisuinoConstants::FloatValue6 > // Value_Min
    > >, // OutputRange
 Mitov::ConstantPropertyFloat<2, float, ::VisuinoConstants::FloatValue4 >, // Span
 Mitov::ConstantPropertyFloat<1, float, ::VisuinoConstants::FloatValue3 > // Value
  > DeadZoneScaled2;
} // Types

namespace Instances
{
Types::DeadZoneScaled2 DeadZoneScaled2;
} // Instances

} // Declarations

// Pin Call Implementations

namespace PinCalls
{
void PinCallerReceive0::Notify( void *_Data )
{
 Declarations::Instances::DeadZoneScaled1.InputPin_o_Receive( _Data );
}

void PinCallerReceive1::Notify( void *_Data )
{
 Declarations::Instances::DeadZoneScaled2.InputPin_o_Receive( _Data );
}

void PinCallerReceive2::Notify( void *_Data )
{
 Declarations::Instances::Stepper1.StepsPerSecond().InputPin_o_Receive( _Data );
}

void PinCallerReceive3::Notify( void *_Data )
{
 Declarations::Instances::Stepper2.StepsPerSecond().InputPin_o_Receive( _Data );
}

} // PinCalls

namespace ComponentsHardware
{
void SystemUpdateHardware()
{
}
} // ComponentsHardware

//The setup function is called once at startup of the sketch
void setup()
{
 BoardDeclarations::Instances::ArduinoAnalogInputChannel_0.SystemInit();
 BoardDeclarations::Instances::ArduinoAnalogInputChannel_1.SystemInit();
 BoardDeclarations::Instances::ArduinoAnalogInputChannel_0.SystemStart();
 BoardDeclarations::Instances::ArduinoAnalogInputChannel_1.SystemStart();
 Declarations::Instances::DeadZoneScaled1.SystemStart();
 Declarations::Instances::DeadZoneScaled2.SystemStart();
}

// The loop function is called in an endless loop
void loop()
{
 BoardDeclarations::Instances::ArduinoAnalogInputChannel_0.SystemLoopBegin();
 BoardDeclarations::Instances::ArduinoAnalogInputChannel_1.SystemLoopBegin();
 Declarations::Instances::Stepper1.SystemLoopBegin();
 Declarations::Instances::Stepper2.SystemLoopBegin();
}
``

Hi Gordon,

give this tutorial a try to improve your knowledge about programming

Arduino Programming Course

It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.

you will have much more fun if you don't have to beg for each and every next part of the code or how to change it to do this or that.

the code you have found makes things unnescessary complicated through using a lot of namespaces
I guess a lot of people here are "out of help" because of this complicated construction and never have used
the "mitov_stepper"-library

I offer support to write the code from scratch. This has two effects:

1: knowing exactly what your code does
2: improving your programming-skills while building your robot-arm

So a possible first step is:

take a joystick (the one used in this project seem to be analog)
reading out the value of X- and Y-axes and print the read-in value to the serial monitor
putting this functionality into a - guess what?! - a function!

int MyJoyStickReaderX() {
code to read in Joystick-X-position
}

int MyJoyStickReaderY() {
code to read in Joystick-Y-position
}

using a "standard-library like stepper.h or mobatools.h to make a single stepper-motor turn clockwise /counterclockwise

follow-up-step: examining the limits with which rpms does the motor rotate without loosing steps

If you know the rpm-limits, expanding the testcode for driving a stepper-motor to increase/decrease rpm with a variable.
from min-rpm to max-rpm

if this works adding the joystick-function to the drive-stepper-code .

Basic principle

My_X_Rpm = MyJoyStickReaderX()
run_X_Motor(My_X_Rpm)

My_Y_Rpm = MyJoyStickReaderY()
run_Y_Motor(My_Y_Rpm)

I bet if you go down this path a lot of people will join in with joy to answer any of the 2000 questions about any detail
you might have.

So what's your decision?

best regards Stefan