1

In the IRremote library, IR signals are decoded and held in results.value. My project uses the NEC protocol which is 32 bits, so the IR code will always be 4 bytes.

uint32_t dCodedIR;
//
//  code exists here that we can ignore
//
dCodedIR = results.value

This decoded signal is then sent out the serial port to a second MCU which will be waiting for incoming data:

while (!Serial.available())  {
}

After this, there will ideally be a complete code of 4 bytes waiting in the FIFO. I will allow for times when < 4 bytes are ready (check for more, timed out? NO:loop YES:reset), but this should rarely happen. So I want to optimize the sending code so that the receiver has the best chance of avoiding split groups. In theory, is it better to write as single bytes and repeat 4 times, or make a 4-byte array to send once?

Serial.write(dCodedIR & 255);
Serial.write((dCodedIR >> 8) & 255);
Serial.write((dCodedIR >> 16) & 255);
Serial.write((dCodedIR >> 24) & 255);

or

byte sendBuf[4];
//
// 
sendBuf[3] = (byte) dCodedIR & 255;
sendBuf[2] = (byte) (dCodedIR >> 8) & 255;
sendBuf[1] = (byte) (dCodedIR >> 16) & 255;
sendBuf[0] = (byte) (dCodedIR >> 24) & 255;
Serial.write(sendBuf, 4);

(Since there will be plenty of storage space for the code, with performance being the priority, I decided against using for loops because updating an index, testing it, and looping would seem to add overhead.)

1 Answer 1

2

Unless you are using very high baud rates, (at least higher than 115.2 kb/s), it should make no difference.

The reason is that either version of your code should run faster than the UART. Serial.write() doesn't wait for the bytes to be sent out the wire. Instead, it just stores those bytes in a ring buffer that belongs to the HardwareSerial library. When the UART is ready to accept an outbound byte, it triggers an interrupt. The corresponding ISR takes one byte from the ring buffer and handles it to the UART. Since the UART itself is double-buffered, all this happens while the previous byte is being sent.

The end result is that, with either version of your code, you end up with a continuous byte stream. The start bit of the second byte comes right after the stop bit of the first byte, and so on. The stream doesn't pause until the full message is sent. That is, unless you have somewhere in your program overly long critical sections that can impose excessive latency to the whole process.

Side note: if your MCU is little endian (most Arduinos are), you could also avoid one copy and just do

Serial.write((byte *) &dCodedIR, 4);

Addendum: The details may depend on the MCU you are using. On an Uno, or similar AVR-based boards, the UART has no knowledge of the software ring buffer. It rises the UDRE0 (data register empty) flag whenever it is ready to accept an outbound byte in its sender data register. When there is data in the buffer, the software enables the data register empty interrupt, which is tied to the UDRE0 flag.

1
  • Re the interrupt handling: see expanded answer. Re Serial.available(): I don't know how the timing of your receiving code works. Jun 15, 2019 at 11:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.