Связь Arduino-C ++ не читать Arduino

У меня есть следующий код:

QSerialPort arduPort("COM5");
arduPort.setBaudRate(QSerialPort::Baud9600);
arduPort.setDataBits(QSerialPort::Data8);
arduPort.setParity(QSerialPort::NoParity);
arduPort.setStopBits(QSerialPort::OneStop);
arduPort.setFlowControl(QSerialPort::NoFlowControl);
arduPort.open(QSerialPort::ReadWrite);
cout<<arduPort.isReadable()<<endl;
cout<<arduPort.isWritable()<<endl;
arduPort.write("a");
QByteArray s=arduPort.readAll();

cout<<QString(s).toStdString()<<endl;

И следующий код в Arduino:

int inByte = 0;

void setup()
{
Serial.begin(9600);
while(!Serial){;}
int i=0;
}

void loop()
{
if(Serial.read()=='a')
Serial.write('b');
}

Сначала я посылаю ‘a’ в Arduino, и ARduino должен ответить ‘b’. Но когда я читаю порт Arduino, я получаю только «».

Кто-нибудь знает, почему я получаю «» вместо «б»? Спасибо за ваше время.

4

Решение

Обновление: см. Ответ ниже. TL; DR: вы установили скорость передачи (и, вероятно, все остальные настройки) после Вы открываете порт.

Я считаю, что это ошибка в реализации Windows QSerialPort. Я еще не смог определить причину, но у меня есть следующие симптомы:

  1. Загрузите Arduino (Uno в моем случае; Леонардо может вести себя по-разному) с демонстрацией ASCII. Отключите и снова подключите Arduino. Обратите внимание, что индикатор TX не загорается.

  2. Подключите его с помощью Putty или монитора последовательного порта Arduino. Это сбрасывает Arduino, а затем печатает таблицу ASCII. Индикатор TX горит постоянно, как и ожидалось.

  3. Отключите / снова подключите Arduino и на этот раз подключите к нему программу QSerialPort. На этот раз, несмотря на то, что порт открыт нормально, индикатор TX никогда не включается и readyRead() никогда не срабатывает. Также обратите внимание, что Arduino не сбрасывается, потому что по умолчанию QSerialPort не меняет DTR. Если вы делаете QSerialPort::setDataTerminalReady(false); затем сделать паузу на 10 мс, затем установить его true Это будут сбросить Arduino, как и ожидалось, но он все еще не передает.

  4. Обратите внимание, что если у вас есть программа Arduino, которая передает данные непрерывно (пример ASCII останавливается), если вы открываете порт с помощью putty, чтобы он начал передачу и затем откройте его с помощью QSerialPort, не отключая кабель, он будет работать! Однако, как только вы отключите / подключите кабель, он перестанет работать снова.

Это заставляет меня подозревать, что putty устанавливает некоторые параметры последовательного порта, которые требуются для arduino, и сбрасывается при повторном подключении кабеля. QSerialPort, очевидно, не меняет это значение.

Вот настройки, которые использует Putty, насколько я могу судить:

dcb.fBinary = TRUE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fTXContinueOnXoff = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fAbortOnError = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.BaudRate = ...;
dcb.ByteSize = ...;

И по QSerialPort:

dcb.fBinary = TRUE;
dcb.fDtrControl = unchanged!
dcb.fDsrSensitivity = unchanged!
dcb.fTXContinueOnXoff = unchanged!
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = unchanged!
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.BaudRate = ...;
dcb.ByteSize = ...;

Поэтому я думаю, что это должно быть одно из тех неизменных значений, которое заставляет Arduino думать, что это не связано. От Документация DCB Я подозреваю fTxContinueOnXoff,

Хорошо, я собираюсь написать небольшую программу, чтобы прочитать эти настройки и посмотреть, что изменится.

Хорошо, я написал свою программу и сделал следующее открытие. Различия после запуска putty и только моей программы Qt были:

  • BaudRate: ЭТО НЕ БЫЛО УСТАНОВЛЕНО QT !!!!!!! Оказывается, вы можете установить только скорость передачи после Вы открываете порт.. В противном случае он остается на прежнем значении, которое равно 0, когда вы впервые подключаете кабель.
  • fDtrControl: установить 1 для Putty, оставить равным 0 для Qt.
  • fOutX и fInX: оба также установлены в 1 для Putty и оставлены в 0 для Qt.

После переезда все мои set...() вызовы функций после открытия работали отлично. Мне не пришлось возиться с DtrControl или Out / InX. (Хотя я также установил высокий DTR вручную.)

При настройке всех параметров я подумал, что было бы неплохо установить политику ошибок «пропустить». НЕ ДЕЛАЙТЕ ЭТОГО! ОСТАВЬТЕ ЭТО НА ИГНОРЕ! В противном случае это все испортит и добавляет странные задержки во все ваши коммуникации.

4

Другие решения

Установка портов до открытия не совсем возможна до Qt 5.2. Причина в том, что первоначальный дизайн был слишком низкоуровневым для класса, а должным образом объектно-ориентированным. Я долго думал, стоит ли менять его, и в конце концов я действительно решил это сделать.

Я только что представил изменение, которое в настоящее время пересматривается, и ваша оригинальная концепция тоже будет работать.

Здесь вы можете найти детали:

Сделать возможным установить значения порта перед открытием

Резюме можно прочитать здесь для изменения:

Сделать возможным установить значения порта перед открытием

Этот патч также изменяет поведение метода open. Мы не используем порт
обнаружение больше навсегда. Это была сломанная концепция, и это очень
вряд ли кто-то когда-либо полагался на это. Если бы кто-то сделал это, они бы
быть в беде в любом случае, получать ненужные шумные предупреждения и все такое.

Также было рассмотрено, что другой вариант оставить это поведение необязательно, так как
по умолчанию, но это слишком усложнит API без особой выгоды.

Настройки порта по умолчанию теперь также вменяемые 9600,8, N, 1 и без контроля потока.
Также обратите внимание, что последовательный порт закрывается автоматически в методе open
если какая-либо из настроек не удалась.

Пожалуйста, обновите свою версию Qt (по крайней мере, до Qt 5.2), или вы можете сделать бэкпорт изменения самостоятельно. Затем можно написать этот код, и даже рекомендуется:

QSerialPort arduPort("COM5");
arduPort.setBaudRate(QSerialPort::Baud9600);
arduPort.setDataBits(QSerialPort::Data8);
arduPort.setParity(QSerialPort::NoParity);
arduPort.setStopBits(QSerialPort::OneStop);
arduPort.setFlowControl(QSerialPort::NoFlowControl);
arduPort.open(QSerialPort::ReadWrite);
4

BaudRate: ЭТО НЕ БЫЛО УСТАНОВЛЕНО QT !!!!!!! Оказывается, вы можете только установить
скорость передачи после открытия порта. В противном случае он остается на
предыдущее значение 0, когда вы впервые подключаете кабель.

Да, это правда. Но это было исправлено и будет доступно в Qt 5.3

fDtrControl: установить 1 для Putty, оставить равным 0 для Qt.

Нет. Qt не касайтесь сигнала DTR при открытии. Этот сигнал будет очищен только тогда, когда было установлено значение DTR_CONTROL_HANDSHAKE. Потому что QtSerialPort не поддерживает управление потоком DTR / DSR. Таким образом, в любом случае вы можете управлять DTR с помощью QSerialPort :: setDataTerminalReady (bool).

PS: я имею в виду текущий выпуск Qt 5.3

fOutX и fInX: оба также установлены в 1 для Putty и оставлены в 0 для Qt.

Этот флаг используется только при использовании QSerialPort :: Software flow control (Xon / Xoff). Но вы используете QSerialPort :: NoFlowControl (как я вижу из вашего фрагмента кода), так что все в порядке. Поэтому, пожалуйста, убедитесь, что вы используете Putty с контролем потока «None».

При настройке всех параметров я подумал, что было бы неплохо
установите политику ошибок «пропустить».

Пожалуйста, используйте только политику QSerialPort :: Ignore (по умолчанию). Потому что другие политики устарели (все политики) и будут удалены в будущем.

UPD:

dcb.fRtsControl = RTS_CONTROL_ENABLE;

Ааа, кажется, ваш Arduino ожидает, что сигнал RTS должен быть включен по умолчанию. В этом случае вам следует использовать QSerialPort :: setRequestToSend (bool). Но это возможно только в режиме QSerialPort :: NoFlowControl.

То есть RTS всегда будет в RTS_CONTROL_DISABLE или RTS_CONTROL_HANDSHAKE после открытия порта (зависит от ваших настроек FlowControl, QSerialPort :: setFlowControl ()).

1
По вопросам рекламы [email protected]