Поиск:

Ответ в темуСоздание новой темы Создание опроса
> QCustomPlot и QByteArray, отображение данных на графике 
:(
    Опции темы
7BON
Дата 26.11.2015, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 20.11.2015

Репутация: нет
Всего: нет



Доброго дня! Произвожу передачу данных по COM порту(передача и прием осуществляется нормально) это через консоль. Ввожу таймер передача идет 8 байт, делаю остановку счетчика и снова запускаю, уже передача идет 16 байт и так каждый раз увеличивается на 8. В чем может быть проблема?
Код

void MainWindow::writeData(/*const uint*/ )
{

     data[0]=0xA5;
     data[1]=0x01;
   //  data[0]<<16|data[1];


    data[3]=data[3]+0x02;// каждый адрес начинается с 0x02 с шагом 0x02

    if(data[3]==0x00)//условия сравнение если data[2]==0x00, то data[1]
                     //будет изменятся с шагом 0x01
        {
            data[2]=data[2]+0x01;
        }


    data[4] = 0x00;
    data[5] = 0x00;
    data[6] = 0x00;
    data[7] = data[0]^data[1]^data[2]^data[3]^data[4]^data[5]^data[6];


    serial->write(data);




    QTextCodec *win1250Codec = QTextCodec::codecForName("Windows-1250");
     QString str = win1250Codec->toUnicode((const char*)data, 0x08);
        qDebug() << str;
}
//! [6]

//! [7]
void MainWindow::readData()
{

    if(data[0]==0xA5 && data[1]==0x03)
    {
        ostem = data[2];
        I = ((data[3]<<8)|(data[4]));
        Iadress = ((data[5]<<8)|data[6]);
        data=serial->readAll();
    }



    ui->console->putData(data);
   

}

void MainWindow::on_pushButton_clicked()
{


    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(writeData()));
    connect(timer, SIGNAL(timeout()), this, SLOT(readData()));


   // timer->setInterval(1000);
    timer->start(400);


    connect(ui->pushButton , SIGNAL(clicked()), timer, SLOT(start()));
    connect(ui->pushButton_3, SIGNAL(clicked()),timer, SLOT(stop()));
   




}




и второй вопрос, когда принимаю данные нужно отображать их на графике(использую библиотеку QCustomPlot). Вот код:
Код

void MainWindow::setupQuadraticDemo(QCustomPlot *customPlot)
{
  demoName = "Quadratic Demo";
  // generate some data:
  QVector<double> x(101), y(101); // initialize with entries 0..100
  for (int i=0; i<101; ++i)
  {
   // x[i] = i/50.0 - 1; // x goes from -1 to 1
      x[i] = i;
      y[i] = data[i];
   // y[i] = x[i]*x[i];  // let's plot a quadratic function
  }
      //y=data[2];
  // create graph and assign data to it:
  customPlot->addGraph();
  customPlot->graph(0)->setData(x, y);
  // give the axes some labels:
  customPlot->xAxis->setLabel("x");
  customPlot->yAxis->setLabel("y");
  // set axes ranges, so we see all data:
  customPlot->xAxis->setRange(-1, 1);
  customPlot->yAxis->setRange(0, 1);
  customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
}



Добавлено через 1 минуту и 33 секунды
Данные не отображаются. В чем может быть проблема? раньше с этой билиотекой не работал
PM MAIL   Вверх
baldman88
Дата 26.11.2015, 11:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: нет
Всего: 7



По первому пункту ничего не понял. А вот по второму -- после обновления данных для отрисовки, нужно вызывать метод replot(). Допишите его в конец метода MainWindow::setupQuadraticDemo и будет Вам счастье.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
baldman88
Дата 26.11.2015, 11:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: нет
Всего: 7



И еще, по первому пункту. Зачем каждый раз создавать новый таймер? Создайте его в конструкторе. Плюс на один сигнал от таймера повешенно два слота. То, в какой очередности они выполнятся, будет зависеть от положения звезд на небе. Скорее всего из-за этого и происходит то, что вы описали.

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
7BON
Дата 26.11.2015, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 20.11.2015

Репутация: нет
Всего: нет



в первом пункте пробывал прописать, не сработало, а по второму у меня replot() прописан в конструкторе, прописал так как вы сказали не сработало

PM MAIL   Вверх
math64
Дата 26.11.2015, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Всегда нужно проверять число принятых байт.
Например, у меня сделано так:
Код

SerialHelper::SerialHelper(QMainWindow *parent) :
    QObject(parent)
{
    ...
    serialTimer = new QTimer(this);
    connect(serialTimer, SIGNAL(timeout()), this, SLOT(onSerialTimeout()) );
    connect(serial, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    connect(serial, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
}

void SerialHelper::onReadyRead()
{
    qint64 bytes = serial->bytesAvailable();
    if (bytes > 0) {
        recieved += bytes;
        QByteArray ba = serial->read(bytes);
        unprocessedData.append(ba);
        int processed = processData((const byte*)unprocessedData.data(), unprocessedData.size());
        unprocessedData.remove(0, processed);
    }
}

Данные могут приходить по одному байту, а могут приходить сразу много.
processData() ждет когда накопится нужное количество байт (у тебя 8) и обрабатывает их.
Возвращает число обработанных байт, которые потом удаляются из буфера.
PM   Вверх
math64
Дата 30.11.2015, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Цитата(7BON @  26.11.2015,  10:51 Найти цитируемый пост)
Данные не отображаются. В чем может быть проблема? раньше с этой билиотекой не работал 

Код

  customPlot->xAxis->setRange(-1, 1);
  customPlot->yAxis->setRange(0, 1);

т.е. x должен быть -1...1, y - 0...1, а у тебя x = 0...100, y зависит от data.
В лучшем случае отобразятся только первые две точки.


Цитата(miranka @  28.11.2015,  19:17 Найти цитируемый пост)
а нет ни какого конвертера или чего то вроде того?

Что хотите конвертировать? Если не по этой теме, спрашивайте в новой.

Добавлено через 2 минуты и 36 секунд
Цитата(7BON @  26.11.2015,  10:51 Найти цитируемый пост)
Код
     data[0]=0xA5;
    data[1]=0x01;

так что да, первая точка вне диапазона, вторая в углу - можно не заметить.
PM   Вверх
7BON
Дата 18.12.2015, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 20.11.2015

Репутация: нет
Всего: нет



math64 возможно я не правильно задаю свою посылку

Посылка по UART от компьютера(8 байт, скорость 115200 бод, один стоповый, без паритета) имеет следующую структуру: 

                                     1 - шапка - 0xA5;
                                     2 - 0x01;
                                     3 - старший байт адреса, по которому хранятся данные по току*;
                                     4 - младший байт адреса, по которому хранятся данные по току*;
                                     5 -7 - 0x00(резерв);
                                     8 - кс;

Ответная посылка имеет следующую структуру:

                                     1 - шапка - 0xA5;
                                      2 - 0x03;
                                      3 - остаточная ёмкость в процентах;
                                      4 - старший байт адреса, по которому хранятся данные по току;
                                      5 - младший байт адреса, по которому хранятся данные по току;
                                      6 - старший байт тока по запрашиваемому адресу;
                                      7 - младший байт тока по запрашиваемому адресу;
                                      8- кс;

* - Первое измеренное значение начинается с адреса 0x0004, все последующие адреса рассчитываются добавлением 0x0002.

это запись
Код

void MainWindow::writeData(/*const uint*/ )
{

     data[0]=0xAA;
     data[1]=0x01;
   //  data[0]<<16|data[1];


    data[3]=data[3]+0x02;// каждый адрес начинается с 0x02 с шагом 0x02

    if(data[3]==0x00)//условия сравнение если data[2]==0x00, то data[1]
                     //будет изменятся с шагом 0x01
        {
            data[2]=data[2]+0x01;
        }


    data[4] = 0x00;
    data[5] = 0x00;
    data[6] = 0x00;
    data[7] = data[0]^data[1]^data[2]^data[3]^data[4]^data[5]^data[6];


    serial->write(data);




    QTextCodec *win1250Codec = QTextCodec::codecForName("Windows-1250");
     QString str = win1250Codec->toUnicode((const char*)data, 0x08);
        qDebug() << str;
}


это чтение
Код

void MainWindow::readData()
{

    if(data[0]==0xA5 && data[1]==0x03)
    {
        ostem = data[2];
        I = ((data[3]<<8)|(data[4]));
        Iadress = ((data[5]<<8)|data[6]);
        data=serial->readAll();
 }



и вот значение I мне надо вывести 
подскажи как это сделать??
преобразование из шестнадцатиричной системы через функцию fromHex вроде бы

Это сообщение отредактировал(а) 7BON - 18.12.2015, 08:55
PM MAIL   Вверх
math64
Дата 18.12.2015, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Наиболее удобный способ преобразования числа в строку-
Код

QString str = tr("Адрес: %1 Ток: %2")
  .arg(address, /*fieldWidth:*/4, /*base:*/16, /*fillChar:*/'0')
  .arg(current, /*fieldWidth:*/4, /*base:*/16, /*fillChar:*/'0');

Для отображения в виде графика - пройдись по массивам x и y чтобы найти минимум и максимум для setRange();
PM   Вверх
kuzulis
Дата 18.12.2015, 11:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



Цитата

это чтение,
Код

data=serial->readAll()



1) В принципе, неправильно. Никто не гарантирует что readAll() вернет полный фрейм. 
2) Парсить фреймы (также как и генерить) лучше используя QDataStream, а не 
Код

(data[3]<<8)|(data[4])


Например:

Код

void MainWindow::writeData(/*const uint*/ )
{
    QByteArray frame;
    QDataStream out(&frame);
    out.setByteOrder(...); // если надо

    out << quint8(0xAA) << quint8(0x01) << ... << ... << quint32(value1) << ... ;

    serial->write(frame);
}

void MainWindow::readData(/*const uint*/ )
{
    if (serial->bytesAvailable() < expectedFrameLength)
        return;

    const QByteArray frame = serial->read(expectedFrameLength);
    QDataStream in(frame);
    in.setByteOrder(...); // если надо

    quint8 aa = 0;
    quint8 bb = 0;
    quint32 value = 0;

    in >> aa >> bb >> ... >> ...  >> value1 >> ... ;
}


Это сообщение отредактировал(а) kuzulis - 18.12.2015, 11:59
PM MAIL   Вверх
7BON
Дата 22.12.2015, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 20.11.2015

Репутация: нет
Всего: нет



kuzulis можете мне сказать: 
1. в этой строке
Код

out << quint8(0xAA) << quint8(0x01) << ... << ... << quint32(value1) << ... ;

value1 переменнная? и еще контрольную сумму создать как отдельную переменную к примеру вот так
Код

quint32(value)=0xA5^0x01^0x00^0x02^0x00^0x00^0x00;


в read тоже самое получается?

2. 
Код

if (serial->bytesAvailable() < expectedFrameLength)
            return;
        const QByteArray frame = serial->read(expectedFrameLength);
        QDataStream in(frame);
        //in.setByteOrder(...); // если надо
        quint8 aa = 0;
        quint8 bb = 0;

        quint8 cc = 0;
        quint8 dd = 0;
        quint8 gg = 0;
        quint8 ff = 0;
        quint8 kk = 0;

        quint32 value = 0;


        in >> aa >> bb >> cc >> dd >> gg >> ff >> kk >> value;

выдает ошибку 1 и 3 строки 
D:\program ZUAA\terminal QCustomPlot\mainwindow.cpp:249: ошибка: 
'expectedFrameLength' was not declared in this scope if (serial->bytesAvailable() < expectedFrameLength)

где лучше всего объявить эту функцию?
                                    ^
PM MAIL   Вверх
math64
Дата 23.12.2015, 08:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



expectedFrameLength - в Вашем случае конствнта, = 8.
Но если уж пользуемся QDataStream, то и задавать надо не числом, а примерно так:
Код

#pragma pack(push,1)
struct Frame {
qint8 header;
qint8 command;
qint16 address;
qint8 reserved[3];
qint8 crc;
};
#pragma pack(pop)
const int expectedFrameLength = sizeof(Frame);
QDataStream& operator <<(QDataStream&, const Frame&);
QDataStream& operator >>(QDataStream&, Frame&);

Но: для правильного вычисления expectedFrameLength нужно, чтобы структура была упакована, а #pragma pack не гарантирует этого (хотя в большинстве компиляторов работает)

Это сообщение отредактировал(а) math64 - 23.12.2015, 13:50
PM   Вверх
kuzulis
Дата 23.12.2015, 11:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 154
Регистрация: 5.9.2007

Репутация: нет
Всего: 1



Если структура упакована, то и QDataStream не нужен. smile

Но, ИМХО, все-таки лучше и гибче QDataStream - меньше ошибок будет. 
ТС, посмотри примеры из /network/fortuneclient&&fortuneserver, погугли, и все будет нормуль.  smile 

PS: И не надо бездумно копипастить куски кода, нужно думать что там и для чего!

Это сообщение отредактировал(а) kuzulis - 23.12.2015, 11:59
PM MAIL   Вверх
math64
Дата 23.12.2015, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Цитата(kuzulis @  23.12.2015,  11:57 Найти цитируемый пост)
Если структура упакована, то и QDataStream не нужен

В данном случае нужен, чтобы поменять порядок байтов в address (у ТС сначала идёт старший байт).
PM   Вверх
7BON
Дата 24.12.2015, 10:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 20.11.2015

Репутация: нет
Всего: нет



math64 у меня несколько вопросов:
1. Правильно ли я прописал это в файле.h
Код

QDataStream &operator <<(QDataStream &out, const Frame &frame)
{
    out << frame.header << frame.command << frame.address << frame.reserved << frame.crc;

      return out;
}

QDataStream &operator >>(QDataStream &in, Frame1 &frame1)
{
    in >> frame1.header1 >> frame1.command1 >> frame1.emkost >>
            frame1.address1 >> frame1.zapros >> frame1.crc1;
    return in;
}

2. чтение осуществляю таким образом
Код

void MainWindow::readData()
{
    if (serial->bytesAvailable() < expectedFrameLength)
            return;
         serial->read(expectedFrameLength);



        frame1.header1 = 0xA5;
        frame1.command1 = 0x03;
        frame1.emkost;
        frame1.address1 = 0x0004;
        frame1.zapros = 0x0004;
        frame1.crc1 = frame1.header1^frame1.command1^frame1.emkost^frame1.address1^frame1.zapros;


        //in >> frame1;
        serial->read(frame1);

}

ошибка в последней строке. если использоваться будет QDataStream чтение по другому будет осуществляться или таким образом? и если можно показать напримере
3. 
Код

     data[3]=data[3]+0x02;// каждый адрес начинается с 0x02 с шагом 0x02
    if(data[3]==0x00)//условия сравнение если data[2]==0x00, то data[1]
                     //будет изменятся с шагом 0x01
        {
            data[2]=data[2]+0x01;
        }

Адрес таким образом можно менять или другим способом лучше?

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
math64
Дата 25.12.2015, 08:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



1. Нет operator << для записи массива. Поэтому вместо
Код

out << frame.reserved;

которое запишет строку
нужно
Код

for (int i = 0; i < sizeof(frame.reserved)/sizeof(frame.reserved[0]); i++)
   out << frame.reserved[i];

Поскольку
Код

QDataStream::BigEndian    QSysInfo::BigEndian    Most significant byte first (the default)

порядок байт по умолчанию при записи address - тот, который нужен.
Но при подсчете контрольной суммы нужно
Код

frame.crc = ... ^ (frame.address & 0xFF) ^ ((frame.address >> 8) & 0xFF) ^ ...;


Этого делать не нужно:
Код

serial->read(frame1);

Вы уже все прочитали:
Код

serial->read(expectedFrameLength);

но результат нужно было записать в QByteArray или массив:
Код

char data[expectedFrameLength];
serial->read(data, expectedFrameLength);
QBuffer buffer;
buffer.setData(data, expectedFrameLength);
buffer.open(QIODevice::ReadOnly);
QDataStream in(&buffer);


PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.1181 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.