Go Down

Topic: [tuto]Communication Qt Arduino (Read 4415 times) previous topic - next topic

Vicolaships

Apr 02, 2013, 12:40 pm Last Edit: Apr 03, 2013, 09:15 am by Vicolaships Reason: 1
Pré-requis
Aucun ! Tout est expliqué et détaillé, aucune connaissance particulière n'est nécessaire. C'est réalisable par tout le monde !

Objectif
On va contrôler un servomoteur grâce a une application Qt. La communication se fait par le câble USB
Voir la vidéo

Matériel
  • Un Arduino (j'utilise un Arduino Nano 3.0)

  • Un PC, s'il n'est pas sous Linux il faudra adapter le code Qt (le mien est sous Ubuntu 12.04.2 desktop (64 bits))

  • Un servomoteur


Installation
Il faut installer Qt Creator et compiler ExtSerialPort :
Code: [Select]
sudo apt-get install -y qtcreator && git clone https://code.google.com/p/qextserialport/ && cd qextserialport && qmake && make && sudo make install

Arduino
On branche l'Arduino sur l'USB après avoir branché le servomoteur :
Rouge : 5V
Marron : GND
Jaune : D9

Démarrer un projet Arduino et compiler/transférer ce code :
Code: [Select]
#include <Servo.h>

Servo srv;
int incomingByte = 0;

void setup()
{
 Serial.begin(9600); // on defini le baud-rate
 srv.attach(9); // on attache un servo en D9
}

void loop()
{
if (Serial.available() > 0)
{
 // lecture des bytes arrivant :
 incomingByte = Serial.read();
 srv.write(incomingByte); // on écrit la valeur recue sur le servo
 //Serial.print(incomingByte);    
}
}


Projet Qt Creator
Créez un projet Qt Creator: Projet Qt Widget : Application graphique Qt
Nommer le projet "USB_servo" et le nom de la classe "USB_servo" (laisser le reste par défaut)

Aller dans formulaires, et créer les éléments suivants :

Widget - Nom
Qdial - "dial"
Qslider - "slider"
Qlcdnumber - "lcd"

Une fois les éléments crées appuyer sur F4 pour éditer les signaux/slots (ou cliquer en haut sur l'icône "Editer signaux/slots)
Créer les signaux suivants :

Emetteur - Signal - Receveur - Slot
dial - sliderMoved(int) - lcd - display(int)
dial - sliderMoved(int) - slider - setValue(int)
slider - sliderMoved(int) - dial - setValue(int)
slider - sliderMoved(int) - lcd - display(int)

Modifier le contenu des fichiers suivants comme suit :

USB_servo.pro
Code: [Select]
QT       += core gui

TARGET = USB_servo
TEMPLATE = app

#add qExtSerialPort libs
CONFIG += extserialport

SOURCES += main.cpp\
        usb_servo.cpp

HEADERS  += usb_servo.h

FORMS    += usb_servo.ui


usb_servo.h
Code: [Select]
#ifndef USB_SERVO_H
#define USB_SERVO_H

#include <QMainWindow>
#include <QtGui>
#include <qextserialport.h>

namespace Ui {
class USB_servo;
}

class USB_servo : public QMainWindow
{
    Q_OBJECT
   
public:
    explicit USB_servo(QWidget *parent = 0);
    void init_port(); // initialisation du port
    ~USB_servo();

public slots:
void transmitCmd(int value); // fonction d'envoi
   
private:
    Ui::USB_servo *ui;
    QextSerialPort *port;
};

#endif // USB_SERVO_H


usb_servo.cpp
Code: [Select]
#include "usb_servo.h"
#include "ui_usb_servo.h"

USB_servo::USB_servo(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::USB_servo)
    // Création de l'intefarce ("formulaires")
{
    init_port(); //initiation of the port
    ui->setupUi(this);
    connect(ui->dial, SIGNAL(sliderMoved(int)), this, SLOT(transmitCmd(int)));
    // On connecte le mouvement du bouton a l'envoi de la commande
    connect(ui->slider, SIGNAL(sliderMoved(int)), this, SLOT(transmitCmd(int)));
    // On connecte le mouvement du slider a l'envoi de la commande
    transmitCmd(90);
    // On initialise le servo à 90°
}

USB_servo::~USB_servo()
{
    delete ui;
}

void USB_servo::init_port(void)
{
    QString dev_port = "/dev/ttyUSB0";
    port = new QextSerialPort(dev_port); //on ouvre le port
    // ls /dev/ | grep USB   << Permet de donner la liste des périphériques USB

     port->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
    if(!port->isOpen())
    {
        QMessageBox::warning(this, "Impossible d'ouvrir le port", dev_port);
    }

    // On parametre la liaison :
    port->setBaudRate(BAUD9600);
    port->setFlowControl(FLOW_OFF);
    port->setParity(PAR_NONE);
    port->setDataBits(DATA_8);
    port->setStopBits(STOP_1);
}

void USB_servo::transmitCmd(int value)
{
    QByteArray byte; //byte a envoyer
    qint64 bw = 0; //bytes really writen

    byte.clear(); // on efface le contenu de byte
    byte.append(value); // on ajoute "value" a byte

    if(port != NULL){ // on vérifie que le port existe toujours
        bw = port->write(byte); // on écrit les byte
        //(bw récupere le nombre de byte écris)
        qDebug() << bw << "byte(s) written | Value sent:" << value << "(dec)";
        port->flush(); // on attend la fin de la transmission
    }

}


Branchez l'Arduino si ce n'est pas déjà fait et lancez la commande suivante dans un terminal :
Code: [Select]
ls /dev/ | grep USB

Le résultat devrait être ttyUSB0 par exemple. Modifier ligne 21 de usb_servo.cpp pour que le périphérique corresponde.
Pour exécuter le programme : Ctrl + R ou clic sur la flèche "lecture" verte en bas à gauche.

Remarque
Chez moi le programme Qt a parfois du mal a ouvrir le port, débrancher et rebrancher l'Arduino si cela arrive.
Arduino Nano v3.0 | Ubuntu 13.04

zoroastre

Yep!

Le fichier zip n'étant pas disponible à ce moment précis où je tente en vain de le télécharger.

Je me demande s'il s'agit bien de python ou de c++.

Bref!

Sous python, je vérifiais régulièrement si un port Usb était dispo ou pas (Linux uniquement).

Code: [Select]

def scan():
    """scan for available ports. return a list of device names."""
    f = glob.glob('/dev/ttyUSB*')
    if len(f) == 0:
        return None
    else:
        return f[0]


Dans la routine principale :

Code: [Select]
...
if scan() != device:
                        closeSerialPort()
                        time.sleep(2)
                        openSerialPort()
...


Vf bitty.py pour l'essentiel.

@+

Zoroastre.
Gné! ;)

Vicolaships

Salut !
Bon mon hébergeur semble pas marcher chez tout le monde alors j'ai rajouté dans le tutoriel comment créer le projet Qt.
A+
Arduino Nano v3.0 | Ubuntu 13.04

tymop

Bonjour,
je ne comprend pas #include "ui_usb_servo.h" car ce fichier n'existe pas.
Et mon complateur le le comprend pas non plus.

Est ce normal ?

Note : je débute sous QT.

XavierMiller


tymop

C'est quoi cet UI ? J'ai bien un fichier usb_servo.ui, mais je pense que ce n'est pas de ce fichier qu'il est question.

Je me doutais bien qu'il manquait ce fichier ui_usb_servo.h, mais je ne sais absoluent pas du tout ce qu'il doit y avoir dedans ?

XavierMiller

le ui_usb_servo.h est généré par QT sur base de l'interface graphique

Go Up