1

I have an arduino mega connected to a light sensor that reads the status of a machine's indicator light. I have a C++ application that controls the machine, and I would like the arduino to send the application the status of the indicator light in real-time so that the application can control the machine.

Essentially, I just want to constantly send a "1" or "0" through the serial monitor to a C++ application. What would the best way to do this be? I am confused as to the difference between serial.Write() and serial.Print(), what is more optimal for this application?

4
  • what amount of delay is acceptable?
    – jsotola
    Jun 21, 2023 at 1:13
  • 2
    I just want to constantly send a "1" or "0" ... it makes more sense to send data when transition occurs and send a heartbeat data the rest of the time
    – jsotola
    Jun 21, 2023 at 1:16
  • 1
    you have to define best before the question an be answered
    – jsotola
    Jun 21, 2023 at 2:39
  • Since "optimal" is already a superlative, there is no "more optimal". :-D Jun 21, 2023 at 6:19

3 Answers 3

4

It might sound like a good idea to send "0" or "1" in real time, for a fast response, but that might be counter-productive.

For one thing, you are spamming serial data which could slow down the receiving machine slightly. For another, if the sampling rate is faster than the baud rate, then the sending buffer will fill up, and the data being sent will be "old". Say the buffer size is 64 bytes, then the data being sent (and therefore received by windows) could be 64 bytes ago, and not real time.

I would suggest sending a "1" (with Print rather than Write) when the light is on, and then nothing until you detect that the light is off, then send a "0". And ditto for the transition back to being on. Thus the serial data flow merely indicates transitions and not the current state. This greatly reduces the amount of data, and makes it much less likely you will lose some or it will be out of date.

And just in case, send the current state (0 or 1) every second or so, just in case the listening end has only just been turned on.

1
  • That makes sense, I only care when the light turns on so I only need to tell the application that the light is on, the default is that the light is off. Thanks!
    – Max Bluhm
    Jun 21, 2023 at 14:11
4

I agree with both previous answers. Nick Gammon gives excellent advise on how to handle this situation, and Rohit Gupta gives you the gist of write() v.s. print(). I would like to elaborate on this write() / print() distinction though.

These methods of the Arduino API can be confusing, as they have many different signatures.

write()

Let's look at write() first, as it is the simplest of them:

size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);

These are meant to send a single byte and an array of bytes respectively. You can send arbitrary bytes, which is usually termed “binary data”. Note that any data, including text, is binary data: the term binary here simply means that there is no restriction on the bytes you can send.

size_t write(const char *buffer, size_t size);

This is the same as the previous one, for the case when the buffer is of type “array of char”. It can still send arbitrary data.

size_t write(const char *str);

This is a version for sending C-strings, i.e. NUL-terminated buffers. This one cannot send a zero byte, as that byte is interpreted as a string terminator. It is thus inappropriate for sending binary (in the sense of “arbitrary”) data. For this reason, I believe the inclusion of this overload is a mistake made by the designers of the API, and I would avoid it in preference of print() which, for this type of argument, does exactly the same thing.

Note that, in every instance, write() takes the data you give it and sends it as-is. There is no attempt at formatting it in any manner.

print()

As stated by Rohit Gupta, print() is meant for sending text. If you have some data to send that is text to start with (like a literal string), print() sends it as-is, and is thus quite similar to write(). This is the case for the following overloads:

size_t print(const String &);  // sends a String object
size_t print(const char[]);    // sends a C-string
size_t print(char);            // sends a single character

Then you have some overloads for printing various kinds of numbers. All of these involve a binary-to-text conversion. The two remaining overloads, which involve __FlashStringHelper and Printable, are a bit too technical and I will not discuss them here.

Comparison

All the statements below do the same thing, they send "A" through the serial port:

Serial.write(65);        // sends a byte with binary value 65
Serial.write('A');       // the ASCII code of 'A' is 65
Serial.print('A');       // a char is print()ed by sending it as-is
Serial.print(char(65));  // 'A' is a shortcut for char(65)
Serial.print("A");       // a one-character string

All the statements below send "65" through the serial port:

Serial.write(54); Serial.write(53);    // send two binary values
Serial.write('6'); Serial.write('5');  // ASCII('6') = 54...
Serial.write("65");       // sends text in a pre-formatted buffer
Serial.print("65");       // same
Serial.print(65);         // print() does the number-to-text conversion
Serial.print(int('A'));   // same

As a general rule, I recommend to always use print() for sending text, and use write() only for sending data that is not (reliably known to be) text.

1
  • Yes, excellent. I struggle to explain exactly the difference between binary and non-binary. For example "00110001" is arguably binary, however it is an ASCII string with binary digits in it. However (in C++) 0b00110001 is binary in a different sense.
    – Nick Gammon
    Jun 21, 2023 at 9:00
2

Serial.write sends binary data, whereas Serial.print sends ASCII data. So it depends on whether you want Windows to receive ASCII 0 and 1 or binary 0 and 1.

I would suggest that you use print and send ASCII data.

Your Answer

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

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