Por que es necesario usar write() junto con waitForBytesWritten() ????

138 views
Skip to first unread message

2050f...@gmail.com

unread,
Nov 25, 2014, 12:34:39 PM11/25/14
to qt-es...@googlegroups.com
Buenas tardes,
Me gustaria amablemente preguntarles porque siempre que quiero enviar por puerto serial algun dato, pues siempre es necesario usar aparte de la funcion write() la funcion
waitForBytesWritten() ...... sin esta ultima nada funciona ...... alguien me puede esclarecer esta situacion. He preguntado bastante a mis companeros de clase, pero nadie entiende como realmente funciona.
Si funcionaria bien todo estaria ok ........ pero funciona como deberia. Estoy usando Terminal V1.9b para poder leer los datos que envio pero dichos datos se leen dos veces si se envia hola, en el Terminal V1.9b se lee
holahola ...................... aqui les dejo mi codigo el cual es muy facil, pero no funciona como deberia ser.


#include <QtSerialPort/QSerialPort>
#include <QTextStream>
#include <QCoreApplication>
#include <QFile>
#include <QStringList>
#include <QDebug>

QT_USE_NAMESPACE

int main(int argc, char *argv[])
{
QCoreApplication coreApplication(argc, argv);

QTextStream standardOutput(stdout);

QSerialPort serialPort;
QString serialPortName = "COM1";
serialPort.setPortName(serialPortName);
serialPort.setBaudRate(QSerialPort::Baud9600);

if (!serialPort.open(QIODevice::ReadWrite)) {
standardOutput << "error" << endl;
return 1;
}

QByteArray readData;

qint64 bytesWritten = serialPort.write("something"); serialPort.waitForBytesWritten(2000);

for (;;)
{
   if (serialPort.bytesAvailable() > 0 || serialPort.waitForReadyRead(2000))
{
readData = serialPort.readAll();
qint64 bytesWritten = serialPort.write(readData); serialPort.waitForBytesWritten(2000);
}

 }

return 0;
}



MUCHAS gracias por su ayuda, en forma fisica el puerto COM1 esta conectado con el puerto COM11. Y el programa Terminal V1.9b esta conectado al COM11. El programa primero deberia enviar something y lo envia bien solo una vez !!! . Pero cuando envio como dije hola, pues en el Terminal V1.9b se lee holahola .................. y esto esta mal. Gracias de antemano por sus consejos. 









Lisandro Damián Nicanor Pérez

unread,
Nov 25, 2014, 3:47:55 PM11/25/14
to qt-es...@googlegroups.com
On Tuesday 25 November 2014 09:34:38 2050f...@gmail.com wrote:
> Buenas tardes,
> Me gustaria amablemente preguntarles porque siempre que quiero enviar por
> puerto serial algun dato, pues siempre es necesario usar aparte de la
> funcion write() la funcion
> waitForBytesWritten() ......

Veamos: la documentación de QSerialPort::waitForBytesWritten[0] redirije a las
de QIODevice[1].

[0] <http://qt-project.org/doc/qt-5/qserialport.html#waitForBytesWritten>
[1] <http://qt-project.org/doc/qt-5/qiodevice.html#waitForBytesWritten>

En ésta última se lee:

For buffered devices, this function waits until a payload of buffered
written data has been written to the device and the bytesWritten() signal
has been emitted, or until msecs milliseconds have passed. If msecs is -1,
this function will not time out. For unbuffered devices, it returns
immediately.

El puerto serie es un dispositivo con buffer, por lo que aplica lo anterior.

> sin esta ultima nada funciona ......

¿A que te referís con "no funciona"? Es decir, sé mas explícito :) Necesitamos
entender cuál es el problema.

> alguien
> me puede esclarecer esta situacion. He preguntado bastante a mis companeros
> de clase, pero nadie entiende como realmente funciona.
> Si funcionaria bien todo estaria ok ........ pero funciona como deberia.
> Estoy usando Terminal V1.9b para poder leer los datos que envio pero dichos
> datos se leen dos veces si se envia hola, en el Terminal V1.9b se lee
> holahola ......................

Si el hola inicial lo escribiste en ésa terminal lo vas a ver dos veces: una
por la vez que lo tipeaste (las terminales suelen tener el echo encendido) y
otra por la que lo recibiste. Es decir, está andando bien.

> aqui les dejo mi codigo el cual es muy
> facil, pero no funciona como deberia ser.

[snip código]

El código ese funciona sin el event loop de Qt, por lo que te estás perdiendo
gra parte de su funcionalidad.


--
"Waaah! Debian never keeps its release schedules!"
Okay, lets make a Debian-like distribution that hits its schedules and is
close to bleeding edge.
"Waaah! Ubuntu ships buggy stuff!"
Grrrrrr.
(Not aimed at jwb in particular, BTW. Just pointing out that there's always
going to be some disappointed people.)
vmole (subscriber, #111) - http://lwn.net/Articles/279111/

Lisandro Damián Nicanor Pérez Meyer
http://perezmeyer.com.ar/
http://perezmeyer.blogspot.com/
signature.asc

2050f...@gmail.com

unread,
Nov 26, 2014, 12:48:15 PM11/26/14
to qt-es...@googlegroups.com
Buenas tardes,
Muchas gracias por sus respuestas, me sirvieron para hacer un analisis profundo de como poder corregir ese pequeno codigo. El problema de la duplicacion de la palabrita hola, la he corregido quitando el metodo bytesAvailable. De este modo se escribe la palabra test en el Terminal V1.9b y se lee en el mismo terminal test, solo una vez. El hecho es que funciona, pero aun no me queda claro que influencia tuvo esa funcion para que en la terminal se escriba la palabra dos veces????, leyendo la documentacion sobre esa funcion regresa la cantidad de Bytes disponibles para lectura, no me habla nada de duplicidad al momento de enviar.
Me parece que lo que hice fue suerte de principiante, pero cuando el profesor me pregunte el por que y como ????? pues temo que me clave un cero mas grande que mi cabeza que ni me va a dejar entrar a mi casa, y tendria que ir acostumbrandome a hacerle compania al Fido (el perro).
Agradecere muchismo su ayuda con este caso que esta interesante pero no logro aun tener muchas cosas claras ...... Muchas gracias por su majestuosa explicacion de antemano.
Cordiales saludos.

Lisandro Damián Nicanor Pérez

unread,
Nov 29, 2014, 6:31:57 PM11/29/14
to qt-es...@googlegroups.com
On Wednesday 26 November 2014 09:48:15 2050f...@gmail.com wrote:
> Buenas tardes,
> Muchas gracias por sus respuestas, me sirvieron para hacer un analisis
> profundo de como poder corregir ese pequeno codigo. El problema de la
> duplicacion de la palabrita hola, la he corregido quitando el metodo
> bytesAvailable.

¿Y el código?


--
#exclude <windows.h>
signature.asc

2050f...@gmail.com

unread,
Dec 1, 2014, 3:20:48 AM12/1/14
to qt-es...@googlegroups.com
Buenos dias,
Pues el codigo esta en el primer mensaje de este debate.
Si no lo puede leer, por favor digamelo.
Que tenga un lindo inicio de semana.
Cordiales saludos

2050f...@gmail.com

unread,
Dec 5, 2014, 3:24:37 AM12/5/14
to qt-es...@googlegroups.com
Buenos dias estimado Damian,
Durante esta semana he estado trabajando en la solucion del problema, pero desgraciadamente aun no he podido solucionar el problema. Aqui le envio el programita y una foto adjunta para que vea que es lo que realmente hace.
El problema esta en que al enviar por el Terminal V1,9b la palabra test, en la consola se escribe la palabra test pero dos veces, igualmente en el Terminal V1,9b (ver foto) . Aqui en la clase, pues nadie tiene idea de lo que podria estar pasando, he estado leyendo sobre el famoso eco de la terminal, pero aqui el profe me dijo, que no hay fundamento para aceptar una respuesta asi, y que estoy haciendo las cosas mal, pero no se en donde estoy haciendo cometiendo el error, y he buscado bastante con respecto a este caso, pero lastimosamente no he podido solucionar el problema.
Muchas gracias de antemano por su respuesta, y que tenga un lindo dia.
Cordiales saludos ........... Aqui esta el codigo :

#include <QtSerialPort/QtSerialPort>
#include <QtCore/QCoreApplication>
#include <QStringRef>
#include <QString>
#include <QDebug>
#include <iostream>
#include <string>

using namespace std;


int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QSerialPort SerialPort;

/*=======================================================================================================#1
Serial Port Configuration :
-------------------------
=======================================================================================================*/

SerialPort.setPortName("COM1");
SerialPort.setBaudRate(QSerialPort::Baud9600);
SerialPort.setDataBits(QSerialPort::Data8);
SerialPort.setParity(QSerialPort::NoParity);
SerialPort.setStopBits(QSerialPort::OneStop);
SerialPort.setFlowControl(QSerialPort::NoFlowControl);
SerialPort.open(QIODevice::ReadWrite);

/*=======================================================================================================#1*/


qDebug() << "\nStart :" << endl;
qDebug() << "=========\n" << endl;

for (;;)
{
if (SerialPort.bytesAvailable() > 0 || SerialPort.waitForReadyRead(100))

{

QByteArray Data;
Data = SerialPort.read(4);

qDebug() << Data << endl;

SerialPort.write(Data);
if (!SerialPort.waitForBytesWritten(100))
{
qDebug() << "an error occurred \n" << endl;
}
}
}

SerialPort.close();
return 0; //a.exec();
}
error.jpg

Juancar

unread,
Dec 5, 2014, 12:36:46 PM12/5/14
to qt-es...@googlegroups.com
Hola,

Sencillamente ese método "serialPort.bytesAvailable()" no debería estar dentro de la condición del if, lo puedes usar pero es para saber cuantos bytes tienes disponibles para leer, además lo pones como primera condición con el operador OR ( || ) por lo que siempre que haya "algo que leer" será distinto de 0 o TRUE, luego tienes la otra parte de la condición "serialPort.waitForReadyRead(2000)" Que solo se evaluará cuando la función anterior de 0. En este caso si lo que quieres garantizar es que el buffer esté preparado para ser leído y que contenga datos lo suyo sería lo siguiente:
 if ( serialPort.waitForReadyRead(2000) && serialPort.bytesAvailable() > 0)
   {

Si lo cambias por el siguiente código:
qint64 count;
 if ( serialPort.waitForReadyRead(2000) &&(count = serialPort.bytesAvailable()) > 0)
   {

En la variable count tendrás el número de bytes disponibles aprovechando la asignación para incluirla como condición, si no te gusta siempre se puede anidar el if y quedaría de esta otra forma:
 if ( serialPort.waitForReadyRead(2000)
  {
      count = serialPort.bytesAvailable()
      if ( count > 0)
      {
        ...
        ...
        ...
      } 
   }

Siempre hay que tener mucho cuidado con las condiciones y tener muy claro como se evalúan.

Saludos

   {

2050f...@gmail.com

unread,
Dec 5, 2014, 2:06:19 PM12/5/14
to qt-es...@googlegroups.com
Buenas tardes Juancar,
Gracias por tu valiosa respuesta, me ha ayudado a esclarecer este problema. Pero haciendo las modificaciones que recomiendas, pues me genera otro problemita. Del Terminal V1.9b envio la palabra exit por partes osea, "e" luego "x" luego "i" y finalmente "t", cada letra la envia sin problemas y solo una vez tanto a la consola como de vuelta al Terminal V1.9b, el problema esta cuando nuevamente quiero enviar la palabra exit, de nuevo por partes, es cuando en la consola me escribe esto :

"e"

"x"

"i"

"t"

"ex"

"exit"

"itex"

"exex"

El primer exit funciona bien, pero el segundo sale con regalo incluido, mi pregunta es porque a la letra que envio le agrega letras que ya han sido enviadas???? ahora lo bueno es que las envia a la consola y al terminal V1.9b solo una vez.
He probado enviando la palabra test entera dos veces y luego la palabra prueba, pues en la consola me escribe test test y la tercera deberia de ser la palabra prueba, pero no en la consola me escribe test nuevamente............................ :(
Me podria dar su punto de vista??. Muchisimas gracias de antemano por su respuesta. Cordiales exitos.

Juancar

unread,
Dec 6, 2014, 7:22:42 AM12/6/14
to qt-es...@googlegroups.com
Hola,

Sin ver como estás leyendo exactamente del buffer solo puedo especular, pero tiene todos los síntomas de que el buffer no está vacío y lees todo su contenido, para que eso no ocurra hay que limpiar el buffer cada vez que se lee. Recuerdo que en C había que limpiarlo porque las funciones de lectura no lo hacían.

Lo mejor es que pongas el código que usas ahora para leer del puerto serie, para ver si el método que usas de lectura no es el mas adecuado.

2050f...@gmail.com

unread,
Dec 8, 2014, 3:34:45 AM12/8/14
to qt-es...@googlegroups.com
Buenos dias Juancar,
Muchas gracias por tu respuesta. Es precisamente la conclusion a la que yo tambien he legado que el buffer parece no estar del todo limpio. El codigo que estoy usando para lectura y envio es bien sencillo, y es el siguiente :


#include <QtSerialPort/QtSerialPort>
#include <QtCore/QCoreApplication>
#include <QStringRef>
#include <QString>
#include <QDebug>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QSerialPort SerialPort;

/*=======================================================================================================#1
Serial Port Configuration :
-------------------------
=======================================================================================================*/

SerialPort.setPortName("COM1");
SerialPort.setBaudRate(QSerialPort::Baud9600);
SerialPort.setDataBits(QSerialPort::Data8);
SerialPort.setParity(QSerialPort::NoParity);
SerialPort.setStopBits(QSerialPort::OneStop);
SerialPort.setFlowControl(QSerialPort::NoFlowControl);
SerialPort.open(QIODevice::ReadWrite);

/*=======================================================================================================#1*/


qDebug() << "\nStart :" << endl;
qDebug() << "=========\n" << endl;

for (;;)
{
//if (SerialPort.bytesAvailable() > 0 || SerialPort.waitForReadyRead(100))


if (SerialPort.waitForReadyRead(2000) && SerialPort.bytesAvailable() > 0)


{

QByteArray Data;
Data = SerialPort.read(4);

qDebug() << Data << endl;

SerialPort.write(Data);
if (!SerialPort.waitForBytesWritten(100))
{
qDebug() << "an error occurred \n" << endl;
}
}
}

SerialPort.close();
return 0; //a.exec();
}

Me gustaria preguntarle como es que podria de una manera determinante decir que realmente el buffer esta sucio. Por ejemplo, en este instante envio la palabra "test" y me envia de regreso al Terminal V1.9b la palabra "testtest" y en la consola pasa lo mismo, como podria afirmar que esta realmente sucio si en este momento justo antes de escribir la palabra "test" pues supuestamente no deberia haber nada en el buffer, y apenas escribo dicha palabra el programita que estoy usando pues la dobletea "testtest", por que la dobletea ?? :(
Sobre las funciones de lectura ya sea .read() o .readAll() en Qt pues no hablan nada al respecto de si limpian o no el buffer, es mas este aspecto ni lo toman en consideracion durante la documentacion. Aqui los companeros lo unico que dicen es, estas haciendo las cosas mal, Qt es poderoso que hasta el Android esta hecho el Qt, Skype y blablabla ...... todas esas cosas que solo desmoralizan a la persona, pero no se atreven a dar un comentario constructivo el cual me ayude a solucionar el problema, bueno queda confiar en Dios que al final se vera una luz al final del tunel :)
Mis mas cordiales saludos y que tenga un lindo dia.

Juancar

unread,
Dec 8, 2014, 6:18:25 AM12/8/14
to qt-es...@googlegroups.com
Hola,

Lo primero, ¿Porque usas Data = SerialPort.read(4); ?
mejor usa:
 if ( serialPort.waitForReadyRead(
2000)
  {
      count = serialPort.bytesAvailable()
      if ( count > 0)
      {
        Data = SerialPort.read(count);
        ...
        ...
        ...
      } 
   }

Así tu código leerá los caracteres que han llegado, si no te gusta usa readAll()

Sobre el problema de la repetición... ¿Usas el mismo puerto para leer y escribir? ¿Te has preguntado que puede pasar si al escribir en él permanecen los datos? Con tu código lo que estás leyendo la segunda vez es lo que escribiste. Limpia el buffer una vez que hayas enviado los datos con el método clear() si quieres controlar que limpias el buffer tanto en lectura como en escritura mira la documentación para pasar los parámetros adecuados al método clear(). Sin parámetros limpia tanto la lectura como la escritura.

Saludos.

2050f...@gmail.com

unread,
Dec 8, 2014, 12:52:14 PM12/8/14
to qt-es...@googlegroups.com
Buenas noches estimado Juancar,
Muchas gracias por tus respuestas. He usado la funcion clear() con argumento de entrada y salida, y cuando envia los datos al Terminal V1.9b pues envia lo siguiente:

<0>€€€<0>€<0><0>€

El baudrate y todas las configuraciones del puerto serial son las mismas, pues me pasaba eso cuando tenia otra baudrate configurada en el Terminal V1.9b en comparacion con la que tenia el programa. El otro problemita que ha surguido es que cuando envio la palabrita "test", pues en la consola me escribe :

"te"
"s"
"t"

ya no la lee junta osea "test". Cual podria ser el problema de que no me escribe la palabrita "test" de una, sino por partes.
Cordiales saludos y muchas gracias de antemano por tu respuesta.

Juancar

unread,
Dec 9, 2014, 12:52:52 PM12/9/14
to qt-es...@googlegroups.com
Hola,

Comprueba que limpias el buffer una vez que haya terminado de enviar los datos. Sobre lo que escribe la consola... Los retornos de carro los estás introduciendo tu al usar endl Ten en cuenta que el bucle va leyendo los datos según le llegan, primero dos caracteres y después uno a uno, lo suyo es que cambies la línea: qDebug() << Data << endl; por qDebug() << Data; Si recibes un retorno de carro no lo sabes porque no es un carácter visible, antes de cambiar ese código prueba a enviar "test" y después "prueba" al menos una par de veces, después haces la misma prueba cambiando el código.

La llamada a clear() es después del siguiente código:

SerialPort.write(Data);
if (!SerialPort.
waitForBytesWritten(100))
{
qDebug() << "an error occurred \n" << endl;
}

Si limpias el buffer antes de tiempo puedes estar enviando basura, por eso se usa la función waitForBytesWriten() para que espere a que escriba, otra opción es limpiar el buffer con clear() sin parámetros después de: qDebug() << Data; Aquí no debería afectar al resto del código puesto que ya has leído los datos y solo vas a enviar con el buffer límpio.

Saludos

2050f...@gmail.com

unread,
Dec 17, 2014, 2:14:14 PM12/17/14
to qt-es...@googlegroups.com
Buenas tardes estimado amigo,
Gracias por tus consejos, los pondre a prueba durante las vaciones de navidad. Durante estos dias he estado muy ocupado con otro tema que tambien me esta dando dolores de cabeza. Me refiero a la programacion de microcontroladores AVR . Este microcontrolador es el que deberia enviar un mensaje y mi aplicacion de consola en Qt deberia de leerlo ...... bien  :(  :( 
Abrire un nuevo temita para consultar sobre la programacion en este micro : Atmega48 . No encuentro la forma de obtener el famoso tiempo de ejecucion de tarea.
Muchisimas gracias por sus valiosos consejos. Cordiales saludos.
Reply all
Reply to author
Forward
0 new messages