I'm writing a Qt GUI application that receives and sends data to an Arduino over serial. It writes correctly, but when trying to read it doesn't work.
My problem is:
I have an Arduino code that sends things over Serial, I programmed it to turn on and off a LED on pin 13 depending on the received data:
#define ARDUINO_TURNED_LED_ON "LEDON"
#define ARDUINO_TURNED_LED_OFF "LEDOFF"
#define PC_REQUESTED_LED_STATE_CHANGE u8"CHANGELED"
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13, OUTPUT);
}
String serialCmd = "";
bool ledState=false;
void loop()
{
// put your main code here, to run repeatedly:
if (Serial.available())
{
serialCmd=Serial.readString();
if (serialCmd==PC_REQUESTED_LED_STATE_CHANGE)
{
if (ledState)
{
digitalWrite(13, LOW);
Serial.write(ARDUINO_TURNED_LED_OFF);
}
else
{
digitalWrite(13, HIGH);
Serial.write(ARDUINO_TURNED_LED_ON);
};
ledState=!ledState;
serialCmd = "";
}
}
}
I'm using the following signal and slot at MainWindow class:
#define ARDUINO_TURNED_LED_ON "LEDON"
#define ARDUINO_TURNED_LED_OFF "LEDOFF"
#define PC_REQUESTED_LED_STATE_CHANGE u8"CHANGELED"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
/* Create Object the Class QSerialPort*/
serialPort = new QSerialPort(this);
/* Create Object the Class Arduino to manipulate read/write*/
arduino = new Arduino(serialPort);
//connect signal:
connect(serialPort, SIGNAL(readyRead()), this, SLOT(ReadData()));
}
//slot
void MainWindow::ReadData()
{
QString received = arduino->Read();
qDebug() << "received data:" << received;
if (received==ARDUINO_TURNED_LED_ON)
{
qDebug() << "led on";
}
else if (received==ARDUINO_TURNED_LED_OFF)
{
qDebug() << "led off";
}
}
And the Arduino::Read() method that is called by the previous slot:
QString Arduino::Read()
{
QString bufRxSerial;
qDebug() << "bytes available:" << serialPort->bytesAvailable();
/* Awaits read all the data before continuing */
while (serialPort->waitForReadyRead(20)) {
bufRxSerial += serialPort->readAll();
}
return bufRxSerial;
}
When writing to the Arduino it works well, the LED changes as it should, the problem happens when Qt tries to read the replied data.
In most of the times that the Arduino sends something, the signal is emitted and serialPort->bytesAvailable() returns a number that is not zero, but serialPort->waitForReadyRead(20) times out without receiving anything and serialPort->readAll() returns an empty QString. If I use serialPort->waitForReadyRead(-1) the window freezes.
The weirdest thing is that, in a random moment that something is sent, everything works well and the function returns all the data that couldn't be read previously.
Here's an example of what happens:
1st attempt (fails)
Qt writes PC_REQUESTED_LED_STATE_CHANGE (u8"CHANGELED") to the serial port
Arduino LED changes its state (turns on)
Arduino writes ARDUINO_TURNED_LED_ON ("LEDON") to the serial port
Qt reads an empty QString from the Arduino
2nd attempt (fails)
Qt writes PC_REQUESTED_LED_STATE_CHANGE (u8"CHANGELED") to the serial port
Arduino LED changes its state (turns off)
Arduino writes ARDUINO_TURNED_LED_OFF ("LEDOFF") to the serial port
Qt reads an empty QString from the Arduino
3rd attempt (this is a random attempt that everything works)
Qt writes PC_REQUESTED_LED_STATE_CHANGE (u8"CHANGELED") to the serial port
Arduino LED changes its state (turns on)
Arduino writes ARDUINO_TURNED_LED_ON ("LEDON") to the serial port
Qt reads "LEDONLEDOFFLEDON" from the Arduino, that is everything that couldn't be read previosly.
4th attempt (fails)
Qt writes PC_REQUESTED_LED_STATE_CHANGE (u8"CHANGELED") to the serial port
Arduino LED changes its state (turns off)
Arduino writes ARDUINO_TURNED_LED_OFF ("LEDOFF") to the serial port
Qt reads an empty QString from the Arduino
5th attempt (this is another random attempt that everything works)
Qt writes PC_REQUESTED_LED_STATE_CHANGE (u8"CHANGELED") to the serial port
Arduino LED changes its state (turns on)
Arduino writes ARDUINO_TURNED_LED_ON ("LEDON") to the serial port
Qt reads "LEDOFFLEDON" from the Arduino, that is everything that couldn't be read previosly.
I tested using the Arduino IDE serial monitor and it worked as it was supposed to be: I wrote "CHANGELED", then the LED changed and the Arduino replied "LEDON" or "LEDOFF" all the times.
What can I do to solve this problem? Thanks
Edit: the complete code can be found here
20
inserialPort->waitForReadyRead(20)
? – eyllanesc