user68546: When reading and writing with a python serial port connection to arduino, if I don't use latin-1 ('ISO-8859-1'), the results are not as expected. Like if I have
int outP = 5;
//...
int outV = Serial.read();
analogWrite(outP, outV);

While with python I have
serial_port.write(chr(255).encode())

I read 3.78 V from the pin, whereas if I use
serial_port.write(chr(255).encode(encoding = 'latin-1'))

I get 5.04 V. I have read latin-1 and utf-8 don't always match, but is there something about arduino that requires using latin-1? Of course, these return different values when testing each encoding, using 255 gives b'\xc3\xbf' (from 'Ã¿') with utf-8 or b'\xff' from ('ÿ') with latin-1, but why does arduino work with latin-1?
FYI other options that work are
v = 255

serial_port.write(v.to_bytes(1, byteorder = 'big'))

serial_port.write(bytes[v])



user70020: 
but is there something about arduino that requires using latin-1?

No, not really.
What it comes down to is that Serial.read() reads bytes, irrespective of whatever encoding they may be being used with.  ISO-8859 only encodes character code points in the 0-255 range, so when you choose a 0-255 code point and send it as ISO-8859, it gets sent as 1 byte, which is how you're code has been written to receive it.
A 255 code point as utf-8 would require multiple bytes to encode and so would result in multiple Serial.read() calls for a given value.
If you open a python3 REPL and put chr(255).encode() or more explicitly chr(255).encode('utf-8') you will see it results in b'\xc3\xbf'.  So on the Arduino side you will see this as two separate Serial.read() results, 0xC3 and 0xBF.
When you're just taking in strings and UTF-8 and splatting them out via Serial.println(), the Arduino is blissfully unaware of that they're UTF-8 and not ISO-8859.  Really you could use any encoding you wanted, the the caveat being that if you're using c-strings to store them, the encoding would need to be one that doens't allow for a single null byte to be in the middle of the string.

You may want to look into using struct.pack rather than cobbling together python bytestrings with sequences of chr() and .encode(whatever). struct.pack will also result in a bytestring, but it's more purpose built for doing this.
You can import struct and then struct.pack('B', 255) will result in b'\xff same as chr(255).encode('iso8859-1'), but at least expresses intent.  'B' here signifies an unsigned char range, you'll find the format specifiers in the documentation. You'll get a greater benefit when you begin using multiple fields where struct.pack will be a lot less unwieldy than the chr and encode and string concatenation.

68546: <p>When reading and writing with a python serial port connection to arduino, if I don't use latin-1 ('ISO-8859-1'), the results are not as expected. Like if I have</p>
<pre><code>int outP = 5;
//...
int outV = Serial.read();
analogWrite(outP, outV);
</code></pre>
<p>While with python I have</p>
<pre><code>serial_port.write(chr(255).encode())
</code></pre>
<p>I read 3.78 V from the pin, whereas if I use</p>
<pre><code>serial_port.write(chr(255).encode(encoding = 'latin-1'))
</code></pre>
<p>I get 5.04 V. I have read latin-1 and utf-8 don't always match, but is there something about arduino that requires using latin-1? Of course, these return different values when testing each encoding, using 255 gives b'\xc3\xbf' (from 'Ã¿') with utf-8 or b'\xff' from ('ÿ') with latin-1, but why does arduino work with latin-1?</p>
<p>FYI other options that work are</p>
<pre><code>v = 255

serial_port.write(v.to_bytes(1, byteorder = 'big'))

serial_port.write(bytes[v])

</code></pre>
 70020: <blockquote>
<p>but is there something about arduino that requires using latin-1?</p>
</blockquote>
<p>No, not really.</p>
<p>What it comes down to is that <code>Serial.read()</code> reads bytes, irrespective of whatever encoding they may be being used with.  ISO-8859 only encodes character code points in the 0-255 range, so when you choose a 0-255 code point and send it as ISO-8859, it gets sent as 1 byte, which is how you're code has been written to receive it.</p>
<p>A 255 code point as utf-8 would require multiple bytes to encode and so would result in multiple <code>Serial.read()</code> calls for a given value.</p>
<p>If you open a python3 REPL and put <code>chr(255).encode()</code> or more explicitly <code>chr(255).encode('utf-8')</code> you will see it results in <code>b'\xc3\xbf'</code>.  So on the Arduino side you will see this as two separate <code>Serial.read()</code> results, <code>0xC3</code> and <code>0xBF</code>.</p>
<p>When you're just taking in strings and UTF-8 and splatting them out via <code>Serial.println()</code>, the Arduino is blissfully unaware of that they're UTF-8 and not ISO-8859.  Really you could use any encoding you wanted, the the caveat being that if you're using c-strings to store them, the encoding would need to be one that doens't allow for a single null byte to be in the middle of the string.</p>
<hr />
<p>You may want to look into using <a href="https://docs.python.org/3/library/struct.html#struct.pack" rel="nofollow noreferrer">struct.pack</a> rather than cobbling together python bytestrings with sequences of <code>chr()</code> and <code>.encode(whatever)</code>. <code>struct.pack</code> will also result in a bytestring, but it's more purpose built for doing this.</p>
<p>You can <code>import struct</code> and then <code>struct.pack('B', 255)</code> will result in <code>b'\xff</code> same as <code>chr(255).encode('iso8859-1')</code>, but at least expresses intent.  <code>'B'</code> here signifies an <code>unsigned char</code> range, you'll find the format specifiers in the documentation. You'll get a greater benefit when you begin using multiple fields where <code>struct.pack</code> will be a lot less unwieldy than the <code>chr</code> and <code>encode</code> and string concatenation.</p>
