環境構築: Arduino IDE 入門チュートリアル を参考に IDE をインストールし、使用する開発ボードに応じたボードマネージャーおよび必要なライブラリをインストールしてください。
使用するライブラリ:
使用ハードウェア:


ステッピングモーターは電気パルスを角変位に変換するモーターです。各パルスでシャフトが一定角度だけ回転します。この特性により、3DプリンタやCNC、ロボットなど精密な位置制御が必要な用途に適しています。
1. 構成:
2. 動作原理:
3. 主要パラメータ:
G5 (EN), G6 (STEP), G7 (DIR) を使用します。Atomic Stepmotor Base の DIP スイッチでマイクロステップを設定できます。4つのスイッチ M2、M1、M0、DECAY は DRV8825 の MODE2、MODE1、MODE0、DECAY に対応します。M2/M1/M0 でマイクロステップを選択し、DECAY は電流減衰モードの選択に使います。詳細は DRV8825 のデータシートを参照してください: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/module/DRV8825_en.pdf
下記スケッチでは step_division 変数でマイクロステップ倍率を指定します。DIP の設定に合わせて値を変更してください。本例では 1/32 マイクロステップを使用しています。
#include "M5Unified.h"
#include "M5GFX.h"
// Stepper motor configuration parameters
int step_division = 32; // Motor microstepping division factor
int number_of_steps = 200; // Number of steps per full revolution of the motor
int en_pin = 5; // Motor driver enable pin
int step_pin = 6; // Motor step control pin
int dir_pin = 7; // Motor direction control pin
// Timing variables for step control
unsigned long step_interval = 10000; // Microsecond interval between step pulses
unsigned long last_step_time = 0; // Timestamp of the last step pulse
unsigned long target_step_time1 = 0; // Target time for step pin HIGH state
unsigned long target_step_time2 = 0; // Target time for step pin LOW state
void motor_setSpeed(float rpm); // Set motor rotation speed (revolutions per minute)
void motor_powerEnable(bool ena); // Enable/disable motor driver
void motor_setDirection(long steps_to_move); // Set rotation direction based on step count
void motor_move(); // Generate a single step pulse
void motor_moveInterval(unsigned long target_delay); // Control step pulse timing
void motor_dynamicMove(int s1, int s2); // Step with dynamic acceleration/deceleration
void motor_step(long steps_to_move); // Move specified steps without acceleration
void motor_step_accdec(long steps_to_move, long steps_acc, long steps_dec); // Move with acceleration/deceleration
void setup() {
M5.begin();
M5.Lcd.setFont(&fonts::FreeMonoBoldOblique9pt7b); // Set display font
M5.Lcd.drawCenterString("Motor", 64, 64); // Display title at center
pinMode(en_pin, OUTPUT);
pinMode(dir_pin, OUTPUT);
pinMode(step_pin, OUTPUT);
motor_setSpeed(0); // Set initial speed to 0
motor_powerEnable(true); // Enable motor driver
delay(1600); // Short delay for initialization
}
void loop() {
M5.update();
if (M5.BtnA.wasPressed()) {
motor_setSpeed(300); // Set motor speed to 300 RPM
motor_step(1200); // Rotate 1200 steps clockwise
motor_step(-1200); // Rotate 1200 steps counter-clockwise
}
}
// ---- Function Definitions ----
/**
* Set motor rotation speed in revolutions per minute (RPM)
* Calculates step interval based on RPM, steps per revolution, and microstepping
* @param rpm Target rotation speed in revolutions per minute
*/
void motor_setSpeed(float rpm) {
// Calculate microsecond interval between steps:
// 60,000,000 microseconds/minute ÷ (steps/rev × RPM × microsteps)
step_interval = 60000000L / (number_of_steps * rpm * step_division);
}
/**
* Enable or disable the motor driver
* @param ena True to enable motor (driver active), false to disable
*/
void motor_powerEnable(bool ena) {
digitalWrite(en_pin, ena ? LOW : HIGH); // Typically, LOW enables most drivers
}
/**
* Set motor rotation direction based on step count sign
* @param steps_to_move Positive for clockwise, negative for counter-clockwise
*/
void motor_setDirection(long steps_to_move) {
if (steps_to_move < 0) {
digitalWrite(dir_pin, HIGH); // Set direction pin for counter-clockwise
} else {
digitalWrite(dir_pin, LOW); // Set direction pin for clockwise
}
}
/**
* Generate a single step pulse (HIGH then LOW) with proper timing
*/
void motor_move() {
digitalWrite(step_pin, HIGH); // Set step pin HIGH to trigger step
motor_moveInterval(step_interval); // Maintain HIGH state and then transition to LOW
}
/**
* Control timing for step pin state transitions
* Ensures proper duration for HIGH and LOW states of the step pulse
* @param target_delay Total duration of one step cycle (HIGH + LOW) in microseconds
*/
void motor_moveInterval(unsigned long target_delay) {
// Calculate target times for state transitions
target_step_time1 = last_step_time + (target_delay / 2); // Midpoint (HIGH to LOW)
target_step_time2 = last_step_time + target_delay; // End of cycle (LOW to next step)
// Wait for HIGH state duration
if (target_step_time1 >= last_step_time) {
while (micros() < target_step_time1) {} // Handle normal time progression
} else {
while ((long)(micros()) < (long)target_step_time1) {} // Handle micros() rollover
}
digitalWrite(step_pin, LOW); // Set step pin LOW after half the interval
// Wait for remaining LOW state duration
if (target_step_time2 >= last_step_time) {
while (micros() < target_step_time2) {} // Handle normal time progression
} else {
while ((long)(micros()) < (long)target_step_time2) {} // Handle micros() rollover
}
last_step_time = micros(); // Update last step timestamp
}
/**
* Generate a step with dynamic speed adjustment for acceleration/deceleration
* @param s1 Current step in acceleration/deceleration phase
* @param s2 Total steps in acceleration/deceleration phase
*/
void motor_dynamicMove(int s1, int s2) {
digitalWrite(step_pin, HIGH); // Start step pulse
// Calculate speed ratio using polynomial for smooth acceleration/deceleration
double r1 = (double)s1 / (double)s2;
double r2 = 0.1 + 0.2*r1 + 2.2*r1*r1 - 1.5*r1*r1*r1;
// Adjust step interval based on calculated ratio
motor_moveInterval((unsigned long)(step_interval / r2));
}
/**
* Move motor specified number of steps without acceleration
* Converts input steps to microstepped steps using step_division
* @param steps_to_move Number of steps to move (positive = clockwise, negative = counter-clockwise)
*/
void motor_step(long steps_to_move) {
steps_to_move *= step_division; // Convert to microstepped steps
motor_setDirection(steps_to_move); // Set rotation direction
last_step_time = micros(); // Initialize step timestamp
// Generate each step pulse
for (long i = abs(steps_to_move); i > 0; i--) {
motor_move();
}
}
/**
* Move motor with acceleration, constant speed, and deceleration phases
* @param steps_to_move Total steps to move (signed for direction)
* @param steps_acc Number of steps used for acceleration phase
* @param steps_dec Number of steps used for deceleration phase
*/
void motor_step_accdec(long steps_to_move, long steps_acc, long steps_dec) {
// Convert all step counts to microstepped values
steps_to_move *= step_division;
steps_acc *= step_division;
steps_dec *= step_division;
motor_setDirection(steps_to_move); // Set rotation direction
last_step_time = micros(); // Initialize step timestamp
// Acceleration phase: gradually increase speed
if (steps_acc > 0) {
for (long i = 1; i <= steps_acc; i++) {
motor_dynamicMove(i, steps_acc);
}
}
// Constant speed phase: maintain steady speed
long constant_steps = abs(steps_to_move) - abs(steps_acc) - abs(steps_dec);
for (long i = constant_steps; i > 0; i--) {
motor_move();
}
// Deceleration phase: gradually decrease speed
if (steps_dec > 0) {
for (long i = (steps_dec - 1); i >= 0; i--) {
motor_dynamicMove(i, steps_dec);
}
}
}