Связь Arduino-Pyserial на Python 3, машина Windows: Pyserial.write(), похоже, ничего не делает
Недавно я получил в руки Arduino (или, скорее, Genuino, но общая архитектура должна быть такой же) UNO. Сейчас я использую этот Arduino для проверки того, как данные передаются с USB на последовательный разъем в Arduino.
Я уже убедился, что передача данных с Arduino на ПК возможна с помощью hTerm и PySerial. Однако всякий раз, когда я отправляю данные с Pyserial или hTerm, они не отображаются в последовательном терминале Arduino. Кроме того, я использую SoftwareSerial для настройки вторичного последовательного терминала, чтобы увидеть, что получает Arduino. (Я использую стандартный последовательный порт для отправки данных на терминал и порт SoftwareSerial для подключения к USB-последовательному разъему.)
Вот мой код на данный момент:
Сторона Python:
import serial
import time
import sys
import struct
ser = serial.Serial('COM3', 9600, timeout=0)
time.sleep(10)
while 1:
print(ser.write(struct.pack('>B', 0)))
time.sleep(2)
print(1)
sys.stdout.flush()
Сторона Arduino выглядит так и по сути является примером по умолчанию: https://www.arduino.cc/en/Tutorial/SoftwareSerialExample
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
// поместите сюда ваш код настройки для однократного запуска:
if (Serial) {
Serial.end();
}
Serial.begin(9600);
while (!Serial) {
;
}
Serial.println("Godnight moon!");
mySerial.begin(9600);
mySerial.println("Hello, world?");
}
void loop() {
// поместите сюда свой основной код для многократного выполнения:
mySerial.listen();
if (mySerial.available() > 0) {
Serial.println("Hello User");
Serial.println(mySerial.read());
}
}
Терминал никогда не печатает "Hello User". Кроме того, никакие другие сигналы не печатаются. Удалив условие if, я получаю кучу "Hello User" и "-1" в последовательном мониторе Arduino IDE.
Относительно моей настройки:
У меня есть преобразователь USB в последовательный порт, который подключен как "COM3". С другой стороны, у меня есть Arduino UNO, который подключен через USB к тому же компьютеру. Контакт TX преобразователя подключен к контакту RX Arduino и наоборот. Кроме того, заземление подключено к заземлению. Кроме того, я использую блокнот Jupyter/IPython для запуска моего скрипта Python и стандартную среду разработки Arduino для компиляции программ для моего Arduino. В случае, если я получил данные от Arduino, я использовал скрипт, указанный в предоставленном URL, который очень похож на тот, который я уже показываю здесь. Кроме того, ser.write() заменен на ser.read(1), так что он считывает один байт за раз. Моя система - Windows 7 (64 бит).
Редактировать: Вот установленное соединение между hTerm (последовательным терминалом) и скриптом Python при использовании com0com в качестве эмулятора порта.

@user25642, 👍1
Обсуждение2 ответа
Как вы думаете, что должно получиться?
Я не эксперт по Python, но вы, похоже, используете struct pack, который, как я думаю, добавляет несколько байтов к данным для генерации 4-байтового слова. Вы используете NULL, 0 для упаковки структуры. Когда Serial.println() встречает NULL, он предполагает, что это конец строки. Так что вы, похоже, печатаете строку из нулевых байтов.
О, и Serial.read() считывает только один байт данных, так что с этим тоже есть проблема. Я подозреваю, что у вызова записи похожая проблема, обычно нужно указывать параметр размера, потому что это двоичные данные.
Имеет ли это смысл?
Привет, спасибо за ответ. Синтаксис struct pack следующий: Символ «>B» обозначает байт с прямым порядком байтов, который будет упакован, а «0» — это просто целое число, упакованное в байт. Если я выведу это на экран, то получу b'\x00', что означает, что это просто пустой байт. Вы это имели в виду, когда говорили о NULL, или это другой параметр?, @user25642
И да, я знаю, что Serial.read(1) считывает только один байт за раз. Это было сделано только для проверки, так как я отправлял только один байт за раз. (Чтобы проверить, работает ли вообще соединение). pySerialAPI (http://pyserial.readthedocs.io/en/latest/pyserial_api.html) В заявлении указано, что функция write принимает только один аргумент — данные. В Python 3 данные должны быть отформатированы, поэтому я использую пакет struct. Для четырёхбайтового слова мне нужно использовать что-то вроде ">BBBB", поскольку одна буква B — это всего один байт. Надеюсь, это немного прояснит, что делает код :), @user25642
Как правило, пакет struct используется для форматирования переменных в Python в соответствии с определёнными стандартами. Проблема в том, что тип int в Python занимает ровно столько места, сколько необходимо, поэтому его длина может меняться в зависимости от размера числа., @user25642
Переменная длина int, какой глупый язык :) Да, спасибо, это многое проясняет. Под NULL я имею в виду 0x00, так что если вы получаете это, то всё работает. Если вывести это как строку, то будет казаться, что ничего не происходит. Можете написать (0x42) вместо упаковки? На Arduino должно получиться 0x42 или 'B'., @Code Gorilla
Хорошо, я просто использовал функцию упаковки, чтобы упаковать b"B" (что является байтовым представлением B. Python 3 использует Unicode, так что это должно сработать) и отправить его вместо 0. Arduino по-прежнему ничего не отображает., @user25642
Итак, я могу отправлять данные из моего скрипта Python в hTerm через виртуальные порты (я использую com0com). Я также могу отправлять данные из hTerm в свой скрипт. Но если я соединить два USB-Serial-конвертера друг с другом, а один подключить к hTerm, а другой — к скрипту Python, они не будут обмениваться данными. Теперь я проверю драйверы и всё такое для USB-Serial-конвертеров. (Хотя они всё равно мигают, если что-то отправляют.), @user25642
Не используйте pack(), это и вызывает проблему. Вы отправляете 0x00000043, что соответствует Null, Null, Null B. Когда Arduino считывает один байт, она видит Null, что означает, что она ничего не выводит. Вам нужно отправить один байт 0x43. Если вам нужно отправить слово, отправьте 0x43000000. Так всё должно работать. USB <-> Serial <-> Serial <-> USB не будет работать, если в Serial <-> Serial не перекрещены линии RX и TX. Перекрещивания линий нет, поскольку для связи с Arduino можно использовать оба преобразователя., @Code Gorilla
Могу ли я спросить, почему у вас сложилось впечатление, что pack() создаёт 4-байтовое число? Если я использую ">c", я упаковываю строку в её однобайтовое символьное представление. Я проверил это с помощью терминала. Приходит только один байт, больше ничего (я также постараюсь прикрепить скриншот к своему вопросу). И я не совсем понимаю, что вы имеете в виду под «перекрёстным соединением». Я подключил TX одного Serial-USB к RX другого Serial-USB, и наоборот. Вы это имели в виду?, @user25642
Я заметил значение NULL, но предполагал, что Serial.println() отобразит «0», как будто вы запустили Serial.println(0)., @SoreDakeNoKoto
@user25642 — Я догадывался, что сделал pack, так что спасибо, что поправил. Да, под «переходом» я имею в виду tx в rx и rx в tx., @Code Gorilla
Когда вы запускаете свой код Python, вы видите то, что отправляете на экран?
Я думаю, вам нужно вызвать ser.open().
- Не удается связаться с ардуино с помощью python (Windows)
- AT-команда не отвечает на последовательный монитор
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- Как остановить SoftwareSerial от получения данных и повторно включить его в какой-то другой момент?
- Последовательная связь Arduino с Python: отправка массива
- Ардуино для чтения с преобразователя RS232 в последовательный модуль TTL
- Построение графика на Python с использованием Tkinter Canvas
- Не нашел датчик отпечатков пальцев :( Arduino Mega 2560 Adafruit Fingerprint Sensor
Что вы используете для подключения к контактам SoftwareSerial?, @Majenko
Некоторые кабели, входящие в стартовый набор Genuino. RX подключается к TX, а TX — к RX (USB-Serial к Arduino), а земля — к земле., @user25642
«Некоторые кабели» — не очень точное определение. К каким контактам TX и RX вы подключаетесь?, @Majenko
Ладно. Ну, я подключаюсь к контактам 10 (RX) и 11 (TX). Или вы имеете в виду, как я подключаюсь на другом конце?, @user25642
Хорошо, теперь это имеет для меня больше смысла., @Majenko
Схема вашей установки значительно прояснит ваш вопрос. Вы проверили, что порт USB-Serial — COM3? Что выводит оболочка Python при запуске скрипта? Для ясности: вы подключили RX адаптера USB-Serial к контакту 11 Arduino, а его TX — к контакту 10 Arduino? Удалите аргумент 'timeout' в реализации 'ser' в скрипте Python и попробуйте ещё раз., @SoreDakeNoKoto
Я обновил описание. Всё верно, COM3 — это порт, назначенный USB-Serial-конвертеру. Контакт 10 (RX) подключен к TX на стороне USB, а контакт 11 (TX) — к RX на стороне USB. Кроме того, я уже получил данные от Arduino, поэтому не думаю, что проблема в настройке. Я также поменял местами соединительные кабели, но это тоже не решило проблему., @user25642
Работает ли это при использовании встроенного аппаратного последовательного порта Arduino? Таким образом, мы можем попытаться выяснить, в чём проблема: в Python или в Arduino., @brtiberio
Итак, я использовал hTerm, так как сейчас он, вероятно, лучше подходит для отладки. Когда я отправляю сигнал с терминала Arduino на Arduino через последовательный порт (работает в обоих случаях, как виртуальный, так и встроенный аппаратный последовательный порт (контакты 0 (RX) и 1 (TX), верно?)), я получаю ответ в отдельном окне hTerm. hTerm подключен к USB-Serial Converter (COM7). Однако, если я отправляю данные из hTerm или скрипта ipython на Arduino, он не отвечает. (Терминал Arduino IDE и hTerm ничего не показывают). Поэтому, скорее всего, USB-Serial Converter сломан..., @user25642
@user25642 — Номер COM-порта изменился, или я неправильно понял? В вашей программе указано COM3, хотя вы подключаете hTerm к COM7., @Code Gorilla
У меня два USB-Serial-конвертера, и я только что попробовал оба. Извините, если это было непонятно. И оба, похоже, не работают., @user25642