Как игнорировать значения мусора при последовательной связи между Arduino и Python
У меня есть arduino uno
. Я пытаюсь отправлять и получать последовательные данные с Arduino на Python. У меня есть конвертер USB-UART. Я подключил его tx
к rx
Arduino и rx
к tx
Arduino и gnd
подключен к gnd
. Я подключил этот USB-накопитель к своему ноутбуку, где написал скрипт Python ниже:
import serial
ser = serial.Serial(port='COM6')
res = ser.read(10)
print(bytes.hex(res))
data = b"\x7E\x7E\xAA\x03\xAB\x77"
ser.write(data)
ser.close()
В приведенном выше коде я сначала считываю последовательные данные, а как только данные получены, я отправляю несколько шестнадцатеричных пакетов. Ниже приведен код Arduino:
void setup()
{
Serial.begin(9600);
}
void loop()
{
const byte message[] = {0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03 };
Serial.write(message, sizeof message);
Serial.println("data sent");
delay(1000);
char buffer[6];
if (Serial.available() > 0)
{
int size = Serial.readBytesUntil('\x77', buffer, 6);
for (int i = 0 ; i < size ; i++)
{
Serial.println(buffer[i], HEX);
}
}
}
В приведенном выше коде я сначала отправляю шестнадцатеричные пакеты (которые нормально принимаются на стороне Python), а затем он ожидает последовательных данных. Как только последовательные данные доступны для чтения, он считывает их с помощью \x77
и распечатывает все данные. Это получено на последовательной консоли Arduino:
Вы заметите, что данные получены, но получены дополнительные FF
. Почему мы получили эти FF
. Также в коде Python мы знаем, что отправляем данные длиной 6, поэтому, соответственно, мы определили char buffer[6]
в arduino, но что, если нам нужно получить данные, которые мы не знаем, какой длины они будут быть. Пожалуйста помоги. Спасибо
@S Andrew, 👍3
Обсуждение1 ответ
Лучший ответ:
Эффект, который вы видите, — это продвижение типа, которое в стандарте C++ называется «интегральным продвижением», которое происходит неявно. Значения типа char
преобразуются в in t
. Обычно, и в вашем случае тоже, char
по умолчанию подписан.
Значения 0xAA
и 0xAB
имеют установленный старший бит, который обычно обозначает отрицательное значение в дополнение до двух. Это справедливо и для вашего случая. Таким образом, эти отрицательные значения преобразуются в те же отрицательные значения, но в полную ширину int
. В вашем случае int
имеет 32 бита.
Hex 0xAA
как (по умолчанию знак) char
представляет собой десятичное число -86
. И десятичный -86
, поскольку (по определению со знаком) int
равен 0xFFFFFFAA
шестнадцатеричному.
Печатается в шестнадцатеричном формате, отображаются все биты. Итак, вы видите все эти FF
.
Решение состоит в том, чтобы замаскировать только интересующие младшие 8 бит:
{
Serial.println(buffer[i] & 0xFF, HEX);
}
Хороший улов! Ну, на самом деле все немного сложнее: char
преобразуется в 16-битное int
с помощью разрешения перегрузки Serial.println()
, а затем явно [приводится к long
с помощью Print::print (int, int)
](https://github.com/arduino/ArduinoCore-avr/blob/1.8.6/cores/arduino/Print.cpp#L79), затем преобразуется в unsigned long с помощью вызова printNumber()
., @Edgar Bonet
@EdgarBonet Эта проблема часто случается с новичками, и у меня она уже была много раз. :-D -- Спасибо, что углубились в детали! Я считаю официальную документацию Arduino в сети неудовлетворительной, потому что мне всегда не хватает точных и полных прототипов. Нам не нужно заглядывать в исходный код библиотеки..., @the busybee
Спасибо за Ваш ответ. Есть идеи, почему принимаются некоторые мусорные и случайные значения? Танск, @S Andrew
@SAndrew Какой мусор и случайные значения вы имеете в виду? Я ничего не вижу. Пожалуйста, задайте новый вопрос, если это отдельная проблема, иначе отредактируйте свой вопрос., @the busybee
- Последовательная связь Arduino с Python: отправка массива
- Сброс последовательного порта Arduino в последовательном мониторе и Python
- Последовательная связь между python и arduino
- Как получить ненулевой выход из HX711 и ячейки загрузки?
- Почему нужно использовать latin-1 вместо utf-8 при использовании python с arduino?
- Как остановить серводвигатель в текущем положении при использовании последовательного порта? Я хочу, чтобы он оставался в одном положении при получении «0».
- Метод перебора битов в байте, отправленном по последовательному каналу.
- серийные данные портятся
Как вы настроили последовательный порт на стороне Python? Это не сделано в самом коде Python., @Edgar Bonet
@EdgarBonet Извините, я не понял вас по настройке последовательного порта. Что касается Python, я только что упомянул номер порта и все. Что касается оборудования, то оно то же самое, что упоминалось в вопросе., @S Andrew
Вы не можете подключить другой преобразователь USB-Serial к тем же контактам RX и TX. Последовательные порты не могут работать «параллельно». Определите серийный номер программного обеспечения, используя любые другие цифровые контакты, и подключите преобразователь к этим контактам. Аппаратные контакты rx и tx уже подключены к встроенному преобразователю «последовательный порт в USB»., @Fahad
@Фахад, я знаю, и именно поэтому при загрузке кода мне нужно удалить перемычки между контактами rfom tx и rx. Как только код загружен, я просто нажимаю кнопку сброса, чтобы запустить его снова. Все хорошо?, @S Andrew
@SAndrew Но вы все еще используете одни и те же контакты для двух сериалов! Один из них — встроенный серийный номер, который вы просматриваете в последовательном окне Arduino IDE (COM7), а другой — в Python (COM6). Это проблема. Последовательные шины не предназначены для использования в качестве параллельных шин., @Fahad
@Фахад Спасибо за твою помощь. Использование серийного программного обеспечения на самом деле является хорошим вариантом., @S Andrew