Я пытаюсь построить некоторые последовательные данные в моей программе Qt Gui, используя класс qcustomplot. У меня не было проблем, когда я пытался построить данные с низкой частотой дискретизации, например, 100 данных в секунду. График был действительно крутым и отображал данные плавно. Но при высокой частоте дискретизации, такой как 1000 данных в секунду, плоттер создает узкое место для функции последовательного чтения. Это замедляло время, как на расстоянии 4-5 секунд от устройства. Прямо говоря, плоттер не смог достичь скорости потока данных. Итак, есть ли какая-то общая проблема, о которой я не знаю, или какие-либо рекомендации?
Я думаю, что эти сценарные,
1 — разделить всю программу на 2 или 3 потока. Например, последовательная часть выполняется в одном потоке, а часть печати выполняется в другом потоке, а два потока связываются с QSemaphore.
2-кадр / с пользовательского сюжета ограничен. но должно быть решение, потому что NI LABVIEW отображает до 2 тыс. данных без каких-либо задержек
3 — для разработки нового виртуального последовательного устройства в протоколе USB. Теперь я использую ft232rl последовательный в USB конвертер.
4- изменить язык программирования. Какова ситуация и класс поддержки в C # или Java для построения графиков в реальном времени? (Я знаю, что это как ребенок говорит, но это повод, чтобы испытать на других языках)
Мое последовательное устройство отправляет функцию данных (это устройство для экспериментов, в котором нет серьезного кодирования), вкратце:
void progTask()
{
DelayMsec(1); //my delay function, milisecond
//read value from adc13
Adc13Read(adcValue.ui32Part);
sendData[0] = (char)'a';
sendData[1] = (char)'k';
sendData[2] = adcValue.bytes[0];
sendData[3] = (adcValue.bytes[1] & 15);
Функция чтения программы Qt такова:
//send test data
UARTSend(UART6_BASE,&sendData[0],4);
}
union{
unsigned char bytes[2];
unsigned int intPart;
unsigned char *ptr;
}serData;
void MedicalSoftware::serialReadData()
{
if(serial->bytesAvailable()<4)
{
//if the frame size is less than 4 bytes return and
//wait to full serial receive buffer
//note: serial->setReadBufferSize(4)!!!!
return;
}
QByteArray serialInData = serial->readAll();
//my algorithm
if(serialInData[0] == 'a' && serialInData[1] == 'k')
{
serData.bytes[0] = serialInData[2];
serData.bytes[1] = serialInData[3];
}else if(serialInData[2] == 'a' && serialInData[3] == 'k')
{
serData.bytes[0] = serialInData[0];
serData.bytes[1] = serialInData[1];
}
else if(serialInData[1] == 'a' && serialInData[2] == 'k')
{
serial->read(1);
return;
}else if(serialInData[0] == 'k' && serialInData[3] == 'a')
{
serData.bytes[0] = serialInData[1];
serData.bytes[1] = serialInData[2];
}
plotMainGraph(serData.intPart);
serData.intPart = 0;
}
И заданная пользователем настройка сюжета:
void MedicalSoftware::setGraphsProperties()
{
//MAIN PLOTTER
ui->mainPlotter->addGraph();
ui->mainPlotter->xAxis->setRange(0,2000);
ui->mainPlotter->yAxis->setRange(-0.1,3.5);
ui->mainPlotter->xAxis->setLabel("Time(s)");
ui->mainPlotter->yAxis->setLabel("Magnitude(mV)");
QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime());
timeTicker->setTimeFormat("%h:%m:%s");
ui->mainPlotter->xAxis->setTicker(timeTicker);
ui->mainPlotter->axisRect()->setupFullAxesBox();
QPen pen;
pen.setColor(QColor("blue"));
ui->mainPlotter->graph(0)->setPen(pen);
dataTimer = new QTimer;
}
И последняя функция сюжета:
void MedicalSoftware::plotMainGraph(const quint16 serData)
{
static QTime time(QTime::currentTime());
double key = time.elapsed()/1000.0;
static double lastPointKey = 0;
if(key-lastPointKey>0.005)
{
double value0 = serData*(3.3/4096);
ui->mainPlotter->graph(0)->addData(key,value0);
lastPointKey = key;
}
ui->mainPlotter->xAxis->setRange(key+0.25, 2, Qt::AlignRight);
counter++;
ui->mainPlotter->replot();
counter = 0;
}
Ты пытался:
ui->mainPlotter->replot(QCustomPlot::rpQueuedReplot);
в соответствии с документацией это может улучшить производительность при выполнении большого количества реплотов.
По твоему коду я чувствую, что ты пытаешься реплотировать так часто, как можешь, чтобы получить сюжет «в реальном времени». Но если вы работаете на ПК с настольной ОС, в реальном времени не бывает такого понятия.
То, о чем вы должны заботиться,
В вашем случае вы получаете 1000 данных / с, которые составляют 1 данные каждую мс. Это довольно быстро, потому что это за пределами разрешения по умолчанию таймера большинства настольных ОС. Это означает, что при вызове «serialReadData ()» у вас может быть больше одной точки данных, и вы можете оптимизировать ее, вызывая ее реже (например, вызывайте ее каждые 10 мс и каждый раз считывая 10 точек данных). Затем вы можете вызывать «replot ()» каждые 30 мс, что будет добавлять 30 новых точек данных каждый раз, пропускать около 29 вызовов replot () каждые 30 мс по сравнению с вашим кодом и давать вам ~ 30 к / с.
1 — разделить всю программу на 2 или 3 потока. Например, серийная часть
выполняется в одном потоке, а часть печати выполняется в другом потоке и двух
поток связывается с QSemaphore
Разделение графического интерфейса пользователя от последовательной части на 2 потока хорошо, потому что вы предотвратите узкое место в графическом интерфейсе, чтобы заблокировать последовательную связь. Также вы можете пропустить использование семафора и просто положиться на соединения Qt сигнал / слот (подключенные в режиме Qt :: QueuedConnection).
4- изменить язык программирования. Какова ситуация и класс
поддержка в C # или Java для построения графиков в реальном времени? (Я знаю, что это как ребенок
говорят, но это повод, чтобы испытать на других языках)
Изменение языка программирования, в лучшем случае, ничего не изменит или может ухудшить ваши характеристики, особенно если вы переходите на языки, которые не скомпилированы с собственными инструкциями ЦП.
Изменение библиотеки печати с другой стороны мог изменить выступления. Вы можете посмотреть на Qt Charts а также QWT. Я не знаю, как они сравниваются с QCustomPlot, хотя.
Других решений пока нет …