Question

I'm sampling at high frequencies and need to transmit the 10-bit ADC value via UART out of my Arduino.

By default, it uses a byte per character. So if doing an analogRead would yield the value of "612", it would send via UART "6" as one byte, "1" as one byte, "2" as one byte, and the line terminator as the last byte.

Given that my sampling rate is truncated by this communication, it's important that it's as efficient and uniform as possible, so I'm trying to force it to use two bytes to transmit that data, doesn't matter what the data actual is (by default it would use three bytes to transmit "23", four bytes to transmit "883" and five bytes to transmit "1001").

Currently, I'm doing something like this, which is the best way I've found:

int a = 600; //Just an example
char high = (char)highByte(a);
char low = (char)lowByte(a);
Serial.print(high);
Serial.println(low);

Currently this uses three bytes (including \n) regardless of the value. Is there an even more efficient method?

Just printing it with something like

Serial.print(foo, BIN);

Doesn't work at all. It actually uses one byte per every single bit of the binary representation of foo, which is quite silly.

Was it helpful?

Solution

I might be missing something, but why don't you use Serial.write(byte)?

You can use a methode like this one:

void writeIntAsBinary(int value){
    Serial.write(lowByte(value));
    Serial.write(highByte(value));
}

what are you planning to do with the data on your computer?

OTHER TIPS

If you're sending binary data over a serial line, you really shouldn't confuse everything by using a text-style linefeed separator.

On the other hand, it's kind of hard (for the other end) to know which byte is which, without some kind of synchronization help.

But, since you only have 10 bits of payload, but send 16 bits of data, you can "do a UTF-8" and use a free bit to signal "start of value". This will require using only 7 bits of each 8-bit byte for your payload, but that's fine since 7 + 7 = 14 which is way more than 10. We can let the 8th bit mean "this is the high byte of a new pair of bytes":

const int a = 600;
const unsigned char high = ((a >> 7) & 0x7f) | 0x80;
const unsigned char low  = (a & 0x7f);

Serial.print(high);
Serial.print(low);

In the above, the two bytes transmitted will be:

high == ((600 >> 7) & 0x7f) | 0x80 == 4 | 0x80 == 0x84
low  == (600 & 0x7f)               == 88       == 0x58

The receiver will have to do the above in reverse:

const int value = ((high & 0x7f) << 7) | low;

This should work, and uses the most-significant bit of the high byte, which is sent first, to signify that that is indeed the high byte. The low byte will never have the MSB set.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top