LINUX.ORG.RU

Виснет QSerialPort

 


1

2


serial.write("COMMAND");
serial.waitForBytesWritten();
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));
buffer[how_many-1] = '\0';
qDebug()<<buffer;

//вплоть до этой точки работает верно


serial.write("COMMAND2");
serial.waitForBytesWritten();
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));
buffer[how_many-1] = '\0';
qDebug()<<buffer;


//fail


serial.write("COMMAND");
serial.waitForBytesWritten();
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));
buffer[how_many-1] = '\0';
qDebug()<<buffer;

//ужу не работает

Файл выглядит как нормально выведенная строка (или частично?). Но после него уже другие комманды не проходят. Устройство работает правильно. Во всех случаях принятое количество символов заведомо меньше размера буфера, но во втором случае символов чуть больше, и, вероятно, приходят они с некоторой задержкой (около секунды).

ЧЯДНТ?

★★★★★

Последнее исправление: next_time (всего исправлений: 1)

qserialdevice не переводит COM в raw мод самостоятельно(Qserialport - переводит), эту нужно делать руками, из-за этого COM'у может стать плохо ибо встретил он в бинарном потоке данных управляющий символ.

dhampire ★★★
()
Ответ на: комментарий от anonymous

я типа случайно слишком рано запостил сообщение

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Беда в том что этот класс выведет первые залетевшие в ответ байты. Чтобы получить ответ целиком надо до определенного времени еще почитывать байты (bytesAvailable), и если ничего нет через некоторое время - значит всё. Увы, только так.

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

+1
QSerialPort как и любой другой поток данных так пользовать нельзя. Процедура чтения должна обязательно либо ориентироваться на требуемый размер полученных данных либо на interchar timeout посылки.

dib2 ★★★★★
()
Ответ на: комментарий от dib2

после попытки чтения во втором абзаце порт становится неюзабельным

next_time ★★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

мне желательно ещё, чтобы оно тянуло минимум либ. хотя, сигналы-слоты, наверное, по-любому притянутся. так что, наверное, так и сделаю.

next_time ★★★★★
() автор топика
Ответ на: комментарий от dib2

ну вот, а в документации писали...

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Если у тебя уже QSerialPort то считай ничего дополнительного не добавится, лишь зря вкуснятина (сигналы-слоты) болтается но не юзается - а так будет использоваться.

I-Love-Microsoft ★★★★★
()
void ComPort:writeDataSlot(const QByteArray& data)
{
        qint64 bytesWritten = m_serial->write(data);
        if (bytesWritten == -1) {
                output_to_log(QString("Failed to write the data to port %1, error: %2").arg(m_serial->portName()).arg(m_serial->errorString()));
        } else if (bytesWritten != data.size()) {
                output_to_log(QString("Failed to write all the data to port %1, error: %2").arg(m_serial->portName()).arg(m_serial->errorString()));
        } else if (!m_serial->waitForBytesWritten(5000)) {
                output_to_log(QString("Operation timed out or an error occurred for port %1, error: %2").arg(m_serial->portName()).arg(m_serial->errorString()));
        }
}

как минимум ты не проверяешь код возврата из write .... про сигнал-слоты уже написали

dhampire ★★★
()
Последнее исправление: dhampire (всего исправлений: 1)
Ответ на: комментарий от dhampire

+100500, тем более в случае ошибки значение -1 значит 4 миллиарда для unsigned, и это еще если повезет не оказаться на 64-битной тачке ;) how_many - какой тип?

В общем, с кодом что-то явно не так.

QSerialport из состава Qt5 - очень хорошая реализация, с ней нет проблем. Однако скажу что я писал программу, которая должна была допускать пропадание порта (USB-Serial) и восстанавливать связь когда он вернется. Так вот в случае пропадания порта - QSerialport продолжал лишь делать видимость работы (не вылетала программа) но сигналы не шли таймеры не срабатывали (но загрузки ЦП не было) - одним словом программа не могла восстановить работу с портом, а QExtSerialport этого недостатка лишен.

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 2)

Интересно, мне одному пришла идея использовать socat в качестве транспорта?

QProcess *p = new QProcess(this);
connect(p, readyReadStandardOutput(), this, data_in());
p->start("socat", "- /dev/ttyS0,b115200,raw,echo=0");

nanoolinux ★★★★
()

вылечил, вставив задержку


serial.write("COMMAND2");
serial.waitForBytesWritten();
QThread::msleep(100); //магия
serial.waitForReadyRead(-1);
how_many = serial.read(buffer, sizeof(buffer));

если бы оно было парой строчек выше или ниже , я бы ещё понял, но тут-то оно как влияет? о_0

next_time ★★★★★
() автор топика

Про Event Loop слышали? Вот QSerialPort так же на него завязан.(конкретно - в реальности вы вообще не запишете ничего в порт пока не обработается EventLoop). Иными словами вам надо что бы EventLoop нормально работал, т.е. как костыль вставить принудительную обработку эвентлупа, а лучше просто сделать чтение по слоту ReadyToRead (или как-то так, точное незвание не помню) - а по-хорошему вы читать должны как раз только по ReadyToRead сигналу.

RiseOfDeath ★★★★
()
Последнее исправление: RiseOfDeath (всего исправлений: 3)

Наивный, ты надеешься прочитать весь ответ одним read? Так не бывает, куски ответа обычно рандомной длины. Нужно читать и склеивать куски, пока в конце не будет оконечного символа. Я вообще буфер делал в 1 байт, ибо рандомная длина кусков заколебала.

anonymous
()
Ответ на: комментарий от RiseOfDeath

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

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Ну известен, и что? Как это помешает ему прочитаться не за 1 раз? Если ты имел в виду размер буфера, то я не про тот, в который ты читаешь, а про тот, который setReadBufferSize().

anonymous
()

есть такой проектик: http://sigrok.org/wiki/Libserialport

Если зависоны с usb-to-com, бывает что пакет в 64 байта идёт дольше чем в 63

anonymous
()
Ответ на: комментарий от I-Love-Microsoft

попробовал. та же фигня и почти лечится также. почему «почти» — выяснилось, что некоторые запросы замусориваются. и я уже хз, как лечить. за основу брал немного подпиленный пример из qt.

так что, проблема всё ещё актуальна, и походу, это баг qt.

next_time ★★★★★
() автор топика
Ответ на: комментарий от RiseOfDeath

не, не помогает, наоборот, частично помогло большие задержки ставить

next_time ★★★★★
() автор топика
Ответ на: комментарий от dhampire

в продакшен без обмотки проверками на ошибки пихать, конечно, нельзя. но подобные рода проверки только мешают во время отладки, поэтому я их ставлю в последнюю очередь. ну вернёт он не 9 а -1, ну вылетит во время отладки прога — так это пофиг, пока программа даже до альфа версии не дошла. в данном же частном случае, практика показала, что запись таки не фейлится, сообщение всегда доходит прекрасно до устройства, фейлится именно чтение.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

очевидно, и раньше беда, на самом деле, была в тотальном замусоривании/неполном считывании данных

next_time ★★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

хотя не, поправил код — уже не мусорится, но всё равно задержки (слишком здоровые для времени записи) нужны. нахрена нам waitForBytesWritten() и waitForReadyRead(-1) тогда — непонятно.

next_time ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.