why introducing delay in serial communication helps

i am using Arduino Due to do serial half duplex communication with Reaction Wheel(RW) using RS485.Below is my code.When i press enter the communication initiates.It takes the command from the RWCommand_6000[] array which is defined below.The output is saved in response[] array.Sending command to control my system seems to be easy but receiving the response from the system to arduino is giving the problem.I got around this by introducing a delay of around 1ms but cant figure it out why introducing delay is doing the trick.In the code below, i send the command bytes to RW and at the end of the final bytes the program enters the if() statement which Enables the Receiver to receive the response data to Arduino.Its in the if() statement block where i introduced the delayMicroseconds(1000) before enabling the Receiver.
Any idea why introducing delay is helping in this case?
I am using digitalWrite() to turn the pin HIGH or LOW and i dont like this idea because digitalWrite is slow,in Arduino Due i cant use DDR registor and PORTx to manipulate pins,maybe this is giving me the problem but i am not sure.

#define SerialTXControl  11  // RS485 Direction control

byte RW_response[64];
byte response[50];



void setup() { 
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial2.begin(115200); 

  pinMode(SerialTXControl,OUTPUT);
   
}

void loop() {
  // put your main code here, to run repeatedly:

  char  input = Serial.read();

  if(input==13){ //press enter to initiate serial communication
    
    for (int i=0; i<14; i++) { // the command to RW90 has at most 14 bytes
      byte   RWCommand_6000[] = {0x7e, 0x77, 0x40, 0x00, 0x06, 0x6d, 0x67, 0x00, 0xc3, 0x4f, 0xff, 0x4e, 0xf9, 0x0d};
             
  
 
      digitalWrite(SerialTXControl,HIGH); //turns the Driver pin High to send data
      Serial2.write(RWCommand_6000[i]);
      
      Serial.print(RWCommand_6000[i],HEX); // print the command to monitor for degubbing
      Serial.print(" ");
      
      /******* this block check for the end byte and enables the receiver *******/
      if(i==13){
        Serial.println();
        Serial.print("R: ");

        delayMicroseconds(1000); /* using the delay function seems to establish the two way      
                                                communication */

        digitalWrite(SerialTXControl,LOW); // enables the Receiver pin to get data from RW
        if(Serial2.available()>0){
          for(int j=0;j<12;j++){ /* the response is 12byte long */
            Serial2.readBytes(response,Serial2.available());
            Serial.print(response[j],HEX);
            Serial.print(" ");
            if(j==11){
              Serial.println();
              
            }
          }
        }
      }   
    }
  }
}

Thanks,
Bikash

You MUST use available to check that data is available before attempting to read it.

Mark

 digitalWrite(SerialTXControl,LOW);
        if(Serial2.available()>0){
          for(int j=0;j<12;j++){
            Serial2.readBytes(response,Serial2.available());
            Serial.print(response[j],HEX);
            Serial.print(" ");
            if(j==11){
              Serial.println();
              
            }
          }
        }

@Mark
here the receiver pin is enabled and then used Serial2.available() to check if data is available from Reaction wheel.Sorry if i misunderstood your reply.

Not here

void loop() {
  // put your main code here, to run repeatedly:

  char  input = Serial.read();

Mark

            Serial2.readBytes(response,Serial2.available());

The second argument is the number of bytes that the array can hold. It is NOT the number of bytes to read.

To answer your misguided question, serial data arrives slowly. Using delay() or other things that take time, you allow for more data to arrive before you try to read it. There is only one person on this forum that thinks using delay() is a good idea, with serial communications. The rest of us use packet markers to define when the complete packet has arrived.

The second argument is the number of bytes that the array can hold. It is NOT the number of bytes to read.

From Serial.readBytes() - Arduino Reference

Syntax

Serial.readBytes(buffer, length)

Parameters

buffer: the buffer to store the bytes in (char[] or byte[])
length : the number of bytes to read (int)

i found out that my reaction wheel has a delay of 1ms between taking a command and sending the response back,so the 1ms delay is working with my code though i dont want to use the delay function.Without the delay function the loop bypasses the serial2.available()

if(i==13){
        Serial.println();
        Serial.print("R: ");

        delayMicroseconds(1000); /* using the delay function seems to establish the two way      
                                                communication */

        digitalWrite(SerialTXControl,LOW); // enables the Receiver pin to get data from RW
        if(Serial2.available()>0){
          for(int j=0;j<12;j++){ /* the response is 12byte long */
            Serial2.readBytes(response,Serial2.available());
            Serial.print(response[j],HEX);
            Serial.print(" ");
            if(j==11){
              Serial.println();
              
            }
          }
        }
      }

Bikas

I modified my code to look for packet markers for serial communication (STX is 0x7E and ETX is 0x0D),the previous code was for debugging purpose and was solely used to check if communication was established between Arduino and Reaction Wheel(Astrofein RW90 is used).Some modification still need to be done,for example initially i always gets two null characters whenever i open my terminal.

#define SerialTXControl  11  // RS485 Direction control,SN65HVD33 3.3V RS485 Driver and Receiver http://www.ti.com/lit/ds/symlink/sn65hvd33.pdf

byte RW_response[64];
byte response[50];

void clearInputBuffer() {
   while (Serial2.available() > 0) {    //this function is taken from http://forum.arduino.cc/index.php?topic=288234.15
        Serial2.read();
   }
}

void clearInputSerialBuffer() {
   while (Serial.available() > 0) { 
    Serial.read();   
    }
}

void setup() { 
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial2.begin(115200); 

  pinMode(SerialTXControl,OUTPUT);
   
}

void loop() {
  // put your main code here, to run repeatedly:

  char  input = Serial.read();

  if(input==13){ //press enter to initiate serial communication
    
    for (int i=0; i<14; i++) { // the command to RW90 has at most 14 bytes
      byte   RWCommand_6000[] = {0x7e, 0x77, 0x40, 0x00, 0x06, 0x6d, 0x67, 0x00, 0xc3, 0x4f, 0xff, 0x4e, 0xf9, 0x0d};
             
  
 
      digitalWrite(SerialTXControl,HIGH); //turns the Driver pin High to send data
      Serial2.write(RWCommand_6000[i]);
      
      Serial.print(RWCommand_6000[i],HEX); // print the command to monitor for degubbing
      Serial.print(" ");
      
      /******* this block check for the end byte and enables the receiver *******/
      if(RWCommand_6000[i]==0x0d){
        Serial.println();
        Serial.print("R: ");

        delayMicroseconds(1000); /* using the delay function seems to establish the two way      
                                                communication */

        digitalWrite(SerialTXControl,LOW); // enables the Receiver pin to get data from RW
        if(Serial2.available()>0){
            Serial2.readBytes(response,Serial2.available());
            Serial.print(response[0],HEX);
            Serial.print(" ");
            if(response[0]==0x0d){
              Serial.println();
              digitalWrite(SerialTXControl_RW,HIGH); /* when the end byte is received the receiver is disabled */
              
            }  clearInputBuffer();     
        }
      } clearInputSerialBuffer(); /* clearing the Serial buffer after 0x0d is read */
    }
  }
}

Bikas

PaulS:
There is only one person on this forum that thinks using delay() is a good idea, with serial communications.

And to put that into context, the forum has over 300,000 members. :slight_smile:

There is only one person on this forum that thinks using delay() is a good idea, with serial communications.

And to put that into context, the forum has over 300,000 members. :slight_smile:

Perhaps you can show where that person ever stated or said "delay() is a good idea". If you can't, then perhaps you are just giving somebody a "big finish". :wink: Backing up others sketchy statements is sometimes risky.

The person I am thinking of regularly recommends code like this:

 while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

You don't need slow looping to allow the buffer to fill - that is just nonsense. You need to code correctly. For one thing, that "slow looping" is totally dependent on the baud rate. It would have to be adjusted for every baud rate. Too short and you lose something. Too long and you process too slowly. And if you process too slowly you might miss incoming data as you gradually fall behind the incoming data stream.

Anyway, I've given up arguing about it, although I notice PaulS hasn't forgotten.

The person I am thinking of regularly recommends code like this:

Can you show where the code was "recommended"? The code has been posted as a simple example of collecting a string of individual arriving characters into a String for further processing. This is in comparison to a forum member ("snippets-r-us") who in more than 50,000+ post has never been seen to post complete code that will even compile muss less run (well, maybe twice).

Anyway, I've given up arguing about it, although I notice PaulS hasn't forgotten

You seem to jump right in with PaulS's ever present embarrassing whining and bashing of forum members, which seems strange for somebody listed as a forum "moderator". It is what it is. :roll_eyes:

Perhaps I better leave it, as this is getting a bit personal.

I should just point out though that I own the snippets-r-us.com domain. Not any other person.

I never saw any example of the use of such delays in processing a serial stream before I saw it here. It makes no sense, unless it is a kludge to hide some other problem.

I have a ton of sketches that use serial (sometimes 2) and I've never needed any delays. Come on, this stuff has been going on since 1955. To be misguided about such a simple thing now is just embarrassing.

I can see how there might be reasons to delay the opening of a serial device, but reading characters, no way.

bikas:
i am using Arduino Due to do serial half duplex communication with Reaction Wheel(RW) using RS485.Below is my code.When i press enter the communication initiates.It takes the command from the RWCommand_6000[] array which is defined below.The output is saved in response[] array.Sending command to control my system seems to be easy but receiving the response from the system to arduino is giving the problem.I got around this by introducing a delay of around 1ms but cant figure it out why introducing delay is doing the trick.In the code below, i send the command bytes to RW and at the end of the final bytes the program enters the if() statement which Enables the Receiver to receive the response data to Arduino.Its in the if() statement block where i introduced the delayMicroseconds(1000) before enabling the Receiver.
Any idea why introducing delay is helping in this case?
I am using digitalWrite() to turn the pin HIGH or LOW and i dont like this idea because digitalWrite is slow,in Arduino Due i cant use DDR registor and PORTx to manipulate pins,maybe this is giving me the problem but i am not sure.

#define SerialTXControl  11  // RS485 Direction control

byte RW_response[64];
byte response[50];

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial2.begin(115200);

pinMode(SerialTXControl,OUTPUT);
 
}

void loop() {
  // put your main code here, to run repeatedly:

char  input = Serial.read();

if(input==13){ //press enter to initiate serial communication
   
    for (int i=0; i<14; i++) { // the command to RW90 has at most 14 bytes
      byte  RWCommand_6000[] = {0x7e, 0x77, 0x40, 0x00, 0x06, 0x6d, 0x67, 0x00, 0xc3, 0x4f, 0xff, 0x4e, 0xf9, 0x0d};

digitalWrite(SerialTXControl,HIGH); //turns the Driver pin High to send data
      Serial2.write(RWCommand_6000[i]);
     
      Serial.print(RWCommand_6000[i],HEX); // print the command to monitor for degubbing
      Serial.print(" ");
     
      /******* this block check for the end byte and enables the receiver *******/
      if(i==13){
        Serial.println();
        Serial.print("R: ");

delayMicroseconds(1000); /* using the delay function seems to establish the two way     
                                                communication */

digitalWrite(SerialTXControl,LOW); // enables the Receiver pin to get data from RW
        if(Serial2.available()>0){
          for(int j=0;j<12;j++){ /* the response is 12byte long */
            Serial2.readBytes(response,Serial2.available());
            Serial.print(response[j],HEX);
            Serial.print(" ");
            if(j==11){
              Serial.println();
             
            }
          }
        }
      } 
    }
  }
}




Thanks,
Bikash

Any idea why introducing delay is helping in this case?

You delay has little or nothing to do with what you are observing.

Two reasons:
You are reading a data which is obviously not there and than you compare the value read to 13 and just continue to read ( loop ) until it is 13.

If you insist in using delay, which is not necessary, you could add it when value read is not 13 ( if() else() ).

The other strange part is - you detect the value == 13 and than check if Serial.available to read the rest of the message.

I am sure if you detect your control characters using Serial.available instead of the current logic( read nothing) it will work better.

@Vaclav Thanks for the suggestion.Will post my progress when done.

The other strange part is - you detect the value == 13 and than check if Serial.available to read the rest of the message.

I am using only Serial2.available() to read messages from Reaction Wheel.Serial port is left to initiate communication and is not used again.
value == 13 is the one which is read from Serial port while i==13 later on the loop is the value from the array declared in the sketch.

bikas:
@Vaclav Thanks for the suggestion.Will post my progress when done.

The other strange part is - you detect the value == 13 and than check if Serial.available to read the rest of the message.

I am using only Serial2.available() to read messages from Reaction Wheel.Serial port is left to initiate communication and is not used again.
value == 13 is the one which is read from Serial port while i==13 later on the loop is the value from the array declared in the sketch.

Sorry, I missed the i ==13 and using two Serial versions.
I should have just answered the delay question only.