Sending a data to Arduino through serial port using Qt
-
Hi all, I want to send and receive data between arduino and computer through serial port. I programmed my Arduino such that when I send the character "a", it responds by sending a string "12334ı485" (just an example). It works when I use Arduino IDE serial monitor. However I need to send and receive data in a Qt project. I wrote this code but it does not work and what I get is this: http://i.hizliresim.com/VaLGWV.png
Here is my code
#include <iostream> #include <QSerialPort> #include <QSerialPortInfo> #include <QDebug> #include <windows.h> QSerialPort serial; using namespace std; int main() { serial.setPortName("COM18"); serial.setBaudRate(QSerialPort::Baud9600); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); serial.open(QIODevice::ReadWrite); QByteArray data="a"; serial.write(data); while(!serial.isOpen()) serial.open(QIODevice::ReadWrite); while(1){ serial.write(data); Sleep(1500); QByteArray ba; ba=serial.readAll(); qDebug()<<ba; } }
-
Hi,
You should take a look at the QtSerialPort examples. You'll find there several possible implementations depending on your application needs.
-
Hi,
You should take a look at the QtSerialPort examples. You'll find there several possible implementations depending on your application needs.
-
Hi, I would sugget you to read about how Qt event system works. All Qt IODevice derived classes work asynchronously. You need to use QApplication in order to host its object system. After that you need to change your code so that its not blocking io thread of QSerialPort.
-
Hi, I would sugget you to read about how Qt event system works. All Qt IODevice derived classes work asynchronously. You need to use QApplication in order to host its object system. After that you need to change your code so that its not blocking io thread of QSerialPort.
@asanka424 Thanks I have solved the problem but this time I have another problem. When I connect the arduino with the usb cable my code works perfectly, but I when I use bluetooth module it does not work correctly. To show what the problem is I will share secreenshot of output with usb cable and bluetooth module.
With USB cable: http://i.hizliresim.com/MpWPPQ.png
With bluetooth: http://i.hizliresim.com/Va6gAr.pngAs you can see when working with bluetooth it sometimes get the data wrong.
Why does it happen?My code is here:
#include <QCoreApplication> #include <iostream> #include <QSerialPort> #include <QDebug> #include <Windows.h> using namespace std; QSerialPort serial; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); serial.setPortName("COM21"); serial.open(QIODevice::ReadWrite); serial.setBaudRate(QSerialPort::Baud115200); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); while(!serial.isOpen()) serial.open(QIODevice::ReadWrite); if (serial.isOpen() && serial.isWritable()) { qDebug() << "Serial is open"; QByteArray output; QByteArray input; while(true) { output = "a"; serial.write(output); serial.flush(); serial.waitForBytesWritten(1000); serial.waitForReadyRead(1000); input = serial.readAll(); qDebug()<<input; } } return a.exec(); }
-
The data you receive is not wrong it's just that you don't receive it at the same pace with both devices e.g. the underlying buffer are handled differently. But all in all the data is the same.
-
The data you receive is not wrong it's just that you don't receive it at the same pace with both devices e.g. the underlying buffer are handled differently. But all in all the data is the same.
-
IMO 2 options:
- QSerialPort::readData() - make your program read data of given length
http://doc.qt.io/qt-5/qserialport.html#readData - QSerialPort::bytesAvailable() - check if there is expected number of bytes available
http://doc.qt.io/qt-5/qserialport.html#bytesAvailable
- QSerialPort::readData() - make your program read data of given length
-
IMO 2 options:
- QSerialPort::readData() - make your program read data of given length
http://doc.qt.io/qt-5/qserialport.html#readData - QSerialPort::bytesAvailable() - check if there is expected number of bytes available
http://doc.qt.io/qt-5/qserialport.html#bytesAvailable
@michelson That works, thanks. I want to share final version of the code
#include <QCoreApplication> #include <iostream> #include <QSerialPort> #include <QDebug> #include <Windows.h> #include <QElapsedTimer> using namespace std; QSerialPort serial; QElapsedTimer timer; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); serial.setPortName("COM21"); serial.open(QIODevice::ReadWrite); serial.setBaudRate(QSerialPort::Baud115200); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); while(!serial.isOpen()) serial.open(QIODevice::ReadWrite); if (serial.isOpen() && serial.isWritable()) { qDebug() << "Serial is open"; QByteArray output; QByteArray input; while(true) { output = "a"; serial.write(output); serial.flush(); timer.start(); // Sleep(80); qDebug() << timer.elapsed(); serial.waitForBytesWritten(100); serial.waitForReadyRead(100); if(serial.bytesAvailable()>=18) input = serial.read(18); qDebug()<<input; } } return a.exec(); }
- QSerialPort::readData() - make your program read data of given length
-
That while on isOpen is just plain wrong. You already opened the serial port and if for any reason if fails to open you'r going to get stuck in that loop.
Do the check on the first open and act accordingly.
-
That while on isOpen is just plain wrong. You already opened the serial port and if for any reason if fails to open you'r going to get stuck in that loop.
Do the check on the first open and act accordingly.
@SGaist
I add this option because sometimes the computer cannot connect to the bluetooth module, therefore if it cannot connect the first time I want my program to try connecting bluetooth module again, but anyway I exluded this option, since I am using GUI in my project. -
Then add a "Try Again" button to your GUI. It will be cleaner.
-
@michelson That works, thanks. I want to share final version of the code
#include <QCoreApplication> #include <iostream> #include <QSerialPort> #include <QDebug> #include <Windows.h> #include <QElapsedTimer> using namespace std; QSerialPort serial; QElapsedTimer timer; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); serial.setPortName("COM21"); serial.open(QIODevice::ReadWrite); serial.setBaudRate(QSerialPort::Baud115200); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); while(!serial.isOpen()) serial.open(QIODevice::ReadWrite); if (serial.isOpen() && serial.isWritable()) { qDebug() << "Serial is open"; QByteArray output; QByteArray input; while(true) { output = "a"; serial.write(output); serial.flush(); timer.start(); // Sleep(80); qDebug() << timer.elapsed(); serial.waitForBytesWritten(100); serial.waitForReadyRead(100); if(serial.bytesAvailable()>=18) input = serial.read(18); qDebug()<<input; } } return a.exec(); }
@brotify could you show me the IDE code