Arduino Lag?

It’s my first time posting here in the forum so please bear with me and feel free to correct me! Thanks!

I have a project wherein i am using a temp sensor, 2 xbee talking, and a motor. I have configured the 2 xbees to talk to each other and successfully send readings to the xbee coordinator. But when i combine the code for my motor to run using those readings that i get, i am having a delay of about 50 seconds! my delay for sending readings is 3000 ms.

Here is my code:

#include <SoftwareSerial.h>
SoftwareSerial XBee(10, 11); // RX, TX

#define relay 4
int stepPin = 5;
int dirPin = 6;
int enblPin = 7;
long Distance = 0;

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

int dataNumber = 0;             // new for this version

void setup() {
  XBee.begin(9600); //SERIALS
  Serial.begin(9600);
  Serial.println("<Arduino is ready>");
  pinMode(relay, OUTPUT); //RELAY SERIAL
  digitalWrite(relay, HIGH);
  pinMode (stepPin, OUTPUT); //MOTOR SERIAL
  pinMode (dirPin, OUTPUT);
  pinMode (enblPin, OUTPUT);
  digitalWrite(stepPin, LOW);
  digitalWrite(dirPin, LOW);
  digitalWrite(enblPin, HIGH);
}

void loop() {
  recvWithEndMarker();
  showNewNumber();
  runMotor();
  
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  if (XBee.available() > 0) {
    rc = XBee.read();

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void showNewNumber() {
  if (newData == true) {
    dataNumber = 0;             // new for this version
    dataNumber = atoi(receivedChars);   // new for this version
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    Serial.print("Data as Number ... ");    // new for this version
    Serial.println(dataNumber);     // new for this version
    newData = false;
  }
}
  void runMotor() {
    
    if (dataNumber >= 200 )
    {
      digitalWrite(relay, LOW);
    }

    else
    {
      digitalWrite(relay, HIGH);
    }

    {
      //delay(2000);
      //digitalWrite(relay, LOW);  // Turn Relay ON
      //Serial.println("Relay is ON");

    }
    {
      for (long x = 0; x < 38400; x++)
      {
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(100);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(100);
        //Distance = Distance + 1;
      }
    }

    // first rotation COUNTER CLOCKWISE
    if (Distance == 38400);

    { if
      (digitalRead(dirPin) == LOW)
      {
        digitalWrite(dirPin, HIGH);
      }

      else
      {
        digitalWrite(dirPin, LOW);
      }

      delay(2000);
    }

    {
      //digitalWrite(relay, HIGH);  // Turn Relay OFF
      //Serial.println("Relay is OFF");
     // delay(2000);
    }

  }

i have converted my string number to int so i can use it in an if else statement. without the code of motor, the receiving of readings have no problem. Thanks!

  • andrea

Not done much with Xbee but don’t you have to flush the buffer or something to get it to send. My understanding is that it will only send automatically when the buffer is full. That would explain the long delay.

Your for-loop causes a delay of 38400 x 200 microseconds; that's roughly 8 seconds.

Next you add a delay of 2 seconds.

So 10 seconds can easily be explained.

I don't know enough about steppers to be able to advise how to solve the first one.

I'd say that sterretje has already lead you in the right direction.

Assuming that the number you are sending is multiple characters, consider this.

You run through a continuous Loop(). Each time through the Loop, you call recvWithEndMarker() which will receive at most one character. If a character is received, and it happens to be the expected endMarker, the flag newData will be set to true.

Each time through the Loop, you also call showNewNumber(). Most of the time, the function will do nothing because newData is not true. (Why don't you just call showNewNumber() when you actually receive the endMarker?)

Finally, each time through the Loop, you call runMotor(). As sterretje already pointed out, this causes about a ten second delay EACH TIME THROUGH THE LOOP.

If the numbers you are sending are four Digits Long, plus the Terminator = 5. 5 x 10 seconds = the fifty second lag you are experiencing.

You really Need to clean up the code. Remove the extraneous { and } and think about what you are wanting to do when. I suspect that run Motor should only be called once AFTER a new number has been completely received?

JaBa:
(Why don't you just call showNewNumber() when you actually receive the endMarker?)

He is doing it following my demo Serial Input Basics and I wrote it that way to keep the code in loop() as clean as possible. It's not going to have any appreciable effect on timing.

Finally, each time through the Loop, you call runMotor(). As sterretje already pointed out, this causes about a ten second delay EACH TIME THROUGH THE LOOP.

I agree that the runMotor() function is all wrong. It should just move one step each time it is called, and maybe not even that.

@autogation17, have a look at the second (non-blocking) example in this Simple Stepper Code

...R
Stepper Motor Basics

Hello! Thank you guys for replying to my post. im sorry it took me a while to reply because i have been busy with school.

Now i have an idea for the delay.

JaBa:
I suspect that run Motor should only be called once AFTER a new number has been completely received?

@JaBa

I have no idea how to do this since i only followed the code of Robin2. Any idea to share? Thanks!

Robin2:
I agree that the runMotor() function is all wrong. It should just move one step each time it is called, and maybe not even that.

Robin2

I wanted to run my motor in 1 full revolution if it received the reading from my sensor. it is a 3 digit reading so far.

And is it possible in your code that i can receive those readings at the same time not one by one each number? Like i will be receiving 123 not 1 then 2 then 3 then show the reading 123. Or would you please enlighten me on how to receive first those readings then after receiving all numbers, the motor code will run. Sorry im really new. Thanks!

Thank you again guys. Really appreciate your time :smiley:

-andrea

  if (Distance == 38400);Oops

autogation17:
And is it possible in your code that i can receive those readings at the same time not one by one each number? Like i will be receiving 123 not 1 then 2 then 3 then show the reading 123.

Serial sends characters one at a time - that is what serial means.

If you look at my Serial examples nothing happens until the whole message is received and the the variable newData is set to true. That should be the signal for your system to make the motor move.

If your function to move the motor moves it one step at a time you can easily arrange for loop() to count down from the number that is received until it gets to 0.

Something like

void loop() {
   recvWithEndMarker();
   if (newData == true) {
      numSteps = atoi(receivedChars);
       newData = false;
   }
   if (numSteps > 0) {
     moveOneStep();
   }
}

Note that a step may not happen every time moveOneStep() is called because that would probably be too fast. So the moveOneStep() function should reduce the value of numSteps every time a step is taken.

...R