TinyRobotics
Loading...
Searching...
No Matches
StepperMotor.h
1#pragma once
2#include "FastAccelStepper.h"
3#include "TinyRobotics/utils/Config.h"
4#ifdef AVR
5#include "AVRStepperPins.h" // Only required for AVR controllers
6#endif
7#include "IMotor.h"
8
9namespace tinyrobotics {
10
11/**
12 * @class StepperMotor
13 * @ingroup motors
14 * @brief Stepper motor driver using FastAccelStepper for Arduino.
15 *
16 * This class provides an interface to control stepper motors with acceleration
17 * and speed control. It supports:
18 * - Continuous speed mode: setSpeed(percent) for indefinite movement at a
19 * given speed and direction.
20 * - Relative movement: moveRevolutions(revolutions, speedPercent, callback,
21 * ref) to move a specific number of revolutions, with optional callback on
22 * completion.
23 * - Distance-based movement: moveDistance(distance, wheelDiameter,
24 * speedPercent, callback, ref) to move a specific physical distance (using
25 * wheel diameter), with optional callback.
26 *
27 * You can set pins, maximum speed, acceleration, and steps per revolution. The
28 * motor can be started, stopped, or moved by distance or revolutions.
29 * Acceleration is handled automatically based on the configured accelerationMs.
30 *
31 * The class uses FastAccelStepper's continuous mode for setSpeed(), and
32 * supports asynchronous notification via callback for move operations.
33 *
34 * @dependencies
35 * - Requires the FastAccelStepper library:
36 * https://github.com/ESP32DIYer/FastAccelStepper (Install via Arduino Library
37 * Manager or PlatformIO)
38 * - Uses Arduino core functions (e.g., constrain, map)
39 *
40 * Main methods:
41 * - setPins(stepPin, dirPin, enablePin): Assigns the control pins for the
42 * stepper driver.
43 * - setMaxSpeed(stepsPerSec): Sets the maximum speed in steps per second.
44 * - setStepsPerRevolution(steps): Sets the number of steps per full revolution.
45 * - setAccelerationMs(ms): Sets the time in milliseconds to reach max speed
46 * (acceleration).
47 * - begin(): Initializes the stepper hardware and prepares for movement.
48 * - setSpeed(percent): Starts continuous movement at the given speed percentage
49 * (-100 to 100) using continuous mode.
50 * - moveRevolutions(revolutions, speedPercent, callback, ref): Move the stepper
51 * by a given number of revolutions at a specified speed, with optional
52 * callback.
53 * - moveDistance(distance, wheelDiameter, speedPercent, callback, ref): Move
54 * the stepper by a physical distance (using wheel diameter), at a specified
55 * speed, with optional callback.
56 * - end(): Stops the stepper motor.
57 *
58 * Usage notes:
59 * - Call begin() after setting pins and speed parameters.
60 * - Use setSpeed(percent) to start or change continuous movement. Use
61 * setSpeed(0) to stop.
62 * - Acceleration is set in setSpeed() based on the configured accelerationMs.
63 *
64 * Example usage:
65 * @code
66 * Stepper stepper;
67 * stepper.setPins(2, 3, 4);
68 * stepper.setMaxSpeed(1000);
69 * stepper.setStepsPerRevolution(200);
70 * stepper.setAccelerationMs(2000);
71 * stepper.begin();
72 * stepper.setSpeed(50); // Move at 50% of max speed (continuous mode)
73 * stepper.setSpeed(0); // Stop
74 * stepper.end(); // Ensure motor is stopped
75 * @endcode
76 */
77template <typename T = float>
78class StepperMotor : public IMotor<T> {
79 public:
80 StepperMotor(uint8_t id = 0) { setID(id); }
81 StepperMotor(uint8_t id, uint16_t stepsPerRevolution,
82 float maxSpeedStepsPerSec, uint16_t accelerationMs) {
83 setID(id);
84 setMaxSpeed(maxSpeedStepsPerSec);
85 setAccelerationMs(accelerationMs);
86 setStepsPerRevolution(stepsPerRevolution);
87 }
88
89 void setPins(int stepPin, int dirPin, int enablePin = -1) {
90 pinStep = stepPin;
91 pinDir = dirPin;
92 pinEnable = enablePin;
93 is_pins_set = true;
94 }
95
96 /// Set maximum speed in steps per second (e.g., 500 for 1.8 degree stepper,
97 /// 1000
98 void setMaxSpeed(float stepsPerSec) { maxSpeedHz = stepsPerSec; }
99
100 /// Set acceleration time in milliseconds to reach max speed (e.g., 2000 ms)
101 void setAccelerationMs(uint16_t ms) { accelerationMs = ms; }
102
103 /// Set the number of steps per full revolution (e.g., 200 for 1.8 degree
104 /// stepper)
105 void setStepsPerRevolution(int steps) { stepsPerRevolution = steps; }
106
107 /// Initialize the stepper hardware. Must be called after setting pins and
108 /// speed parameters.
109 bool begin() {
110 if (!is_pins_set) return false;
111 engine.init();
112 stepper = engine.stepperConnectToPin(pinStep);
113 if (stepper) {
114 stepper->setDirectionPin(pinDir);
115 if (pinEnable != -1) stepper->setEnablePin(pinEnable);
116 stepper->setAutoEnable(true);
117 }
118 return stepper != nullptr;
119 }
120
121 /// Set continuous speed as a percentage (-100 to 100). Positive for forward,
122 /// negative for backward.
123 // Set value as percentage (-100 to 100)
124 bool setValuePercent(T percent) override {
125 if (!stepper) return false;
126 lastValuePercent = constrain(percent, -100.0f, 100.0f);
127 setSpeedPercent(lastValuePercent);
128 if (lastValuePercent >= 0) {
129 stepper->runForward();
130 } else {
131 stepper->runBackward();
132 }
133 return true;
134 }
135
136 T getValuePercent() const override {
137 return lastValuePercent;
138 }
139
140 // /// Move the stepper by n revolutions (positive or negative) and
141 // optionally
142 // /// call a callback when done.
143 // bool moveRevolutions(T revolutions, int8_t speedPercent,
144 // void* ref = nullptr) {
145 // if (!stepper) return false;
146 // setSpeedPercent(speedPercent);
147 // int steps = revolutions * stepsPerRevolution;
148 // this->callback = callback;
149 // this->ref = ref;
150 // stepper->setNotifyCallback(callbackFastAccel);
151 // stepper->move(steps);
152 // }
153
154 // /// Move the stepper by a specific distance (in units of length) based on
155 // the bool moveDistance(Distance distance, Distance wheelDiameter,
156 // int8_t speedPercent, void (*callback)(void*) = nullptr,
157 // void* ref = nullptr) {
158 // if (!stepper) return false;
159 // T circumferenceM = PI * wheelDiameter.getDistance(DistanceUnit::M);
160 // T revolutions = distance.getDistance(DistanceUnit::M) /
161 // circumferenceM; return moveRevolutions(revolutions, speedPercent,
162 // callback, ref);
163 // }
164
165 /// Stop the stepper motor.
166 void end() override {
167 if (stepper) {
168 stepper->stopMove();
169 }
170 }
171
172 bool isPinsSet() const override { return is_pins_set; }
173
174 protected:
175 T lastValuePercent = 0.0f;
176 FastAccelStepperEngine engine;
177 FastAccelStepper* stepper = NULL;
178 int pinStep = -1;
179 int pinDir = -1;
180 int pinEnable = -1;
181 bool is_pins_set = false;
182 // steps/sec: typical values: 500 for 1.8 degree stepper, 1000 for 0.9 degree
183 // stepper, etc.
184 float maxSpeedHz = 2000;
185 // time in ms to reach max speed, adjust as needed
186 uint16_t accelerationMs = 2000;
187 // typical values: 200 for 1.8 degree stepper, 400 for 0.9 degree stepper,
188 // etc.
189 uint16_t stepsPerRevolution = 200;
190 void* ref = nullptr;
191 void (*callback)(void*) = nullptr;
192
193 void callbackFastAccel(FastAccelStepper* s) {
194 if (callback) {
195 callback(ref);
196 }
197 }
198
199 void setSpeedPercent(T percent) {
200 percent = constrain(percent, -100.0f, 100.0f);
201 int speed = map((int)percent, -100, 100, -maxSpeedHz, maxSpeedHz);
202
203 // Calculate acceleration in steps/sec^2 based on the time to reach max
204 // speed
205 int acceleration = (maxSpeedHz * 1000) / accelerationMs; // steps/sec^2
206 stepper->setAcceleration(acceleration);
207
208 // set speed (FastAccelStepper uses setSpeedInHz for continuous mode)
209 stepper->setSpeedInHz(abs(speed));
210 }
211
212};
213} // namespace tinyrobotics
Abstract base class for all motor driver types.
Definition: IMotor.h:21
Stepper motor driver using FastAccelStepper for Arduino.
Definition: StepperMotor.h:78
void setMaxSpeed(float stepsPerSec)
Definition: StepperMotor.h:98
bool setValuePercent(T percent) override
Definition: StepperMotor.h:124
bool begin()
Definition: StepperMotor.h:109
void end() override
Stop the stepper motor.
Definition: StepperMotor.h:166
void setStepsPerRevolution(int steps)
Definition: StepperMotor.h:105
void setAccelerationMs(uint16_t ms)
Set acceleration time in milliseconds to reach max speed (e.g., 2000 ms)
Definition: StepperMotor.h:101