A bug or am I missing something in a While function

I have a piece of code and have built my own custom hardware to drive a stepper motor.

One function in the code turns the motor by 1920 steps over a period of time.

In the function below, the While loop works perfectly fine only when the Serial.print and Serial.println part is included (using it for debugging). When I remove these the While loop will not function, it is as if the counter does not count and instead simply runs only when by finger is on the button which calls the loop.

In the code below I have got the “Serial.println(motorTimerA1);” line near the bottom. It doesn’t matter where I place it, it works fine. As soon as I remove it, the While function doesn’t work.

I have tried adding a 20uS delay instead, but it fails just the same.

I have not included the whole code as it is nearing 2000 lines, and the circuit diagrams are on A2 sized paper. I am using 595 shift registers to drive the outputs via the shiftDrive() function and the function is called by reading a 165 shift register and using BitMath to check if the appropriate bit is active.

The “steps” variable is set to 48 (giving 1920 runs of the While loop), and the “step_timer” is 10 milliseconds. This function takes around 12 seconds to run through the 1920 steps. The rest of the code halts while this is counting, which is fine for what it needs to do.

The other 1999 lines of code work flawlessly so I can’t see why adding the one Serial.println line would make it work when all it does is tell me what it is doing via Hyperterminal.

void motorA()
{
 unsigned long motorTimerA1;                       // Variable used within this function
 
 digitalWrite(step_enA, HIGH);           // Enables the Motor Drive A.
 
 motorTimerA1 = 0;                        // Sets the Motor Time A to 0.
 
 timer_a = 0;
 
 while (motorTimerA1 <= (40 * steps))     // The 40 is 40 turns, the steps is number of steps per turn (48 for a 7.5 degree motor).
 {
  if (millis() >= (timer_a + step_timer))// Checks the time from the previous pulse.
  {
   timer_a = millis();                   // Set Timer A to Millisecond Clock

   if (chA >= 2)
   {
    chA = 0;                             // Makes sure the chA toggle is within the range of 0 or 1.
   }
   
   if (chA == 1)
   {
    chA = 2;                             // Sets the ChA to be 0 for Output 0.
    
    bitClear(drive, 6);                  // Clears (makes 0) Drive Bit 6, Clock Output for Motor 1.
   
    bitClear(drive, 0);                  // Clears (makes 0) Drive Output Bit 0. Turns ChA1 LED Off on the Shift Register.
    bitSet(drive, 1);                    // Set (makes 1) Drive Output Bit 1. Turns ChA2 LED On on the Shift Register.
   }  

   if (chA == 0)
   {
    chA = 1;                             // Sets the ChA to be 3 for Output 1.
   
    bitSet(drive, 6);                    // Sets (makes 1) Drive Bit 6, Clock Output for Motor 1.

    bitSet(drive, 0);                    // Set (makes 1) Drive Output Bit 0. Turns ChA1 LED On on the Shift Register.   
    bitClear(drive, 1);                  // Clears (makes 0) Drive Output Bit 1. Turns ChA2 LED Off on the Shift Register.
    }  
  
    shiftDrive();                        // Calls the Shift Drive Out function to set the Shift Registers to drive the LED Indicators.
   }
  if (digitalRead(mode) == LOW)
  {
   motorTimerA1 = 65000;                  // If the Mode switch is set to Standard mode, it sets the For variable to a very high number to break the loop.
  }
  
  motorTimerA1++;                         // Adds 1 on to the motorTimerA variable every cycle
  
  Serial.println(motorTimerA1);
  
 }
 motorTimerA = millis();                 // Sets the Motor A Timeout Timer to current time.
}

I've spotted my error.

I have put the "motorTimerA1++;" outside of the If statement so the While loop counts up instantly.

Very interesting though how the addition of one Serial.println line is enough to slow the whole thing down by around 8 milliseconds every time it ran the println function.

You have declared motorTimerA1 to be a long integer but this statement:

   motorTimerA1 = 65000;

does not set it to 65000. In this case the compiler interprets 65000 as a signed integer and uses the value -535 (if my math is correct). You need to force the compiler to use a long integer like this:

   motorTimerA1 = 65000L;

Pete

This piece of the code does not handle timer overflow correctly:

 while (motorTimerA1 <= (40 * steps))     // The 40 is 40 turns, the steps is number of steps per turn (48 for a 7.5 degree motor).
 {
  if (millis() >= (timer_a + step_timer))// Checks the time from the previous pulse.
  {

That will only affect you if you plan to leave the sketch running for weeks, but you ought to do it correctly anyway.

A subtle change which looks logically equivalent but DOES handle overflow correctly is:

  if (millis() - timer_a >= step_timer)
  {
     timer_a += step_timer; // it doesn't matter in this case, but this method of updating timer_a maintains a consistent step interval whereas the one you used will gradually drift

There are quite a few global variables being used and you don’t show how they’re declared, so it may be you’ve chosen the wrong data types. You really need to post a complete sketch that demonstrates the problem, not just a snippet.

Very interesting though how the addition of one Serial.println line is enough to slow the whole thing down by around 8 milliseconds every time it ran the println function.

you can increase the baudrate up to 115200 or higher. The latter is not supported by the Serial monitor anymore, but it is by most terminal programs.
I have succesfully used 230400, 345600 and 500000 baud.
Other option is to decrease the message length [makes it a bit cryptic] e.g. instead of "Temperature in Celsius: " use can use "Tc:"
Or make the serial println conditional, e.g. every 10th call is really printed or time based

if (pc == 10) // pc print count
{  
  pc = 0; 
  Serial.println("..."); 
}
pc++;

OR 

if (millis() - lastPrint > 1000) // pc print count
{  
  lastPrint + millis(); 
  Serial.println("..."); 
}