Serial communication using multiple forms
-
Hello all,
I'm developing a GUI application (with multiple forms) to communicate with a serial device.
I have a class which has methods to communicate with hardware. I open Serial Port in this class's constructor as follows:tetra_grip_api::tetra_grip_api(QObject *parent) : QObject(parent) { serial = new QSerialPort(); serial->setPortName("com5"); serial->setBaudRate(1000000); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::HardwareControl); serial->open(QIODevice::ReadWrite); }
I want a permanent communication with the hardware when I open the application and navigate through the forms. In order to do this I call this class in the
main.cpp
as follows:int main(int argc, char *argv[]) { QApplication a(argc, argv); tetra_grip_api(); StageOneMain w; w.show(); return a.exec(); }
My question is what is correct method to use
signals and slot
mechanism to use the same serial port(opened in class) to send commands to hardware, for example if i press some button on a different form?In other words: How can I
connect
the serial object opened in the above mentionedtetra_grip_api
class in other forms?Please inform me if you need any other information from me.
Thank a lot !!
Vinil
-
Hello all,
I'm developing a GUI application (with multiple forms) to communicate with a serial device.
I have a class which has methods to communicate with hardware. I open Serial Port in this class's constructor as follows:tetra_grip_api::tetra_grip_api(QObject *parent) : QObject(parent) { serial = new QSerialPort(); serial->setPortName("com5"); serial->setBaudRate(1000000); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::HardwareControl); serial->open(QIODevice::ReadWrite); }
I want a permanent communication with the hardware when I open the application and navigate through the forms. In order to do this I call this class in the
main.cpp
as follows:int main(int argc, char *argv[]) { QApplication a(argc, argv); tetra_grip_api(); StageOneMain w; w.show(); return a.exec(); }
My question is what is correct method to use
signals and slot
mechanism to use the same serial port(opened in class) to send commands to hardware, for example if i press some button on a different form?In other words: How can I
connect
the serial object opened in the above mentionedtetra_grip_api
class in other forms?Please inform me if you need any other information from me.
Thank a lot !!
Vinil
@viniltc said in Serial communication using multiple forms:
How can I connect the serial object opened
Don't connect the serial port object itself. Define slots in tetra_grip_api and connect those to signals in your UI. To be able to connect you can pass the pointer to the tetra_grip_api instance to constructor of StageOneMain.
-
@jsulm thanks a lot for your suggestion.
Could you please provide an example.
Now I definedserial
as follows in the header file:class tetra_grip_api : public QObject { Q_OBJECT public: explicit tetra_grip_api(QObject *parent = nullptr); void static send_config_file(QByteArray config, bool nonvolatile); QSerialPort *serial; signals: public slots: }; #endif // TETRA_GRIP_API_H
Are you suggesting to make it as
public slot
? Can you give an example? -
Hi,
Can you give a bit more of details about what you are going to send to the device ?
-
@jsulm thanks a lot for your suggestion.
Could you please provide an example.
Now I definedserial
as follows in the header file:class tetra_grip_api : public QObject { Q_OBJECT public: explicit tetra_grip_api(QObject *parent = nullptr); void static send_config_file(QByteArray config, bool nonvolatile); QSerialPort *serial; signals: public slots: }; #endif // TETRA_GRIP_API_H
Are you suggesting to make it as
public slot
? Can you give an example?@viniltc Example for what? How to declare a slot? How to connect a signal to a slot?
Whether you need slots in tetra_grip_api or not depends on how you want to use it.
You can also use slots in your UI where you then call methods in tetra_grip_api. You just need to let the UI classes know about tetra_grip_api instance. For example:int main(int argc, char *argv[]) { QApplication a(argc, argv); tetra_grip_api api(); StageOneMain w(&api); w.show(); return a.exec(); }
Now StageOneMain can access public methods in the tetra_grip_api instance (you need to adapt tetra_grip_api constructor of course).
-
I will be writing/reading message packets from the device. For example , I created a class file called
tetra_grip_api
having functions to communicate with the serial device's registers as follows:void static send_config_file(QByteArray config, bool nonvolatile); void static send_long_register(uint8_t, uint32_t, uint8_t *); void static clear_stim_config(void); bool static send_short_block(STIM_GUI_MESSAGE_S_BLOCK_T *pblock); void static stimulation_pause(bool); void static stimulation_start(bool); void static toggle_pause(void); void static read_stim_status_reg(void); void static stimulation_set_current(unsigned int, unsigned int);
I defined these functions as
public
I also opened the serial port in the constructor oftetra_grip_api
as shown in the previous message.
I have multiple UI forms , but I need to call these API functions from any forms (to read/write to the device)I need a permanent connection with the device when I open the application, that's why I defined the serial configuration in the constructor of the API and called in the
main.cpp
.Then, for example , if I use objects in the UI forms , I should call the diffenert API functions mentioned above..
-
@viniltc Example for what? How to declare a slot? How to connect a signal to a slot?
Whether you need slots in tetra_grip_api or not depends on how you want to use it.
You can also use slots in your UI where you then call methods in tetra_grip_api. You just need to let the UI classes know about tetra_grip_api instance. For example:int main(int argc, char *argv[]) { QApplication a(argc, argv); tetra_grip_api api(); StageOneMain w(&api); w.show(); return a.exec(); }
Now StageOneMain can access public methods in the tetra_grip_api instance (you need to adapt tetra_grip_api constructor of course).
What should I define in
api
?I have different
public
functions within thetetra_grip_api
to communicate with the device (these functions are to create message blocks to communicate with registers in in the serail device
).But the first step is to open the serial port (that's why I defined serial open in the constructor of the
tetra_grip_api
) .For example I defined
tetra_grip_api
as follows:#include "tetra_grip_api.h" #include <QDebug> #include <QFile> #include <QMessageBox> #include <stdio.h> #include <stdlib.h> #define _CRT_SECURE_NO_DEPRECATE using namespace::std; tetra_grip_api::tetra_grip_api(QObject *parent) : QObject(parent) { } bool tetra_grip_api::send_short_block(STIM_GUI_MESSAGE_S_BLOCK_T *pblock) { contents.... } void tetra_grip_api::clear_stim_config(void) { contents.... } void tetra_grip_api::send_long_register(uint8_t reg, uint32_t data_len, uint8_t *data) { contents.... } void tetra_grip_api::send_config_file(QByteArray config, bool nonvolatile) { contents.... } void tetra_grip_api::stimulation_start(bool start) { contents.... } void tetra_grip_api::stimulation_pause(bool paused) { contents.... } void tetra_grip_api::stimulation_set_current(unsigned int channel_number) { contents.... } void tetra_grip_api::toggle_pause(void) { contents.... } void tetra_grip_api::read_stim_status_reg(void) { contents.... }
and
tetra_grip_api.h
as follows:#ifndef TETRA_GRIP_API_H #define TETRA_GRIP_API_H #include <QObject> #include "Stim_includes/stim_gui_protocol.h" #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> #define _CRT_SECURE_NO_DEPRECATE class tetra_grip_api : public QObject { Q_OBJECT public: explicit tetra_grip_api(QObject *parent = nullptr); void static send_config_file(QByteArray config, bool nonvolatile); void static send_long_register(uint8_t, uint32_t, uint8_t *); void static clear_stim_config(void); bool static send_short_block(STIM_GUI_MESSAGE_S_BLOCK_T *pblock); void static stimulation_pause(bool); void static stimulation_start(bool); void static toggle_pause(void); void static read_stim_status_reg(void); void static stimulation_set_current(unsigned int); signals: public slots: }; #endif // TETRA_GRIP_API_H
What I understood from your suggestion is to open serial port as
public slot
, also other serial functions like write/read data, something like this :private slots: void openSerialPort(); void writeData(const QByteArray &data); void readData();
Then If I use UI element in some forms, I need call API fucntion to create
message blocks
and to send to the serial device usingwriteData
.My doubt where should I open the serial. And how to use
signals and slot
mechanism in other UI forms to communicate with thetetra_grip_api
fucntions? -
What should I define in
api
?I have different
public
functions within thetetra_grip_api
to communicate with the device (these functions are to create message blocks to communicate with registers in in the serail device
).But the first step is to open the serial port (that's why I defined serial open in the constructor of the
tetra_grip_api
) .For example I defined
tetra_grip_api
as follows:#include "tetra_grip_api.h" #include <QDebug> #include <QFile> #include <QMessageBox> #include <stdio.h> #include <stdlib.h> #define _CRT_SECURE_NO_DEPRECATE using namespace::std; tetra_grip_api::tetra_grip_api(QObject *parent) : QObject(parent) { } bool tetra_grip_api::send_short_block(STIM_GUI_MESSAGE_S_BLOCK_T *pblock) { contents.... } void tetra_grip_api::clear_stim_config(void) { contents.... } void tetra_grip_api::send_long_register(uint8_t reg, uint32_t data_len, uint8_t *data) { contents.... } void tetra_grip_api::send_config_file(QByteArray config, bool nonvolatile) { contents.... } void tetra_grip_api::stimulation_start(bool start) { contents.... } void tetra_grip_api::stimulation_pause(bool paused) { contents.... } void tetra_grip_api::stimulation_set_current(unsigned int channel_number) { contents.... } void tetra_grip_api::toggle_pause(void) { contents.... } void tetra_grip_api::read_stim_status_reg(void) { contents.... }
and
tetra_grip_api.h
as follows:#ifndef TETRA_GRIP_API_H #define TETRA_GRIP_API_H #include <QObject> #include "Stim_includes/stim_gui_protocol.h" #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> #define _CRT_SECURE_NO_DEPRECATE class tetra_grip_api : public QObject { Q_OBJECT public: explicit tetra_grip_api(QObject *parent = nullptr); void static send_config_file(QByteArray config, bool nonvolatile); void static send_long_register(uint8_t, uint32_t, uint8_t *); void static clear_stim_config(void); bool static send_short_block(STIM_GUI_MESSAGE_S_BLOCK_T *pblock); void static stimulation_pause(bool); void static stimulation_start(bool); void static toggle_pause(void); void static read_stim_status_reg(void); void static stimulation_set_current(unsigned int); signals: public slots: }; #endif // TETRA_GRIP_API_H
What I understood from your suggestion is to open serial port as
public slot
, also other serial functions like write/read data, something like this :private slots: void openSerialPort(); void writeData(const QByteArray &data); void readData();
Then If I use UI element in some forms, I need call API fucntion to create
message blocks
and to send to the serial device usingwriteData
.My doubt where should I open the serial. And how to use
signals and slot
mechanism in other UI forms to communicate with thetetra_grip_api
fucntions?@viniltc said in Serial communication using multiple forms:
What should I define in api?
What do you mean? api is an instance of your tetra_grip_api class.
Define what ever you need there. -
@viniltc said in Serial communication using multiple forms:
What should I define in api?
What do you mean? api is an instance of your tetra_grip_api class.
Define what ever you need there.Sorry for not being clear enough
My doubt is: I have a number ofpublc
fucntions inside thetetra_grip_api
class , they are to create message packets and will be sent to device. ALSO, I have basic fucntions such asopenSerial
,writeData
andreadData
..you suggested to use instance of api in the
main
astetra_grip_api api();
So that means , I can access to any
public
functions andpublic slots
from the form (StageOneMain
) ?
What to define in the constructor?Any suggestions?
-
Sorry for not being clear enough
My doubt is: I have a number ofpublc
fucntions inside thetetra_grip_api
class , they are to create message packets and will be sent to device. ALSO, I have basic fucntions such asopenSerial
,writeData
andreadData
..you suggested to use instance of api in the
main
astetra_grip_api api();
So that means , I can access to any
public
functions andpublic slots
from the form (StageOneMain
) ?
What to define in the constructor?Any suggestions?
@viniltc said in Serial communication using multiple forms:
What to define in the constructor?
Which constructor do you mean? The one from StageOneMain? Well, simply store the pointer to tetra_grip_api in a member variable to be able to use it when needed:
StageOneMain::StageOneMain(tetra_grip_api *api) : m_api(api) { // Now you can access the public members in tetra_grip_api like m_api->open() }
-
@viniltc said in Serial communication using multiple forms:
What to define in the constructor?
Which constructor do you mean? The one from StageOneMain? Well, simply store the pointer to tetra_grip_api in a member variable to be able to use it when needed:
StageOneMain::StageOneMain(tetra_grip_api *api) : m_api(api) { // Now you can access the public members in tetra_grip_api like m_api->open() }
-
@jsulm
Thanks a lot for the feedback.In my case
StageOneMain
is a one of the form, defined as:StageOneMain::StageOneMain(QWidget *parent) : QMainWindow(parent)
In this case, how can I modify it in order to access public functions from
tetra_grip_api
?Hi
What @jsulm show is:
1:
Add a new variable in the StageOneMain class, in the .h file.
tetra_grip_api *m_api;
Note that you will need to type
class tetra_grip_api; in the top or include its .h file for it to know the
type there.
2:
Change constructor to accept a tetra_grip_api pointer from mainStageOneMain::StageOneMain(QWidget *parent, tetra_grip_api *api) : QMainWindow(parent), m_api(api)
here we change the constructor so that it can take a new parameter and
also store that new parameter in the class so we can use it anywhere in StageOneMain.That is the m_api(api) part. its like m_api = api; so we store the pointer in the class.
Now in all StageOneMain functions , you can use
m_api->xxxx to call any public function.I hope this is more clear ?
-
@mrjj Thanks a lot, now it's more clear.
I was wondering, what change I need to make to my
main.cpp
?
Right now i defined it as :int main(int argc, char *argv[]) { QApplication a(argc, argv); tetra_grip_api api(); StageOneMain w(&api); w.show(); return a.exec(); }
One more thing: I have a method in the
tetra_grip_api
calledopenSerial
(opening aQSerialPort*
calledserial
) to open the serial port as soon as I start the program, so I thought to call it in themain
. What's the correct method to call it? -
@mrjj Thanks a lot, now it's more clear.
I was wondering, what change I need to make to my
main.cpp
?
Right now i defined it as :int main(int argc, char *argv[]) { QApplication a(argc, argv); tetra_grip_api api(); StageOneMain w(&api); w.show(); return a.exec(); }
One more thing: I have a method in the
tetra_grip_api
calledopenSerial
(opening aQSerialPort*
calledserial
) to open the serial port as soon as I start the program, so I thought to call it in themain
. What's the correct method to call it?Hi
Super.Well if new ctor now looks like
StageOneMain::StageOneMain(QWidget *parent, tetra_grip_api *api)then in main
...
tetra_grip_api api;
StageOneMain w(nullptr, &api);// open serial
api.openSerial(xxx);