/*
Forum: https://forum.arduino.cc/t/protocol-for-avoiding-pointers/1394145
Wokwi: https://wokwi.com/projects/435993176508959745
2025/07/10
ec2021
Corrected version
unsigned long steps to float
MICROSTEP_SIZE to float
2025/07/11
ec2021
*/
#define NUM_ELEMENTS(_ArrayName) (sizeof(_ArrayName) / sizeof(_ArrayName[0]))
constexpr int CLOCKWISE {1};
constexpr int COUNTERCLOCKWISE {0};
constexpr long MOTOR_REV {0};
constexpr long DRIVER_MODE {0};
//constexpr long MICROSTEP_SIZE {1 / 8};
// Corrected 2025/07/11
constexpr float MICROSTEP_SIZE {1.0 / 8};
struct MotorData {
int stepPin;
int dirPin;
int direction;
int rpm;
};
//******************************************************************************
struct MotorClass {
MotorData data;
long speed;
bool run;
// unsigned long steps = 0;
// Corrected 2025/07/11
float steps = 0;
void init(MotorData mData) {
data.stepPin = mData.stepPin;
data.dirPin = mData.dirPin;
data.direction = mData.direction;
data.rpm = mData.rpm;
speed = 10000; // ((60000000L) / ((long)rpm * ((long)MOTOR_REV * (long)DRIVER_MODE))) / 2;
run = false;
pinMode(data.stepPin, OUTPUT);
pinMode(data.dirPin, OUTPUT);
}
void setClockWise(boolean cw) {
if (cw) {
data.direction = CLOCKWISE;
} else {
data.direction = COUNTERCLOCKWISE;
}
digitalWrite(data.dirPin, data.direction); //Set the direction.
}
void toggleDirection() {
setClockWise(data.direction == COUNTERCLOCKWISE);
}
void setRun(bool shall_run) {
run = shall_run;
if (!run) {
digitalWrite(data.stepPin, LOW); //Pulse OFF.
}
}
void handle() {
if (run) {
digitalWrite(data.stepPin, HIGH); //Pulse ON.
delayMicroseconds(speed); //Period halftime.
digitalWrite(data.stepPin, LOW); //Pulse OFF.
delayMicroseconds(speed); //Period halftime.
steps += MICROSTEP_SIZE; //Add 1/8 step (motor driver step mode.)
}
}
};
//******************************************************************************
// stepPin, dirPin, direction, rpm
MotorData motorData[] = {
{12, 11, 1, 360},
{10, 9, 1, 360},
{ 8, 7, 1, 360},
{ 6, 5, 1, 360}
};
constexpr int nMotor = NUM_ELEMENTS(motorData);
MotorClass motor[nMotor];
void setup() {
Serial.begin(115200);
for (int i = 0; i < nMotor; i++) {
motor[i].init(motorData[i]);
}
}
void loop() {
doSomethingAll(2);
for (int i = 0; i < nMotor; i++) {
motor[i].handle();
}
}
void doSomethingAll(unsigned long seconds) {
static unsigned long lastChange = 0;
static int activeMotor = 0;
static boolean isFirstCall = true;
if (millis() - lastChange > seconds * 1000UL || isFirstCall) {
lastChange = millis();
if (isFirstCall) {
isFirstCall = false;
} else {
motor[activeMotor].setRun(false);
activeMotor += 1;
if (activeMotor >= nMotor) {
activeMotor = 0;
}
}
motor[activeMotor].toggleDirection();
motor[activeMotor].setRun(true);
}
}