Почему нужно использовать latin-1 вместо utf-8 при использовании python с arduino?
При чтении и записи с подключением последовательного порта python к arduino, если я не использую latin-1 ('ISO-8859-1'), результаты не такие, как ожидалось. Например, если у меня есть
int outP = 5;
//...
int outV = Serial.read();
analogWrite(outP, outV);
В то время как с python у меня есть
serial_port.write(chr(255).encode())
Я считываю 3,78 В с контакта, тогда как если я использую
serial_port.write(chr(255).encode(encoding = 'latin-1'))
Я получаю 5.04 В. Я читал, что latin-1 и utf-8 не всегда совпадают, но есть ли что-то в arduino, что требует использования latin-1? Конечно, они возвращают разные значения при тестировании каждой кодировки, используя 255 дает b'\xc3\xbf' (от 'Ä¿') с utf-8 или b'\xff' от ('ÿ') с latin-1, но почему arduino работает с latin-1?
К вашему сведению другие варианты, которые работают
v = 255
serial_port.write(v.to_bytes(1, byteorder = 'big'))
serial_port.write(bytes[v])
@user14094230, 👍1
1 ответ
Лучший ответ:
но есть ли что-то в arduino, что требует использования latin-1?
Нет, не совсем.
Все сводится к тому, что Serial.read()
считывает байты независимо от того, с какой кодировкой они могут использоваться. ISO-8859 кодирует только кодовые точки символов в диапазоне 0-255, поэтому, когда вы выбираете кодовую точку 0-255 и отправляете ее как ISO-8859, она отправляется как 1 байт, то есть так, как ваш код был записан для ее получения.
Кодовая точка 255, такая как utf-8, потребует кодирования нескольких байтов и поэтому приведет к нескольким вызовам Serial.read()
для данного значения.
Если вы откроете python3 REPL и поставите chr(255).encode()
или более явно chr(255).encode('utf-8')
, то увидите, что это приведет к b'\xc3\xbf'
. Таким образом, на стороне Arduino вы увидите это как два отдельных результата Serial.read ()
, 0xC3
и 0xBF
.
Когда вы просто берете строки и UTF-8 и выплескиваете их через Serial.println()
, Arduino блаженно не знает, что это UTF-8, а не ISO-8859. На самом деле вы можете использовать любую кодировку, какую захотите, но с оговоркой, что если вы используете c-строки для их хранения, то кодировка должна быть такой, чтобы ни один нулевой байт не находился в середине строки.
Возможно, вы захотите рассмотреть возможность использования struct.pack вместо того, чтобы связывать байтовые строки python с последовательностями chr()
и .encode(что угодно)
. struct.pack
также приведет к байтовой строке, но она больше предназначена для этого.
Вы можете импортировать struct
, а затем struct.pack('B', 255)
приведет к b'\xff
так же, как chr(255).encode('iso8859-1')
, но, по крайней мере, выражает намерение. "B"
здесь означает диапазон unsigned char
, спецификаторы формата вы найдете в документации. Вы получите большую выгоду, когда начнете использовать несколько полей, где struct.pack
будет намного менее громоздким, чем chr
, encode
и конкатенация строк.
- В чем разница, когда ардуино был отключен от сети, и когда последовательный порт был закрыт?
- Последовательная связь Arduino с Python: отправка массива
- Построение графика на Python с использованием Tkinter Canvas
- Отправьте несколько значений int из Python в Arduino, используя pySerial
- Команда strtok() с Serial связью
- Как отправить целое число через pyserial с Python на Arduino и получить тот же результат?
- Сброс последовательного порта Arduino в последовательном мониторе и Python
- Как изменить переменную при нажатии кнопки, подключенной к контакту 2
Да,
`len(chr(255).encode(encoding = 'latin-1'))
возвращает 1, а`len(chr(255).encode ())
возвращает 2, @user14094230хорошо, спасибо, какой формат следует использовать с struct.pack?, @user14094230
Я перенес свой предыдущий комментарий в ответ и обратился к вашему вопросу там., @timemage