1
votes

I've been trying for more than a week to communicate from raspberry pi (QT C++) to Arduino (Arduino IDE c++) through a serial port but i keep failing.

I did some searching on google, read the example... and still i didn't succeeded. Ok so the basic thing is that i need to communicate continuously the serial port sent command from Raspberry pi to Arduino. I tried to keep the code as simple as possible.

Initially I'm sending "J" char from raspberry pi (QT C++) to Arduino (Arduino IDE c++) and waiting on that J, to make the LED blink on Arduino. But it doesn't work.. Even I didn't get any sample for interfacing & communicating & sending data raspberry pi (QT C++) to Arduino (Arduino IDE c++). I don't know what is the problem exactly. Kindly help me to solve the issue.

In monitor, 9600 baudrate

I have attached program what I have tried on both side.

main.cpp

#include <iostream>
#include <QIODevice>

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QString>

using namespace std;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    QSerialPort serialPort;
    serialPort.setBaudRate(QSerialPort::Baud9600);

    QSerialPortInfo info("ttyUSB0");
        qDebug() << "Name        : "     << info.portName();
        qDebug() << "Description : "     << info.description();
        qDebug() << "Busy:"              << info.isBusy();

        QSerialPort serial;
        serial.setPortName("ttyUSB0");

        serial.open(QIODevice::ReadWrite);
        serial.setBaudRate(QSerialPort::Baud9600);
        serial.setDataBits(QSerialPort::Data8);
        serial.setParity(QSerialPort::NoParity);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setFlowControl(QSerialPort::NoFlowControl);

        serial.open(QSerialPort::ReadWrite);
        cout<<"Readable    :"<<serial.isReadable()<<endl;
        cout<<"Writable    :"<<serial.isWritable()<<endl<<endl;

        if (serial.isOpen() && serial.isWritable())
        {
            qDebug() << "Is open : " << serial.isOpen() << endl;
            qDebug() << "Is writable : " << serial.isWritable() << endl;

            qDebug() << "Ready..." << endl;
            serial.write("J");

            QByteArray ba("J\n");

            serial.write(ba);
            {
                QByteArray ba("J");
                serial.write(ba);
                serial.flush();
                qDebug() << "data has been send" << endl;
                serial.close();
            }
            if (serial.bytesToWrite() > 0)
            {
                serial.flush();
                if(serial.waitForBytesWritten(1000))
                {
                    qDebug() << "data has been send" << endl;
                }
            }
            if(serial.flush())
                {
                    qDebug() << "ok" << endl;
                }
                qDebug() <<"value sent "<< endl;
                serial.close();
        }
        else
        {
            qDebug() << "An error occured" << endl;
        }
    return a.exec();
}

Arduino code:

int led = 13, avlb = 0;

void setup() 
{ 
Serial.begin(9600); 
pinMode(led, OUTPUT); 
Serial.println("started");
}

void loop() 
{ 

 if (Serial.available() > 0)
{
    Serial.println("available");
    Serial.println(Serial.available());  
    delay(2000); 
    digitalWrite(led, HIGH);  
    delay(5000);           

  if(Serial.read() == 'J')
 {
   Serial.println("read");
   Serial.println(Serial.read());
   delay(2000);
   digitalWrite(led, LOW);   
   delay(1000);  
 }  
}

else
 {
   Serial.println("not available");
   delay(1000);
 }
}

Output Displayed:

Raspberry qt creator ide o/p:

Name        :  "ttyUSB0"
Description :  "FT232R USB UART"
Busy: false

Readable    :1
Writable    :1

Is open :  true 

Is writable :  true 

Ready... 

data has been send 

bool QSerialPort::flush(): device not open
value sent

Arduino Ide Output displayed:

started

not available
not available
not available
not available
not available
not available
not available
not available
not available
2

2 Answers

1
votes

I would suggest 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 it's not blocking io thread of QSerialPort.

I usually use readyRead singal or I use waitForBytesWritten and waitForReadReady combination.You should take a look at the QtSerialPort examples. You'll find there several possible implementations depending on your application needs.

You can try this, it will work fine.

#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("ttyUSB0");
    serial.open(QIODevice::ReadWrite);

       serial.setBaudRate(QSerialPort::Baud9600);
       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();
}
0
votes

The answer to your question is in the following code:

QByteArray ba("J");
serial.write(ba);
serial.flush();
qDebug() << "data has been send" << endl;
serial.close();

After you make serial.flush (), you immediately close the port. It is necessary to wait until the data is really sent. For example, using bool QSerialPort :: waitForBytesWritten (int msecs).