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