Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
controlling a stepper motor with PWM
/* Teensy LC sketch for controlling a stepper motor.
Reads comma-separate commands over serial. Sends back number of steps taken.
Commands are of the form:
step,300,800 -> stepper should move 300 sixteenth-steps forward at 800 steps per second
step,-124,100 -> stepper should move 124 sixteenth-steps backward at 100 steps per second
*/
// Setup the builtin LED, the step and direction pins.
const int ledPin = 13;
const int stepPin = 3;
const int dirPin = 2;
// Set the PWM duty cycle and counter pin.
const int dutyCycle = 25;
const int counterPin = 9;
// Define step targets and counters.
int stepTarget;
volatile int stepsTaken = 0;
// Store the direction the stepper is moving (one or zero).
int stepperDir;
// Setup command-reading vars.
static char commandBuffer[80];
int commandValue;
int commandFrequency;
// Periodically print status info.
elapsedMillis timeSinceLastPrint;
const int printDelayTime = 1000;
void setup() {
// Turn on the LED.
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
// Setup the stepper.
pinMode(dirPin, OUTPUT);
digitalWrite(dirPin, LOW);
pinMode(stepPin, OUTPUT);
// Setup the counter pin.
pinMode(counterPin, INPUT_PULLUP);
attachInterrupt(counterPin, stepInterrupt, RISING);
// Start serial comms over USB.
Serial.begin(57600);
}
int readline(int readch, char *commandBuffer, int len) {
/* Reads chars into a buffer until a carriage return is received.
Method via hackingmajenkoblog.wordpress.com
*/
static int pos = 0;
int rpos;
if (readch > 0) {
switch (readch) {
// Ignore new lines but return on CR.
case '\n':
break;
case '\r':
rpos = pos;
pos = 0;
return rpos;
default:
if (pos < len-1) {
commandBuffer[pos++] = readch;
commandBuffer[pos] = 0; // ??
}
}
}
// No end of line has been found, so return -1.
return -1;
}
void loop() {
// Try to read a command.
if (readline(Serial.read(), commandBuffer, 80) > 0) {
if (sscanf(commandBuffer, "step,%d,%d", &commandValue, &commandFrequency) == 2) {
// If the stepping command is valid, apply it.
if (commandValue > 0) {
digitalWrite(dirPin, HIGH);
stepperDir = 1;
} else {
digitalWrite(dirPin, LOW);
stepperDir = -1;
}
analogWriteFrequency(stepPin, commandFrequency);
stepTarget = stepsTaken + commandValue;
analogWrite(stepPin, dutyCycle);
} else {
Serial.print("Error: received message '");
Serial.print(commandBuffer);
Serial.println("'");
}
}
// Stop the stepper when it reaches its step target.
if (stepperDir == 1 && stepsTaken >= stepTarget) {
analogWrite(stepPin, 0);
}
else if (stepperDir == -1 && stepsTaken <= stepTarget) {
analogWrite(stepPin, 0);
}
// Periodically print the stepper position.
if (timeSinceLastPrint > printDelayTime) {
Serial.println(stepsTaken);
timeSinceLastPrint = 0;
}
}
// Setup counter interrupt. Increment the count in a direction-sensitive way.
void stepInterrupt() {
stepsTaken += stepperDir;
}
@ruizanthony

This comment has been minimized.

Copy link

commented May 3, 2019

Can you please indicate where you got the analogWriteFrequency from ?

I gather that the ellapsedMillis type comes from
https://github.com/pfeerick/elapsedMillis

@yosemitebandit

This comment has been minimized.

Copy link
Owner Author

commented May 28, 2019

@ruizanthony -- it's a builtin if you use the teensy libs, same with ellapsedMillis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.