1

I have been trying to print the letter µ on the Serial Monitor of Arduino IDE but I failed to do so. Is there any way to print µ or any other Non ASCII characters such as Ó,ß,Ô,Ò,õ,Õ,þ, etc using Serial.print()?

7

Most of what follows has already been covered in previous answers. I am posting this nevertheless because I feel no answer so far makes the whole story clear enough. Let me break down the question into two sub-questions.

1. How can I get non-ASCII characters correctly print on the serial monitor?

The answer is simply send them as UTF-8.

That's really all there is to it. The serial monitor expects you to send UTF-8, and it will print the characters correctly only if you use this encoding. But that brings the second question:

2. How can I get the characters as UTF-8 in my Arduino program?

Here you have several options:

Option 1: encode them yourself

For example, the Greek letter “μ” (U+03BC) in UTF-8 is (0xce 0xbc). You can send those bytes explicitly, like

Serial.write(0xce);
Serial.write(0xbc);

or, more comfortably, like

Serial.print("\xce\xbc");

The second syntax is more convenient because it allows the character to be embedded within a longer string.

Option 2: let the Arduino IDE encode them

If you can get the characters in the IDE's editor window, either with an appropriate keyboard layout or by copying and pasting from another application, then you can use them as is in the string:

Serial.print("μ");

The editor will save the source code as UTF-8, and those UTF-8 bytes will go undisturbed from the source file to the compiled program, to the Arduino memory, to the serial port, and finally to the serial monitor.

This option is the best for readability. However, it is somewhat fragile: if the source code ever gets re-encoded (e-mail clients and servers sometimes do that), then the resulting program will not work as expected.

Options 3: let the compiler encode them

You can ask the compiler to do the UTF-8 encoding for you with the syntax

Serial.print(u8"\u03bc");

Here, the escape sequence \u03bc is a way to represent the Unicode character U+03BC (i.e. “μ”), and the u8 prefix means that you want the string as a byte array encoded in UTF-8.

Note that, in practice, the u8 prefix is not needed, as the gcc compiler assumes UTF-8 by default. I would keep the prefix anyway because it doesn't hurt to make the encoding explicit, and it may avoid angering some language lawyer...

Note also that the syntax above only works for characters U+0000 through U+FFFF, i.e. the basic multilingual plane. For other Unicode characters, you have to use the syntax \U + 8 hex digits. For example, the character “😎” (U+1F60E: smiling face with sunglasses) can be printed with:

Serial.print(u8"\U0001f60e");

Clarification about UTF-16: A common misconception has it that with \u you write the characters as UTF-16 code units, and with \U you write UTF-32 code units. But it is incorrect: both syntaxes are used to describe a single character (technically, a code point), irrespective of the encoding. Since the UTF-16 encoding for “😎” is (0xd83d 0xde0e), one could be tempted to write

// Write as UTF-16 code units in the source code.
Serial.print("\ud83d\ude0e");  // WRONG

but then the compiler rightfully complains

error: \ud83d is not a valid universal character
error: \ude0e is not a valid universal character

So forget about UTF-16. There is no UTF-16 involved anywhere, except in the internal representation used by a Java widget used to implement the serial monitor, which is a completely irrelevant implementation detail.

1

The Serial Monitor uses Unicode, so sending characters in that format is possible. The UTF-16 code for µ is 03BC, and you can send it by prepending \u:

Serial.print("\u03BC");

The actual stream of transformations is you provide Unicode (essentially UTF-16) in your string. C++ then converts that into a stream of 8-bit characters in UTF-8 format, which is then sent down the serial connection. Java then receives those and interprets them as UTF-8, recombining them back into the original UTF-16 characters for display in the JTextArea that comprises the Serial Monitor in the Arduino IDE.

This complex transformation is done because:

  • UTF-8 is easier to stream over an 8-bit data link, but is very hard to work with in a program (because of variable-length byte sequences), and
  • UTF-16 is hard to stream (and breaks ASCII compatibility) but is far easier to work with programmatically (since it is just fixed size 16-bit characters).

So your 0x03BC gets transformed into 0xCE,0xBC which is the UTF-8 representation of the Unicode character 0x03BC.

  • Comments are not for extended discussion; this conversation has been moved to chat. – Majenko Aug 9 '18 at 0:07
0

It depends on your operating system, the arduino version and perhaps even on the selected board.

You have selected a weird character, because there are two versions: the micro µ and the mu μ.
See: https://en.wikipedia.org/wiki/Mu_(letter) and https://en.wikipedia.org/wiki/Micro-. They are not the same.

In linux with the Arduino 1.8.5 and Arduino Uno board, everything supports UTF-8 (the Arduino ide, the serial monitor and the ino file).

To test it, I have written the micro character with AltGr+m in the sketch. It is stored in the ino file as C2 B5, which is UTF-8. It shows in the serial monitor as µ.

With gtkterm, it shows as a µ, and in hexadecimal and it shows C2 B5. That confirms that everything is UTF-8 in linux with Arduino version 1.8.5.

The Unicode "\u03BC" shows a µ in the serial monitor. It is stored in the ino file as 5C 75 30 33 42 43. That is not UTF-8 and not UTF-16, but ASCII for the characters "\u03BC". That is okay, since that is what is typed in the sketch. With gtkterm it shows a µ and CE BC in hexadecimal mode. The CE BC is UTF-8 for mu.

That means the Unicode is translated to UTF-8. Perhaps the compiler translates it to UTF-8?

These are the only tests that I did. It is just a very small part of all possibilities.

Conclusion:
Try to type µ (mu or micro) in the Arduino ide editor.
Using AltGr+m will only work if you have selected a certain keyboard settings. Perhaps you can copy the character from the Wikipedia page.
Using Unicode "\u03BC" seems to be possible.

[ADDED]
The internal format of text in Java was UTF-16, but only a fixed two byte format, not the four bytes. It was therefor only a subset of the Unicode characters. The newest Java version supports the real UTF-16 format for user strings, and thus supports all the Unicode characters.
The data that is stored to a ino file and the data that is transmitted to the serial monitor can be ASCII for normal characters with the addition of UTF-8. Most special characters that I use require two bytes in the UTF-8 format.
For Majenko: look at the binary data of a ino file and the binairy serial data. It is not a fixed two byte per character, but just one byte for normal characters.
I still don't know who translates the Unicode description of a character to UTF-8. It would be indeed weird if the compiler did that, so somewhere Java might automatically translate that.

  • It depends on none of those things. It depends purely on what is receiving the raw bytes as to what you place in your sketch. Since that is Java, and Java use 16 bit UTF-16 (regardless of operating system) you embed 16 bit UTF-16 codes in your strings to display things in your serial monitor. If you are sending to something else then you embed the correct codes for whatever you are sending to. But since this is the serial monitor then it is UTF-16 and will always be UTF-16. – Majenko Aug 6 '18 at 23:56
  • 1
    @Majenko , I think you need a night sleep and have a look at it again. In the past the ino file stored UTF-8 characters but the serial monitor did not accept them. The arduino version does matter. In the past there were a number of differences with UTF-8 in Windows and linux. – Jot Aug 6 '18 at 23:58
  • No one cares about UTF-8. Only UTF-16. – Majenko Aug 6 '18 at 23:59
  • And saving UTF-8 in the ino file has nothing to do with sending UTF-16 to the serial monitor. – Majenko Aug 7 '18 at 0:01

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.