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
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
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