Qt y puertos serie

AttachmentSize
Package icon prueba_qextserialport.zip850 bytes
Informática: 

 

Aunque como he dicho en otro post Qt no tiene para la versión 4.x una clase para la utilización de puertos serie insisto en que para linux es super sencillo y no tiene mayor misterio, simplemente tenemos que utilizar el QSocketNotifier.

Para Windows la cosa cambia, y tenemos que utilizar sus clases y estructuras -vuelvo a insistir, en este otro post tienes más información-.

Si no nos queremos ensuciar las manos, podemos probar QextSerialPort. La verdad es que no he podido probarlo con Arduino, pero simplemente probando un listado de los puertos -es uno de los ejemplos- estoy seguro de que es una alternativa válida.

Lo que tenemos que hacer para utilizarlo con Qt4x es:

  • Bajar la versión adecuada -en la actualidad 1.2 para Qt4-
  • Mediante QtCreator, simplemente hacer un
    • Build, Clean All
    • Build, Build All
  • Adaptar nuestro .pro para utilizar la dll en nuestro programa

En mi caso tengo en el .pro:

#-------------------------------------------------
# QextSerialPort
#-------------------------------------------------
LIBS += -LC:/software/qt/serial/qextserialport/build
LIBS += -lqextserialport1
INCLUDEPATH += C:/software/qt/serial/qextserialport/src
DEFINES  = _TTY_WIN_

¿Qué significa esto? Bueno, la primera línea indica dónde tiene que buscar la dll -en este caso y como es una versión release cargamos qextserialport1.dll- que en mi caso tras compilar el código es en C:\software\qt\serial\qextserialport\build Para una versión debug sería qextserialportd1.dll -la verdad es que es un jaleo porque sólo se diferencia por una d y encima el 1 -uno- se parece demasiado a una l -ele- que como podemos ver hacemos uso de ello porque es así como se cargan las librerias. Recomiendo renombrar las dll...

En la segunda línea cargamos la librería para una versión release.

En la tercera línea incluimos el path para añadir cosas adicionales -como por ejemplo, en nuestro caso el include #include <qextserialenumerator.h>-

Ya finalmente realizamos un define necesario para el QextSerialPort.

Dejo el código, a ver si este fin de semana pruebo la dll con Arduino.

Social_buttons: 

Comments

Este fin de semana probé a conectar Arduino y Qt mediante QextSerialPort y la cosa ha funcionado. Lo que hice es mostrar en el PC el valor leído de un potenciómetro conectado a Arduino. Este sería el header:

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
 
namespace Ui {
class Widget;
}
 
class QextSerialPort;
class Widget : public QWidget
{
    Q_OBJECT
     
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:
    Ui::Widget *ui;
    QextSerialPort *puerto;
private slots:
    void onDataAvailable();
};
 
#endif // WIDGET_H

y este el cpp:

#include "widget.h"
#include "ui_widget.h"
#include <qextserialport.h>
 
#include <QDebug>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // Puerto para la comunicación con Arduino
    PortSettings configuracion = {BAUD9600, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 1000};
    puerto = new QextSerialPort("COM2", configuracion, QextSerialPort::EventDriven);
    this->connect(puerto, SIGNAL(readyRead()),
                  this, SLOT(onDataAvailable()));
    puerto->open(QIODevice::ReadWrite);
 
    if (puerto) {
        qDebug() << "Puerto abierto" << endl;
    }
    else {
        qDebug() << "No se ha abierto el puerto" << endl;
    }
}
 
Widget::~Widget()
{
    delete ui;
    if (puerto && puerto->isOpen()) {
        puerto->close();
    }
}
 
/**
 * Los datos se envían desde Arduino finalizando con un \r\n. Por ejemplo, si leemos
 * 287 en el puerto analógico, enviará 287\r\n pero se enviará agrupando los datos de
 * cualquier forma. Esto es, una secuencia de ejemplo sería: 2 87\r \n
 */
void Widget::onDataAvailable()
{
    char datos[8] = "";
    static QString cadena = "";
 
    // La lectura en "datos" se realiza en exclusión mutua
    int bytesRead = puerto->read(datos, 8);
    if (bytesRead > 0) {
        cadena.append(datos);
        // Se ha enviado un paquete de datos completo
        if (cadena.contains("\n")) {
            cadena = cadena.trimmed();
            qDebug() << "Cadena:" << cadena << cadena.size() << endl;
            ui->lblLdr->setText(cadena);
            ui->hSliderLdr->setValue(cadena.toInt());
            cadena = "";
        }
    }
}

Hola, podrías enviarme el archivo de proyecto completo? quiero decir, el paquete completo que genera Qt.
He ido copiando y pegando pero me salen bastantes errores y soy incapaz de corregirlos..

Mi intención es la misma, conectar Arduino a Qt.

Gracias.

Hola David,

No conservo el código de esta prueba por ser eso, una prueba.
De todas formas, aunque está explicado en el post, esto es lo que tienes que hacer:

  • Bajarte el QSerialPort adecuado para tu versión de Qt
  • Adecuar el .pro para que se incluya el QSerialPort
  • Ya en tu proyecto, pones los botoncitos y widgets que quieras, añadiendo un puntero a un QSerialPort y un slot en el header
  • En el cpp, en el constructor sólo tienes que configurar el puerto serie (como ves era una prueba y yo lo hice a pelo abriendo el COM2) y conectar la señal que indica que hay en el puerto readyRead con tu slot (donde manejarás los datos que te llegan de Arduino)
  • En el destructor tienes que asegurarte de cerrar el puerto si lo has abierto, de otra forma el puerto queda capturado y tendrías que reiniciar sesión

Olvídate del código que he puesto, es sólo una guía. Crea tu propio proyecto, adecúa el .pro para que incluya el QSerialPort, utiliza un objeto QSerialPort y conecta el aviso del Sistema Operativo de que hay algo en el puerto serie en tu aplicación.

Un saludo