PDA

View Full Version : How to combine two projects



annaraluca
1st June 2016, 19:54
Hi! I have two separate projects: one that reads Arduino data from a serial port and another one that plots a real time graph. I want to use the data from the first one as input for the second project and plot the data from Arduino in real time. I've tried to copy/paste the second project into the first one but I didn't get anywhere. How cand I solve this?

wysota
1st June 2016, 20:01
You can either invoke one executable from the other and communicate with it using stdin/stdout or you can merge them both into one project e.g. the way you tried (we didn't know what went wrong though).

annaraluca
2nd June 2016, 13:13
Thank you for your response! I will try to explain what I did.When I merge them, only the first project runs and reads the data from the serial port,but the graph doesn't appear.
I have the following files: First project:
eda.pro
serialportreader.h
main.cpp
serialportreader.cpp and for the second project:

plot.pro
qcustomplot.h
mainwindow.h
qcustomplot.cpp
main_g.cpp
mainwindow.cpp
mainwindow.ui.
I don't know if I did the right thing, but I just made another project with all those files and a single .pro. Why is not main_g.cpp running too?

d_stranz
2nd June 2016, 16:57
A program cannot have two main() routines. The C runtime automatically looks for the method main() and uses it as the entry point for your program (that is, it calls that routine to start your program code's execution). If you renamed the "main()" from your Qt program to "main_g()" (as the name of your file implies), what did you do to cause it to execute? Nothing, apparently, since you don't see your GUI.

You can't just naively dump all the source files for two programs into the same project, compile and link it (if it compiles and links at all, which it probably didn't, given that you renamed one of your main.cpp modules), and expect it to just run. The compiler, linker, and runtime can't read your mind. They do what you tell them to do. Looks like you told it to read serial data and nothing else.

So, you need to take a step back and think about what you want your program to do, and how to get it to do that.

0 - Start the program and get the serial port reader active and GUI visible
1 - Read data from the serial port
2 - Store that data somewhere so it can be plotted
3 - Plot new data
4 - Keep everything running in real time so both the serial port and plot stay "live"

Start with the original main() for your custom plot program. Add the appropriate code from the other main() (serial reader) to the plot program's main(), then delete the other main.cpp from your project.

In this main() you need to connect whatever signals your serial reader generates to a slot (which you will probably need to create and write code for) in your MainWindow class that will store the data somewhere (and you'll need to invent a data structure for that, too). You will also need to connect whatever the plot needs to update itself to a method in MainWindow. I don't know QCustomPlot in detail, but there is probably a slot that should be called to tell it that the data has changed and to replot itself.

In order to keep the GUI and serial reader "live", you must do all of this within Qt's event loop. If you write something like a while() loop that repeatedly tries to read data from the serial port, this will lock up your GUI and nothing will be updated despite new data coming in. So use Qt's signal and slot mechanism and let the event loop tell your program (via a slot connected to a serial port signal) that new data is available. And let your program tell the plot (via a signal connected to a slot in the plot class) that the data has changed and it needs to update. And if neither of those things is happening for a while, then the event loop just runs and keeps the GUI active.

annaraluca
6th June 2016, 11:20
Thank you! I have one last error, when I try to call the function that reads serial data, from mainwindow.cpp, and it says : C2664: ' QByteArray:: (QByteArrayDataPtr)': cannot convert argument 1 from 'QByteRef' to 'const char*'. No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called.
The method from serialportreader.cpp is:


QByteArray SerialPortReader::_read_callback()
{
QByteArray data = _serial->readAll();
int sz = data.size();

for(int i=0;i<sz;i++)
if((int)data[i] != 13 && (int)data[i] != 10)
return (data[i]);
}

And in mainwindow.cpp I have the following function that calls the above :


void MainWindow::realtimeDataSlot()
{
double key = QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0;
static double lastPointKey = 0;
if (key-lastPointKey > 0.01)
{
SerialPortReader value;
QByteArray value0=value._read_callback();

ui->customPlot->graph(0)->addData(key, value0);
ui->customPlot->graph(1)->clearData();
ui->customPlot->graph(1)->addData(key, value0);

ui->customPlot->graph(0)->rescaleValueAxis();
lastPointKey = key;
}
ui->customPlot->xAxis->setRange(key+0.25, 8, Qt::AlignRight);
ui->customPlot->replot();
}

Lesiok
6th June 2016, 11:40
The return from QByteArray SerialPortReader::_read_callback() should look like :
return data;

annaraluca
6th June 2016, 11:56
I don't want to return all the data because on my Arduino data[1] is always 13 (carriage return) and data[2] is always 10 (new line), so I am only interested in data[0].

Lesiok
6th June 2016, 12:31
The method SerialPortReader::_read_callback() is messy.
1. Why it is defined as "return QByteArray" if it really returns only one byte ?
2. If the data does not contain CRLF this method returns a random value if at all to compile.