/* * Generic Stepper Motor Driver Driver * Indexer mode only. * Copyright (C)2015 Laurentiu Badea * * This file may be redistributed under the terms of the MIT license. * A copy of this license has been included with this distribution in the file LICENSE. */ //#define DEBUG #include "BasicStepperDriver.h" /* * Basic connection: only DIR, STEP are connected. * Microstepping controls should be hardwired. */ BasicStepperDriver::BasicStepperDriver(int steps, int dir_pin, int step_pin) :motor_steps(steps), dir_pin(dir_pin), step_pin(step_pin) { init(); } BasicStepperDriver::BasicStepperDriver(int steps, int dir_pin, int step_pin, int enable_pin) :motor_steps(steps), dir_pin(dir_pin), step_pin(step_pin), enable_pin(enable_pin) { init(); } BasicStepperDriver::BasicStepperDriver(int steps, int dir_pin, int step_pin, int home_pin, int max_pin) :motor_steps(steps), dir_pin(dir_pin), step_pin(step_pin), home_pin(home_pin), max_pin(max_pin) { init(); home(); } /* * Adding a function for setting the home position */ void BasicStepperDriver::home(void){ //todo // start x toward home until home pin state changes. // start y toward home until home pin state changes. // return } void BasicStepperDriver::init(void){ pinMode(dir_pin, OUTPUT); digitalWrite(dir_pin, HIGH); pinMode(step_pin, OUTPUT); digitalWrite(step_pin, LOW); if IS_CONNECTED(enable_pin){ pinMode(enable_pin, OUTPUT); digitalWrite(enable_pin, HIGH); // disable } if IS_CONNECTED(home_pin){ pinMode(home_pin, INPUT_PULLUP); } if IS_CONNECTED(max_pin) { pinMode(max_pin, INPUT_PULLUP); } setMicrostep(1); setRPM(60); // 60 rpm is a reasonable default enable(); } void BasicStepperDriver::calcStepPulse(void){ step_pulse = STEP_PULSE(rpm, motor_steps, microsteps); } /* * Set target motor RPM (1-200 is a reasonable range) */ void BasicStepperDriver::setRPM(unsigned rpm){ this->rpm = rpm; calcStepPulse(); } /* * Set stepping mode (1:microsteps) * Allowed ranges for BasicStepperDriver are 1:1 to 1:128 */ unsigned BasicStepperDriver::setMicrostep(unsigned microsteps){ for (unsigned ms=1; ms <= this->getMaxMicrostep(); ms<<=1){ if (microsteps == ms){ this->microsteps = microsteps; break; } } calcStepPulse(); return this->microsteps; } /* * DIR: forward HIGH, reverse LOW */ void BasicStepperDriver::setDirection(int direction){ digitalWrite(dir_pin, (direction<0) ? LOW : HIGH); } /* * DIR: forward HIGH, reverse LOW */ int BasicStepperDriver::getDirection(void){ if (digitalRead(dir_pin) == HIGH ) {return 1;} else {return -1;} } /* * Move the motor a given number of steps. * positive to move forward, negative to reverse */ void BasicStepperDriver::move(long steps){ int direction_pin; if (steps >= 0){ setDirection(1); direction_pin = home_pin; } else { setDirection(-1); direction_pin = max_pin; steps = -steps; } /* * We currently try to do a 50% duty cycle so it's easy to see. * Other option is step_high_min, pulse_duration-step_high_min. */ unsigned long pulse_duration = step_pulse/2; while (steps--){ /* * Test to see if we hit an end stop. */ if (digitalRead(direction_pin) == LOW) { #ifdef DEBUG Serial.print("Reached limit: "); Serial.println(direction_pin); #endif return; } digitalWrite(step_pin, HIGH); unsigned long next_edge = micros() + pulse_duration; microWaitUntil(next_edge); digitalWrite(step_pin, LOW); microWaitUntil(next_edge + pulse_duration); } } /* * Move the motor a given number of degrees (1-360) */ void BasicStepperDriver::rotate(long deg){ long steps = deg * motor_steps * (long)microsteps / 360; move(steps); } /* * Move the motor with sub-degree precision. * Note that using this function even once will add 1K to your program size * due to inclusion of float support. */ void BasicStepperDriver::rotate(double deg){ long steps = deg * motor_steps * microsteps / 360; move(steps); } /* * Enable/Disable the motor by setting a digital flag */ void BasicStepperDriver::enable(void){ if IS_CONNECTED(enable_pin){ digitalWrite(enable_pin, LOW); } } void BasicStepperDriver::disable(void){ if IS_CONNECTED(enable_pin){ digitalWrite(enable_pin, HIGH); } } unsigned BasicStepperDriver::getMaxMicrostep(){ return BasicStepperDriver::MAX_MICROSTEP; }