I am attempting to write a custom stepper motor control program to be implemented on a Sunfounder Arduino Uno. The idea is to simultaneously control two stepper motors ("feeder" and "conveyor"), each connected to its own L298N motor driver. The code is below:
/*
* Step C0 C1 C2 C3
* 1 1 0 1 0
* 2 0 1 1 0
* 3 0 1 0 1
* 4 1 0 0 1
*/
// Number of steps per output rotation
int stepsPerRevolution = 200;
// array to hold pins
int feederPins[] = {10, 11, 12, 13};
int conveyorPins[] = {6, 7, 8, 9};
// speeds in RPM
const int feederSpeed = 8;
const int conveyorSpeed = 20;
// store direction
boolean feederDir = true;
boolean conveyorDir = false;
// step number for each motor
byte feederStepNum = 1;
byte conveyorStepNum = 1;
// store the previous time value
unsigned long t_prev = 0;
// store the current time value
unsigned long t_now = 0;
// calculate step time delay
int feederStepDelay = int(1.0/(feederSpeed * stepsPerRevolution / float(60000)));
int conveyorStepDelay = int(1.0/(conveyorSpeed * stepsPerRevolution / float(60000)));
void setup()
{
for (int i = 0; i < 4; i++) {
pinMode(feederPins[i], OUTPUT);
pinMode(conveyorPins[i], OUTPUT);
}
t_prev = micros(); // only goes for 71min
}
void loop()
{
// get current time
unsigned long t_now = micros();
// check if this is bigger than either motor's delay
if ((t_now - t_prev) > feederStepDelay) {
// move the feeder
moveFeeder();
}
if ((t_now - t_prev) > conveyorStepDelay) {
// move the conveyor
moveConveyor();
}
// set the previous time to the time jut used for calculation
t_prev = t_now;
}
void moveFeeder() {
switch (feederStepNum) {
case 1: // 1010
digitalWrite(feederPins[0], HIGH);
digitalWrite(feederPins[1], LOW);
digitalWrite(feederPins[2], HIGH);
digitalWrite(feederPins[3], LOW);
break;
case 2: // 0110
digitalWrite(feederPins[0], LOW);
digitalWrite(feederPins[1], HIGH);
digitalWrite(feederPins[2], HIGH);
digitalWrite(feederPins[3], LOW);
break;
case 3: // 0101
digitalWrite(feederPins[0], LOW);
digitalWrite(feederPins[1], HIGH);
digitalWrite(feederPins[2], LOW);
digitalWrite(feederPins[3], HIGH);
break;
case 4: // 1001
digitalWrite(feederPins[0], HIGH);
digitalWrite(feederPins[1], LOW);
digitalWrite(feederPins[2], LOW);
digitalWrite(feederPins[3], HIGH);
break;
}
if (!feederDir) { // increment step number
feederStepNum++;
if (feederStepNum == 5) feederStepNum = 1;
} else { // decrement step number
feederStepNum--;
if (feederStepNum == 0) feederStepNum = 4;
}
}
void moveConveyor() {
switch (conveyorStepNum) {
case 1: // 1010
digitalWrite(conveyorPins[0], HIGH);
digitalWrite(conveyorPins[1], LOW);
digitalWrite(conveyorPins[2], HIGH);
digitalWrite(conveyorPins[3], LOW);
break;
case 2: // 0110
digitalWrite(conveyorPins[0], LOW);
digitalWrite(conveyorPins[1], HIGH);
digitalWrite(conveyorPins[2], HIGH);
digitalWrite(conveyorPins[3], LOW);
break;
case 3: // 0101
digitalWrite(conveyorPins[0], LOW);
digitalWrite(conveyorPins[1], HIGH);
digitalWrite(conveyorPins[2], LOW);
digitalWrite(conveyorPins[3], HIGH);
break;
case 4: // 1001
digitalWrite(conveyorPins[0], HIGH);
digitalWrite(conveyorPins[1], LOW);
digitalWrite(conveyorPins[2], LOW);
digitalWrite(conveyorPins[3], HIGH);
break;
}
if (!conveyorDir) { // increment step number
conveyorStepNum++;
if (conveyorStepNum == 5) conveyorStepNum = 1;
} else { // decrement step number
conveyorStepNum--;
if (conveyorStepNum == 0) conveyorStepNum = 4;
}
}
When I compile and run this program, absolutely nothing happens. I checked the wiring with the built-in Stepper library and everything worked as expected. I initially attempted to debug the program using the serial monitor and adding a several print statements throughout the program. When I did this, the program and motors suddenly worked; however, when I removed the print statements (without changing any other code), it didn't. Through trial and error, I determined that printing out the value of t_now in the loop causes the program to work.
In response to this, I attempted to debug the code in Visual Studio in accordance with this article; however, I was unable to interpret what I was seeing (see attached screenshot).
After searching for similar issues, I found that this may have something to do with compiler optimization. Thus, I attempted to declare t_prev and t_now as volatile; however, this did not work. I then declared every global variable as volatile, and that didn't work either. Interestingly, the program seems to use very little memory on the global variables:
Sketch uses 1294 bytes (4%) of program storage space. Maximum is 32256 bytes.
Global variables use 19 bytes (0%) of dynamic memory, leaving 2029 bytes for local variables. Maximum is 2048 bytes.
Thus, I'm wondering what the cause of this problem is, as well as if there are any solutions to it. Is it possible to disable the compiler optimization? Is there another way to force these variables to be included? Is there a different, simpler approach I can take to this problem that accomplishes the same goal? I would greatly appreciate any insight or solutions anyone is willing to provide!
Thank you!
