0

I have to reproduce a signal (of 6 UART frames) which have 950 µs delay between each of the frames. Than, a delay of 37ms at the end of those frames.

Everything going right except the delay between each frame...The baud rate is at 9600.

Here is my current code :

  Serial1.write(sw_binary_train_1);
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_2);
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_3);
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_4);
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_5);
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_6);
  delay(37);
  • 2
    Is "Serial1" a software-serial? Potentially the timing may be more accurate using hardware serial. Also you may check if making the delay longer or shorter works. Usually, the receiving end would have some kind of 'deadzone' (that it should be between 900-950uS) and with the value of 950uS you may just overshoot that at some moments). Also, you should try to put "Serial1.flush();" to make sure that all bytes are sent (and not only placed in the queue). – Paul Feb 26 '19 at 14:09
  • No, I'm on the Arduino Micro. Ok shoud I use delay(1) instead of delayMicroseconds(950) ? Between each frames or at the end of all frames ? – Martin.G Feb 26 '19 at 14:11
  • After few more tests, for a delay of 950µs i have to set delayMicroseconds(1900)...A bit strange but it works ;) ! – Martin.G Feb 26 '19 at 20:24
2

It's not strange at all. Serial doesn't block while it sends. When you call write that pushes the byte into the send buffer and that's all. Then the code moves on to the next instruction, the delay(950) and during that time the serial data is actually being sent. It takes about 1 millisecond for that to happen.

This solution works as long as the send buffer doesn't have anything else in it that's slowing you down and as long as you don't change the baud rate. If either of those things happen then you need to recalculate that time.

A better solution would be:

  Serial1.write(sw_binary_train_1);
  Serial1.flush();
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_2);
  Serial1.flush();
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_3);
  Serial1.flush();
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_4);
  Serial1.flush();
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_5);
  Serial1.flush();
  delayMicroseconds(950);
  Serial1.write(sw_binary_train_6);
  Serial1.flush();
  delay(37);

The flush blocks until the send buffer is empty again. That way you don't have to account for that time and all you need the delay for is the time between transmissions.

Even better would be if those things were in an array so you didn't have to keep repeating yourself. Anytime you catch yourself putting numbers on variable names what you really want is an array so that you can use those numbers in the program:

for (int i=0; i<6; i++){
  Serial1.write(sw_binary_train[i]);
  Serial1.flush();
  delayMicroseconds(950);
}
delay(37)

looks much better.

| improve this answer | |
1

set delayMicroseconds(1900) do a delay of 950µs between each frames...Strange but works !

| improve this answer | |
  • Good to hear you've found a solution, potentially you still may want to look at serial.flush(); (and then delay). But if the other option works for you, it may just be OK. – Paul Feb 27 '19 at 0:05
  • 2
    The delayMicroseconds() is actually not between frames. It is more of less the time for the frame plus the 950 us extra space. The extra 1000 us is the time of the USART ISR to push the character into the output hardware buffer plus the time for the 1+8+1 bits, which happens to be approx. 1 ms @ 9600 bps. The Serial.write() is not synchronous for a hardware USART. – Mikael Patel Mar 29 '19 at 0:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.