Serial Readings affect my stepper's ramp profile

Hi guys,
I have been working with the code below where I am reading the signals coming from two weight scales using a MAX232 to convert RS232 into TTL Logic and the serial hardware pins of the Arduino Mega 2560 (Serial 2 and Serial 3). My code works perfectly for the acquisition part: I can acquire and read the weight of the scales on my Serial Monitor.

What my code does in the void loop is acquiring the weight values of the scales, and once the weight float value of the scale 1 is greater than a certain Desired Weight set initially, running a Stepper Motor with a ramp up profile on the Step Pin. (moveMotor())
Unfortunately, when the condition just mentioned is verified, the ramp up profile generated on the Step Pin has some gaps in between, causing my motor to stall (see picture "Ramp profile while serial reading in void loop").

const byte sleep33=12; // SLEEP signal driver stepper
byte stepPin=35; // STEP Signal 
byte directionPin33=25; // DIRECTION signal 

int incomingByte = 0;   // for incoming serial data

char receivedChar_scale1;
const byte numChars_scale1 = 32 ;
char receivedChars_scale1[numChars_scale1];
char tempChars_scale1[numChars_scale1]; // temporary array for use when parsing
char Weight_scale1[numChars_scale1] = {0};
int integerWeight_scale1 = 0;
float floatWeight_scale1 = 0.0;
float DesiredWeight_scale1 = 50.0;
boolean newData_scale1 = false;
int num_scale1;

char receivedChar_scale2;
const byte numChars_scale2 = 32 ;
char receivedChars_scale2[numChars_scale2];
char tempChars_scale2[numChars_scale2]; // temporary array for use when parsing
char Weight_scale2[numChars_scale2] = {0};
int integerWeight_scale2 = 0;
float floatWeight_scale2 = 0.0;
float DesiredWeight_scale2 = 0.0;
boolean newData_scale2 = false;
int num_scale2;

unsigned long curMicros;
unsigned long prevStepMicros = 0;
unsigned long slowMicrosBetweenSteps = 1667; // microseconds (starting frequency) 
unsigned long fastMicrosBetweenSteps = 462; // constant speed frequency) 
unsigned long stepIntervalMicros;
unsigned long stepAdjustmentMicros;
int numAccelSteps = 100; // number of steps for the acceleration part
int numSteps = 2000; //total number of steps in case you go for a complete trapezoidal profile
int stepsToGo;
unsigned long currentMicroTime=0;

void setup() {
pinMode(directionPin33, OUTPUT);
digitalWrite(directionPin33,HIGH);
pinMode(stepPin, OUTPUT);
pinMode (sleep33, OUTPUT);
digitalWrite(sleep33,LOW); // turning the driver in sleep mode
Serial.begin(9600);
Serial2.begin(9600);
Serial3.begin(9600);

stepAdjustmentMicros = (slowMicrosBetweenSteps - fastMicrosBetweenSteps) / numAccelSteps;
stepIntervalMicros = slowMicrosBetweenSteps;
stepsToGo = numSteps;

}  // end of setup

void loop() {
  
recvWithEndMarker_scale1();
if (newData_scale1 == true) {
    strcpy(tempChars_scale1, receivedChars_scale1);
        // this temporary copy is necessary to protect the original data
        //   because strtok() used in parseData() replaces the commas with 
parseData_scale1();
showParsedData_scale1();
newData_scale1 = false;
}

recvWithEndMarker_scale2();
if (newData_scale2 == true) {
    strcpy(tempChars_scale2, receivedChars_scale2);
        // this temporary copy is necessary to protect the original data
        //   because strtok() used in parseData() replaces the commas with 
parseData_scale2();
showParsedData_scale2();
newData_scale2 = false;
}

if (floatWeight_scale1 >= DesiredWeight_scale1){
   if (currentMicroTime==0) {
   currentMicroTime=micros();
   digitalWrite(sleep33,HIGH); //turning ON the driver
   moveMotor();
   }
   else {
   digitalWrite(sleep33,HIGH); //turning ON the driver
   moveMotor();
   }
}
}

void recvOneChar_scale1() {
    if (Serial2.available() > 0) {
        receivedChar_scale1 = Serial2.read();
        newData_scale1 = true;
    }
}

void recvOneChar_scale2() {
    if (Serial3.available() > 0) {
        receivedChar_scale2 = Serial3.read();
        newData_scale2 = true;
    }
}

void recvWithEndMarker_scale1() {
    static byte ndx_scale1 = 0;
    char endMarker_scale1 = 'n';
    char rc_scale1;
   
    while (Serial2.available() > 0 && newData_scale1 == false) {
        rc_scale1 = Serial2.read();

            if (rc_scale1 != endMarker_scale1) {
                receivedChars_scale1[ndx_scale1] = rc_scale1;
                ndx_scale1++;
                if (ndx_scale1 >= numChars_scale1) {
                    ndx_scale1 = numChars_scale1 - 1;
                }
            }
            else {
                receivedChars_scale1[ndx_scale1] = ''; // terminate the string
                ndx_scale1 = 0;
                newData_scale1 = true;
            }
        }
}

void recvWithEndMarker_scale2() {
    static byte ndx_scale2 = 0;
    char endMarker_scale2 = 'n';
    char rc_scale2;
   
    while (Serial3.available() > 0 && newData_scale2 == false) {
        rc_scale2 = Serial3.read();

            if (rc_scale2 != endMarker_scale2) {
                receivedChars_scale2[ndx_scale2] = rc_scale2;
                ndx_scale2++;
                if (ndx_scale2 >= numChars_scale2) {
                    ndx_scale2 = numChars_scale2 - 1;
                }
            }
            else {
                receivedChars_scale2[ndx_scale2] = ''; // terminate the string
                ndx_scale2 = 0;
                newData_scale2 = true;
            }
        }
}

void showNewData_scale1() {
    if (newData_scale1 == true) {
        Serial.print(receivedChar_scale1);
        newData_scale1 = false;
    }
}

void showNewData_scale2() {
    if (newData_scale2 == true) {
        Serial.print(receivedChar_scale2);
        newData_scale2 = false;
    }
}

void parseData_scale1() {      // split the data into its parts

    char * strtokIndx_scale1; // this is used by strtok() as an index

    strtokIndx_scale1 = strtok(tempChars_scale1," ");      // get the first part - the string
    strcpy(Weight_scale1, strtokIndx_scale1); // copy it to messageFromPC
 
    integerWeight_scale1 = atoi(strtokIndx_scale1);     // convert this part to an integer

    floatWeight_scale1 = atof(strtokIndx_scale1);     // convert this part to a float

}

void parseData_scale2() {      // split the data into its parts

    char * strtokIndx_scale2; // this is used by strtok() as an index

    strtokIndx_scale2 = strtok(tempChars_scale2," ");      // get the first part - the string
    strcpy(Weight_scale2, strtokIndx_scale2); // copy it to messageFromPC
 
    integerWeight_scale2 = atoi(strtokIndx_scale2);     // convert this part to an integer

    floatWeight_scale2 = atof(strtokIndx_scale2);     // convert this part to a float

}

void showParsedData_scale1() {
    Serial.print("Weight Drain: ");
    Serial.println(Weight_scale1);
    Serial.print("Integer Drain: ");
    Serial.println(integerWeight_scale1);
    Serial.print("Float Drain: ");
    Serial.println(floatWeight_scale1);
}

void showParsedData_scale2() {
    Serial.print("Weight Concentrates: ");
    Serial.println(Weight_scale2);
    Serial.print("Integer Concentrates: ");
    Serial.println(integerWeight_scale2);
    Serial.print("Float Concentrates: ");
    Serial.println(floatWeight_scale2);
}

void moveMotor() {
    if (stepsToGo > 0) {
        if (micros() - currentMicroTime - prevStepMicros >= stepIntervalMicros) {
            prevStepMicros = prevStepMicros + stepIntervalMicros;
            singleStep();
            //stepsToGo --;
            if (stepsToGo <= numAccelSteps) {
                if (stepIntervalMicros < slowMicrosBetweenSteps) {
                    stepIntervalMicros = stepIntervalMicros + stepAdjustmentMicros;
                }
            }
            else {
                if (stepIntervalMicros > fastMicrosBetweenSteps) {
                    stepIntervalMicros = stepIntervalMicros - stepAdjustmentMicros;
                }
            }
        }
    }
    else {
//        direction = ! direction;
        //digitalWrite(directionPin, direction);
            // next two lines just for the demo
        delay(2000); 
        Serial.println("Changing direction");
        stepsToGo = numSteps;
        prevStepMicros = micros();
    }
}

void singleStep() {

    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);

}

....Continue

Whereas if I comment the part of the code in the void loop related to the weight scales acquisition (the code below), my ramp up profile works perfectly (i.e. the profile doesn't have any gaps in between, see picture "Ramp profile while serial reading commented in void loop") and after the condition has been met (in this case I replaced the weight if-condition with time greater than 20 seconds) my motor is able to turn properly at the desired speed after a ramp up.

recvWithEndMarker_scale1();
if (newData_scale1 == true) {
    strcpy(tempChars_scale1, receivedChars_scale1);
        // this temporary copy is necessary to protect the original data
        //   because strtok() used in parseData() replaces the commas with 
parseData_scale1();
showParsedData_scale1();
newData_scale1 = false;
}

recvWithEndMarker_scale2();
if (newData_scale2 == true) {
    strcpy(tempChars_scale2, receivedChars_scale2);
        // this temporary copy is necessary to protect the original data
        //   because strtok() used in parseData() replaces the commas with 
parseData_scale2();
showParsedData_scale2();
newData_scale2 = false;
}

My betting is that the serial readings are affecting somehow my void loop slowing it down. I would really appreciate your advices on what is going on there and how could I fix this problem.
By the way, the two weight scales are set to continuous data output mode.

It looks like you're using a modified version of Robin2's tutorial. IIRC though, that code allows you to call your recvWithEndMarker_scale1 repeatedly to build up your strings. Your version won't return until it has a complete string to process.

So before you can move your motor a single step, you must receive a complete string from both scales. And the same thing for the second step. Let the recvWithEndMarker_scale1 functions return if new data is still false.

You might consider increasing the baud rate too.

wildbill:
It looks like you're using a modified version of Robin2's tutorial. IIRC though, that code allows you to call your recvWithEndMarker_scale1 repeatedly to build up your strings. Your version won't return until it has a complete string to process.

So before you can move your motor a single step, you must receive a complete string from both scales. And the same thing for the second step. Let the recvWithEndMarker_scale1 functions return if new data is still false.

You might consider increasing the baud rate too.

you are right. I adapted the code for the acquisition from his tutorial. I got that the problem might have been something like that.

"Let the recvWithEndMarker_scale1 functions return if new data is still false." in this case the scale readings are going to be good and stable as well?

"You might consider increasing the baud rate too." is this the only other way or there is another smarter way to code what I have done so far?

D10S:
you are right. I adapted the code for the acquisition from his tutorial. I got that the problem might have been something like that.

"Let the recvWithEndMarker_scale1 functions return if new data is still false." in this case the scale readings are going to be good and stable as well?

The scale readings will be fine because you have this to check for new data:

  if (newData_scale1 == true)

You may need to be careful after you decide to move the motor because the next data from the scale may not have arrived.

wildbill:
Your version won't return until it has a complete string to process.

Looking at the code in the Original Post I don't see any blocking code.

My guess is that it is all the Serial.print() statements that slow things down

Also, floating point maths is slow on a 16MHz Arduino and should be avoided if at all possible.

...R

Robin2:
Looking at the code in the Original Post I don’t see any blocking code.

Oops - my mistake.

How long is each gap and how often do they occur? For example, if they happen every 1024 microseconds then it is likely to be the millis() interrupt on Timer0.

Robin2:
Looking at the code in the Original Post I don't see any blocking code.

My guess is that it is all the Serial.print() statements that slow things down

Also, floating point maths is slow on a 16MHz Arduino and should be avoided if at all possible.

...R

Do you suggest to remove all the serial print()? Or should I increase the baud rate?
I need the float value for my comparison to be accurate enough.

D10S:
I need the float value for my comparison to be accurate enough.

A scaled fixed point long integer is more accurate than a float.

D10S:
Do you suggest to remove all the serial print()? Or should I increase the baud rate?

Why not both?

Why did you not try those options before replying?

I need the float value for my comparison to be accurate enough.

As in Reply #9

...R