Skip to content

Instantly share code, notes, and snippets.

@Robotto
Created March 24, 2026 07:59
Show Gist options
  • Select an option

  • Save Robotto/60b27e218d9595101eb3cd1db9d3230c to your computer and use it in GitHub Desktop.

Select an option

Save Robotto/60b27e218d9595101eb3cd1db9d3230c to your computer and use it in GitHub Desktop.
Linear Stepper motor driver with simpleFOC
// Open loop motor control example
// Open loop means no positional feedback.
#include <SimpleFOC.h> //http://librarymanager/All#Simple%20FOC
// Stepper motor & driver instance
//The motor is this thing:
StepperMotor motor = StepperMotor(10); //18 degrees per step = 20 poles = 10 pole pairs
StepperDriver4PWM driver = StepperDriver4PWM(18,19,5,23);
float outPosition = 500.0; //Position of the end of travel for the linear thingy
//target variable
float target_position = 0.0;
// instantiate the commander - Talk to this with the serial monitor. (Set it to newline only, 115200 baud)
//Commands:
//? -> list options
//T -> [T]arget angle
//L -> voltage [L]imit
//V -> [V]elocity
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_position, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
void doVelocity(char* cmd) { command.scalar(&motor.velocity_limit, cmd); }
void setup() {
// use monitoring with serial
Serial.begin(115200);
// enable more verbose output for debugging
// comment out if not needed
SimpleFOCDebug::enable(&Serial);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 5;
// limit the maximal dc voltage the driver can set
// as a protection measure for the low-resistance motors
// this value is fixed on startup
driver.voltage_limit = 12; //800ma 12V = 15 ohm = 9.6W - At 5V thats
if(!driver.init()){
Serial.println("Driver init failed!");
return;
}
// link the motor and the driver
motor.linkDriver(&driver);
// limiting motor movements
// limit the voltage to be set to the motor
// start very low for high resistance motors
// currnet = voltage/resistance, so try to be well under 1Amp
motor.voltage_limit = 12.0; // [V] seems to work
// limit/set the velocity of the transition in between
// target angles
motor.velocity_limit = 150.0; // [rad/s] 1400ish rpm seems to work
// open loop control config
motor.controller = MotionControlType::angle_openloop;
// init motor hardware
if(!motor.init()){
Serial.println("Motor init failed!");
return;
}
motor.voltage_limit=12.0;
// add target command T
command.add('T', doTarget, "target angle");
command.add('L', doLimit, "voltage limit");
command.add('V', doVelocity, "movement velocity");
Serial.println("Motor ready!");
Serial.println("Set target position [rad]");
_delay(1000);
}
unsigned long lastTick=0;
float delta=0.1;
void loop() {
//torque control
// should be called as frequently as possible
motor.loopFOC();
// open loop angle movements
// using motor.voltage_limit and motor.velocity_limit
if(millis()-lastTick>8000)
{
//if (target_position < 0.1) {target_position=0; delta = 0.1; Serial.println(target_position);}
//if (target_position > 100.0) {target_position=100.0; delta = -0.1; Serial.println(target_position);}
//target_position+=delta;
if(target_position==0.0) target_position=outPosition;
else target_position=0.0;
lastTick=millis();
Serial.print("Target: ");
Serial.println(target_position);
}
// angles can be positive or negative, negative angles correspond to opposite motor direction
motor.move(target_position);
// user communication
command.run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment