How versatile is my stepper motor driver software?
DavidZemon
Posts: 2,973
I wrote some code for a stepper motor and I'm now working on the docs. I want to ensure the docs reflect exactly what it can and can not do.
I have a bipolar and 5-wire unipolar stepper to test with, so I know it works great for those two types. And if I understand it right, those are the only two that can share software, right? The 6- and 8-wire unipolars require different code? I know you can tie certain wires together to create either a bipolar or 5-wire unipolar from 6- and 8-wire unipolars, but I'm not concerned about explaining that in my docs.
Here's the code I have (probably not necessary to answer my question, but just in case), and thank you in advance.
I have a bipolar and 5-wire unipolar stepper to test with, so I know it works great for those two types. And if I understand it right, those are the only two that can share software, right? The 6- and 8-wire unipolars require different code? I know you can tie certain wires together to create either a bipolar or 5-wire unipolar from 6- and 8-wire unipolars, but I'm not concerned about explaining that in my docs.
Here's the code I have (probably not necessary to answer my question, but just in case), and thank you in advance.
/**
* @brief 4-pin bipolar and 5-pin unipolar stepper motor driver
*/
class Stepper {
public:
/**
* @brief Default delay in microseconds used between each step
*/
static const unsigned int DEFAULT_DELAY = 10000;
enum class Step {
HALF,
ONE,
ONE_AND_A_HALF,
TWO,
TWO_AND_A_HALF,
THREE,
THREE_AND_A_HALF,
FOUR
};
public:
/**
* @brief Constructor
*
* @param[in] phase1Mask Pin mask connected to phase 1
* @param[in] phase2Mask Pin mask connected to phase 2
* @param[in] phase3Mask Pin mask connected to phase 3
* @param[in] phase4Mask Pin mask connected to phase 4
* @param[in] start What step should the motor start with
*/
Stepper (const Pin::Mask phase1Mask, const Pin::Mask phase2Mask, const Pin::Mask phase3Mask,
const Pin::Mask phase4Mask, const Step start = Step::HALF)
: m_currentStep(start),
m_phase1(phase1Mask, Pin::Dir::OUT),
m_phase2(phase2Mask, Pin::Dir::OUT),
m_phase3(phase3Mask, Pin::Dir::OUT),
m_phase4(phase4Mask, Pin::Dir::OUT) {
this->set_step();
}
/**
* @brief Move the motor directly to the specified step
*
* @param step[in] Step to move to
*/
void set_step (const Stepper::Step step) {
this->m_currentStep = step;
this->set_step();
}
/**
* @brief Get the current step
* @return Current step where the motor is holding
*/
Step get_step () const {
return this->m_currentStep;
}
/**
* @brief Step the motor to the nearest half-step to achieve a full-power hold
*
* @param direction[in] True for forward, false for backward
* @param usDelay Delay in microseconds after the step is taken (must be greater than 17 for lmm)
*
* @return True if the motor requirement movement to achieve full-power hold, false if the
* motor was already on a full-power hold
*/
bool full_power_hold (const bool direction, const unsigned int usDelay = DEFAULT_DELAY) {
const bool movementNeeded = static_cast<bool>(static_cast<uint32_t>(this->m_currentStep) % 2);
if (movementNeeded) {
if (direction)
this->half_forward(1, usDelay);
else
this->half_reverse(1, usDelay);
}
return movementNeeded;
}
/**
* @brief Step the motor to the nearest full-step to achieve a half-power hold
*
* @param direction[in] True for forward, false for backward
* @param usDelay Delay in microseconds after the step is taken (must be greater than 17 for lmm)
*
* @return True if the motor requirement movement to achieve half-power hold, false if the
* motor was already on a half-power hold
*/
bool half_power_hold (const bool direction, const unsigned int usDelay = DEFAULT_DELAY) {
const bool movementNeeded = !static_cast<bool>(static_cast<uint32_t>(this->m_currentStep) % 2);
if (movementNeeded) {
if (direction)
this->half_forward(1, usDelay);
else
this->half_reverse(1, usDelay);
}
return movementNeeded;
}
/**
* @brief Move the motor forward by a specified number of steps
*
* @param[in] steps Number of steps to move forward
* @param[in] usDelay Delay in microseconds between steps (must be greater than 17 for lmm)
*/
void step_forward (unsigned int steps, const unsigned int usDelay = DEFAULT_DELAY) {
while (steps--) {
const unsigned int stepNumber = static_cast<unsigned int>(this->m_currentStep) + 2;
this->m_currentStep = static_cast<Step>(stepNumber % 8);
this->set_step();
waitcnt(usDelay * MICROSECOND + CNT);
}
}
/**
* @brief Move the motor forward the a specified number of half-steps
*
* @param[in] halfSteps Number of half-steps to move forward
* @param[in] usDelay Delay in microseconds between half-steps (must be greater than 17 for lmm)
*/
void half_forward (unsigned int halfSteps, const unsigned int usDelay = DEFAULT_DELAY) {
while (halfSteps--) {
const unsigned int stepNumber = static_cast<unsigned int>(this->m_currentStep) + 1;
this->m_currentStep = static_cast<Step>(stepNumber % 8);
this->set_step();
waitcnt(usDelay * MICROSECOND + CNT);
}
}
/**
* @brief Move the motor backward by a specified number of steps
*
* @param[in] steps Number of steps to move backward
* @param[in] usDelay Delay in microseconds between steps (must be greater than 17 for lmm)
*/
void step_reverse (unsigned int steps, const unsigned int usDelay = DEFAULT_DELAY) {
while (steps--) {
const unsigned int stepNumber = static_cast<unsigned int>(this->m_currentStep) + 6;
this->m_currentStep = static_cast<Step>(stepNumber % 8);
this->set_step();
waitcnt(usDelay * MICROSECOND + CNT);
}
}
/**
* @brief Move the motor backward by a specified number of half-steps
*
* @param[in] halfSteps Number of half-steps to move backward
* @param[in] usDelay Delay in microseconds between steps (must be greater than 17 for lmm)
*/
void half_reverse (unsigned int halfSteps, const unsigned int usDelay = DEFAULT_DELAY) {
while (halfSteps--) {
const unsigned int stepNumber = static_cast<unsigned int>(this->m_currentStep) + 7;
this->m_currentStep = static_cast<Step>(stepNumber % 8);
this->set_step();
waitcnt(usDelay * MICROSECOND + CNT);
}
}
private:
/**
* @brief Move the motor to the step specified
*/
void set_step () {
switch (this->m_currentStep) {
case Step::HALF:
this->m_phase1.set();
this->m_phase2.set();
this->m_phase3.clear();
this->m_phase4.clear();
break;
case Step::ONE:
this->m_phase1.clear();
this->m_phase2.set();
this->m_phase3.clear();
this->m_phase4.clear();
break;
case Step::ONE_AND_A_HALF:
this->m_phase1.clear();
this->m_phase2.set();
this->m_phase3.set();
this->m_phase4.clear();
break;
case Step::TWO:
this->m_phase1.clear();
this->m_phase2.clear();
this->m_phase3.set();
this->m_phase4.clear();
break;
case Step::TWO_AND_A_HALF:
this->m_phase1.clear();
this->m_phase2.clear();
this->m_phase3.set();
this->m_phase4.set();
break;
case Step::THREE:
this->m_phase1.clear();
this->m_phase2.clear();
this->m_phase3.clear();
this->m_phase4.set();
break;
case Step::THREE_AND_A_HALF:
this->m_phase1.set();
this->m_phase2.clear();
this->m_phase3.clear();
this->m_phase4.set();
break;
case Step::FOUR:
this->m_phase1.set();
this->m_phase2.clear();
this->m_phase3.clear();
this->m_phase4.clear();
break;
}
}
private:
Step m_currentStep;
Pin m_phase1;
Pin m_phase2;
Pin m_phase3;
Pin m_phase4;
};
