Created
November 3, 2018 23:00
-
-
Save jonathanjuursema/730132b4d7b2ff22cb3ce989887e2d59 to your computer and use it in GitHub Desktop.
Arduino sketch to control a stepper motor with an A4988 driver. Specifically written to control a 2DoF turret (https://www.thingiverse.com/thing:417528), hence the rotational calculations.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is the number of steps per revolution for the NEMA17HR stepper motor. | |
const float gearRatio = 50 / 7; | |
const int motorStepsPerRevolution = 400; | |
/* | |
* The Stepper class abstracts one stepper motor and contains the logic the control said motor. | |
* This class is written for the A4988 stepper driver but might also work for others. | |
*/ | |
class Stepper { | |
public: | |
Stepper(int stepperPin, int directionPin); | |
void moveTo(float angleInDegrees); | |
float getCurrentAngle(); | |
private: | |
int _stepperPin; | |
int _directionPin; | |
int _stepsPerRevolution; | |
int _currentAngleInSteps; | |
float _degreesPerStep; | |
}; | |
Stepper::Stepper(int stepperPin, int directionPin) { | |
_stepperPin = stepperPin; | |
_directionPin = directionPin; | |
_currentAngleInSteps = 0; | |
_stepsPerRevolution = (int)((float)motorStepsPerRevolution * gearRatio); | |
_degreesPerStep = (float)360 / _stepsPerRevolution; | |
pinMode(_stepperPin, OUTPUT); | |
pinMode(_directionPin, OUTPUT); | |
digitalWrite(_stepperPin, LOW); | |
digitalWrite(_directionPin, LOW); | |
} | |
void Stepper::moveTo(float angleInDegrees) { | |
int newAngleInSteps = int(angleInDegrees / _degreesPerStep) % _stepsPerRevolution; | |
int stepsToMove = newAngleInSteps - _currentAngleInSteps; | |
bool directionPin = stepsToMove > 0 ? LOW : HIGH; | |
int directionInt = stepsToMove > 0 ? 1 : -1; | |
digitalWrite(_directionPin, directionPin); | |
while (_currentAngleInSteps != newAngleInSteps) { | |
digitalWrite(_stepperPin, HIGH); | |
delayMicroseconds(1000); | |
digitalWrite(_stepperPin, LOW); | |
delayMicroseconds(1000); | |
_currentAngleInSteps += directionInt; | |
} | |
} | |
float Stepper::getCurrentAngle() { | |
return _currentAngleInSteps * _degreesPerStep; | |
} | |
/* | |
* Split a string based on a given delimiter and return the item at index. | |
* Taken from: https://arduino.stackexchange.com/a/1237 | |
*/ | |
String getValue(String data, char separator, int index) | |
{ | |
int found = 0; | |
int strIndex[] = { 0, -1 }; | |
int maxIndex = data.length() - 1; | |
for (int i = 0; i <= maxIndex && found <= index; i++) { | |
if (data.charAt(i) == separator || i == maxIndex) { | |
found++; | |
strIndex[0] = strIndex[1] + 1; | |
strIndex[1] = (i == maxIndex) ? i + 1 : i; | |
} | |
} | |
return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; | |
} | |
/* | |
* Declare the stepper motors. | |
*/ | |
Stepper horizontal(12, 13); | |
Stepper vertical(7, 8); | |
/* | |
* Initialise program. | |
*/ | |
void setup() { | |
Serial.begin(9600); | |
Serial.println("StarGazer Turret Driver"); | |
horizontal.moveTo(0); | |
vertical.moveTo(0); | |
} | |
/* | |
* Read input from serial and report back. | |
* Expected input is XXX:YYY where XXX is the horizontal angle, and YYY is the vertical angle, both in degrees. | |
* Output should be the same, representing the current position. | |
*/ | |
void loop() { | |
while (Serial.available()) { | |
String input = Serial.readString(); | |
float newHorizontalAngle = getValue(input, ':', 0).toFloat(); | |
horizontal.moveTo(newHorizontalAngle); | |
float newVerticalAngle = getValue(input, ':', 1).toFloat(); | |
vertical.moveTo(newVerticalAngle); | |
} | |
Serial.print(horizontal.getCurrentAngle()); | |
Serial.print(':'); | |
Serial.println(vertical.getCurrentAngle()); | |
delay(1000); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment