Class StepperDouble is the publish class of hierarchy implemented in pStpCouple.h library. Implements several advanced features and allows to perform movements with high precision. There are 11 programmed movements that can be quantified in centimeters or degrees (depending on movement). Movements can also be stored in a buffer and then executed in sequence. It also offers the option of using arduino timer2 for pulse timing.
Public declarations:
#define STP_MAX_BUFF_MOVES 16 #define STP_USE_TIMER2 #define STP_TIMER2_TIME 64 typedef struct{ byte mvType; union{ struct{ long stepsLf; long stepsRg; }; float param; }; } TMoveParam; class StepperCouple{ public: // Construction StepperCouple(); // Initialization void begin(uint startSpeed, uint cruiseSpeed, float wheelsDistance, uint turnStepsLf, uint turnStepsRg=0); void beginLf(int mPin_1, int mPin_2, int mPin_3, int mPin_4); void beginRg(int mPin_1, int mPin_2, int mPin_3, int mPin_4); void turboOn(); void turboOff(); void halfStepOn(); void halfStepOff(); void setReportSteps(long steps); //Calibration void moveSteps(byte mvType, long stepsLf, long stepsRg=0); void setBrakeCutPercent(byte brakeCutPercent); // Operation void run(); void moveOn(byte mvType); void move(TMoveParam* mov); void move(byte movType, float moveParam); boolean addMove(TMoveParam* mov); boolean addMove(byte mvType, float moveParam); void goNow(); void clearMoves(); void stopNow(); void decelStop(); void motorOff(); // Monitoring boolean halfStep(); boolean isMoving(); byte getMoveType(); ulong overlaps(); byte movesCount(); protected: virtual void onAllMovesDone(){} virtual void onStartMove(byte mvType, float moveParam){} virtual void onMoveDone(byte mvType, float arc, float dist){} virtual void onMoveReport(float arc, float dist){} };
Read first the topics discussed on the Stepper Motors page.
The purpose of the calibration is find out the parameters of begin() method.
To move the robot at this stage, use moveSteps () method.
Start with cruise and start speeds. Speeds are always reported in pulses per second . Is better to use only mv_TurnLf, mv_TurnRg, mv_Ahead and mv_Back moves at this point. Try some values to startSpeed and cruiseSpeed, until you think the movement is ok. The weight of the robot greatly influences the speed. Whenever the robot gains or loses significant weight, these speeds need to be revised.
The wheelsDistance parameter is the distance between the wheels in centimeters.
Next you need to find out how many steps are required to make a full turn (360 degrees) executing the moves mv_TurnLf and mv_TurnRg. Use moveSteps() method to try values until you get a good ones.
Note: The number of steps to complete a turn with the movement mv_TurnLf (or mv_TurnRg) can be calculated as a function of the distance between the wheels and their diameter. But my experience has shown that the calculated value is rarely equal to the value obtained in practice. That would be true if the two wheels were perfectly aligned, which is hardly the case in home-made robots. Small variations in wheels alignment or diameter can result in a significant difference in steps between the two movements. Of course, this affects the accuracy of movements. This difference introduces an accumulative error in calculations that increases with the extent of movement.
After attempting to correct this distortion by software in several ways, I obtained the best results using the turnStepsLf and turnStepsRg values as a reference for calculating steps for the moves. Both motors have independent timers and controls. The movement of one does not affect the movement of other. This allows class to do (or at least try to do) the necessary corrections. For example, when moving straight the motors can perform a different number of steps, but synchronized to start and finish at the same time.
BrakeCutPercent
The ideal value for this parameter depends heavily on the motors and the weight of the robot. It has to be a high enough to lock one wheel in the position it is in while the other executes the Turn movement. On the other hand, the lower the value, the lower the energy consumption and the lower the risk of something bad happen when the wheels enter in brake state. Keep in mind that, although useful for locking the wheels in a position, brake state cannot be maintained for long.
Call begin() before any method to inform the speeds and wheels params (see Calibration). Next, call beginLf() and beginRg() methods to inform control pins of stepper motors.
Then select the operation mode of motors (half step, turbo or none).
If needed, configure the brake cut percent calling setBrakeCutPercent().
If you want to receive events when certain number of steps are performed, call setReportSteps() informing the number of steps to trigger the event onMoveReport(). The value zero on steps parameter disable this event.
Dont forget to call run() method at least once per loop. Its necessary to trigger events.
To start a not buffered move, call move() or moveOn(). move() execute the movemente specified and stop (after decelerate). moveOn() causes the movement to continue until some method is called to stop.
To stop the movement immediately call stopNow(). To stop with deceleration call decelStop().
To store movements on buffer, call addMove(). To execute the movements stored, call goNow(), the movements will be executed in sequence. To clear the buffer call clearMoves(). movesCount() return the number of moves on buffer.
Overlaps occur when one timer event is triggered before the last event is done.
If you use timer2 to pulses, be sure that the return of overlaps() method is always zero. If not, increase the time between events by modifying the define STP_TIMER2_TIME. overlaps() method is not available (and doesn't occur) if the pulse timming is made by software.
Whenever a move is initiated the onStartMove() event is triggered. When the move ends or if it is aborted, the onMoveDone() event is triggered.
onAllMovesDone() is triggered when all moves on buffer were executed.
The onMoveReport() event was designed to support a real-time (or almost) positioning system in a higher-level class. It Is triggered whenever the minimum stipulated number of steps have been performed on both motors. To activate this event, call setReportSteps( ) informing the minimum number of steps to be triggered. The value zero stops the event.
Wiki: StepperDuo
Wiki: StepperMotors
Wiki: StepperSingle
Wiki: StpDuoBuff
Wiki: StpDuoTimer2