PyQt Lab est une série d’interfaces graphiques qui offre une solution simple et intuitive pour configurer, paramétrer, recevoir et afficher des données en provenance d’Arduino par le port série. Cette série est conçue pour faciliter le travail des développeurs et des ingénieurs qui souhaitent créer des applications à base d’Arduino. Elle permet de créer des applications qui peuvent être facilement configurées et paramétrées, et qui peuvent recevoir et afficher des données en provenance d’Arduino par le port série. Dans cet article, nous allons examiner en détail les fonctionnalités de PyQt Lab et comment elles peuvent être utilisées pour créer des applications à base d’Arduino.
PyQt Lab’ : Série : Interface graphique de base pour configuration, paramétrage, réception et affichage de chaines en provenance d’Arduino par le port série
Par X. HINAULT – Juin 2013

Ce que l’on va faire ici
- Dans ce code PyQt, interface graphique de base pour configuration, paramétrage, réception et affichage de chaines en provenance d’Arduino par le port série
Pré-requis
- python 2.7
- pyqt4.x
- modules :
- python-serial
Téléchargement :
- Ces codes sont disponibles ici : ..
Le fichier d’interface *.py
- Fichier obtenu automatiquement avec l’utilitaire pyuic4 à partir du fichier *.ui créé avec QtDesigner :
# Form implementation generated from reading ui file
#
# Created: Fri Jan 4 15:17:52 2013
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8(« Form »))
Form.resize(431, 199)
self.comboBoxPort = QtGui.QComboBox(Form)
self.comboBoxPort.setGeometry(QtCore.QRect(10, 30, 151, 24))
self.comboBoxPort.setEditable(True)
self.comboBoxPort.setObjectName(_fromUtf8(« comboBoxPort »))
self.comboBoxPort.addItem(_fromUtf8(« »))
self.comboBoxPort.addItem(_fromUtf8(« »))
self.comboBoxPort.addItem(_fromUtf8(« »))
self.comboBoxPort.addItem(_fromUtf8(« »))
self.labelPort = QtGui.QLabel(Form)
self.labelPort.setGeometry(QtCore.QRect(10, 15, 101, 16))
self.labelPort.setObjectName(_fromUtf8(« labelPort »))
self.comboBoxDebit = QtGui.QComboBox(Form)
self.comboBoxDebit.setGeometry(QtCore.QRect(170, 30, 111, 24))
self.comboBoxDebit.setObjectName(_fromUtf8(« comboBoxDebit »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.comboBoxDebit.addItem(_fromUtf8(« »))
self.labelDebit = QtGui.QLabel(Form)
self.labelDebit.setGeometry(QtCore.QRect(170, 15, 111, 16))
self.labelDebit.setObjectName(_fromUtf8(« labelDebit »))
self.pushButtonInitSerial = QtGui.QPushButton(Form)
self.pushButtonInitSerial.setGeometry(QtCore.QRect(290, 15, 131, 41))
self.pushButtonInitSerial.setObjectName(_fromUtf8(« pushButtonInitSerial »))
self.textEditReception = QtGui.QTextEdit(Form)
self.textEditReception.setGeometry(QtCore.QRect(10, 70, 411, 121))
self.textEditReception.setObjectName(_fromUtf8(« textEditReception »))
self.labelReception = QtGui.QLabel(Form)
self.labelReception.setGeometry(QtCore.QRect(10, 55, 191, 16))
self.labelReception.setObjectName(_fromUtf8(« labelReception »))
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate(« Form », « PyQt + PySerial : GUI Base Init Serial + Réception », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxPort.setItemText(0, QtGui.QApplication.translate(« Form », « /dev/ttyACM0 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxPort.setItemText(1, QtGui.QApplication.translate(« Form », « /dev/ttyACM1 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxPort.setItemText(2, QtGui.QApplication.translate(« Form », « /dev/ttyUSB0 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxPort.setItemText(3, QtGui.QApplication.translate(« Form », « /dev/ttyUSB1 », None, QtGui.QApplication.UnicodeUTF8))
self.labelPort.setText(QtGui.QApplication.translate(« Form », « Port Série : », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(0, QtGui.QApplication.translate(« Form », « 115200 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(1, QtGui.QApplication.translate(« Form », « 57600 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(2, QtGui.QApplication.translate(« Form », « 38400 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(3, QtGui.QApplication.translate(« Form », « 28800 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(4, QtGui.QApplication.translate(« Form », « 19200 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(5, QtGui.QApplication.translate(« Form », « 14400 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(6, QtGui.QApplication.translate(« Form », « 9600 », None, QtGui.QApplication.UnicodeUTF8))
self.comboBoxDebit.setItemText(7, QtGui.QApplication.translate(« Form », « 4800 », None, QtGui.QApplication.UnicodeUTF8))
self.labelDebit.setText(QtGui.QApplication.translate(« Form », « Débit Série (bauds) : », None, QtGui.QApplication.UnicodeUTF8))
self.pushButtonInitSerial.setText(QtGui.QApplication.translate(« Form », « Initialiser le port Série », None, QtGui.QApplication.UnicodeUTF8))
self.labelReception.setText(QtGui.QApplication.translate(« Form », « Réception sur le port série : « , None, QtGui.QApplication.UnicodeUTF8))
if __name__ == « __main__ »:
import sys
app = QtGui.QApplication(sys.argv)
Form = QtGui.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
Le fichier d’application *Main.py
# -*- coding: utf-8 -*-
# par X. HINAULT – Janv 2013 – Tous droits réservés
# GPLv3 – www.mon-club-elec.fr
# modules a importer
from PyQt4.QtGui import *
from PyQt4.QtCore import * # inclut QTimer..
import os,sys
import serial # communication serie
from tuto_pyqt_pyserial_init_port_debit_lire_chaine import * # fichier obtenu à partir QtDesigner et pyuic4
class myApp(QWidget, Ui_Form): # la classe reçoit le Qwidget principal ET la classe définie dans test.py obtenu avec pyuic4
def __init__(self, parent=None):
QWidget.__init__(self) # initialise le Qwidget principal
self.setupUi(parent) # Obligatoire
#Ici, personnalisez vos widgets si nécessaire
#Réalisez les connexions supplémentaires entre signaux et slots
# connecte le signal Clicked de l’objet bouton à l’appel de la fonction voulue
self.connect(self.pushButtonInitSerial, SIGNAL(« clicked() »), self.pushButtonInitSerialClicked)
#initialisation Timer
self.timer=QTimer() # déclare un timer Qt
self.connect(self.timer, SIGNAL(« timeout() »), self.timerEvent) # connecte le signal timeOut de l’objet timer à l’appel de la fonction voulue
#— déclaration utiles —
self.serialPort=None # déclaration initiale
# les fonctions appelées, utilisées par les signaux
def pushButtonInitSerialClicked(self):
print(« Bouton Init cliqué »)
if self.serialPort: # si le port existe déjà
self.serialPort.close() # ferme le port si existe
# — initialise paramètres initialisation
if self.comboBoxPort.currentText()==« » : # si le champ d’initialisation Port est vide = initialisation par défaut
strPortInit=« /dev/ttyACM0 » # port par défaut
else :
strPortInit=str(self.comboBoxPort.currentText()) #sinon utilise paramètre champ texte pour le port
strDebitInit=str(self.comboBoxDebit.currentText()) # paramètre champ texte pour debit
#— initialisation série avec gestion erreur —
try: # essaie d’exécuter les instructions
# initialise port serie avec délai attente en réception en sec
self.serialPort=serial.Serial(strPortInit, strDebitInit, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, 0.100)
#self.serialPort=serial.Serial(strPortInit, strDebitInit) # initialise port serie forme réduite
self.serialPort.flushInput() # vide la file d’attente série
print(« Initialisation Port Série : « + strPortInit + » @ « + strDebitInit + » = OK « ) # affiche debug
#– change aspect bouton init
self.pushButtonInitSerial.setStyleSheet(QString.fromUtf8(« background-color: rgb(0, 255, 0); »)) # bouton en vert
self.pushButtonInitSerial.setText(« Connexion OK ») # change titre bouton
except: # si erreur initialisation
print(« Erreur initialisation Série »)
#– change aspect bouton init
self.pushButtonInitSerial.setStyleSheet(QString.fromUtf8(« background-color: rgb(255, 127, 0); »)) # bouton en orange
self.pushButtonInitSerial.setText(QString.fromUtf8(« Non connecté »)) # change titre bouton
self.timer.start(50) # lance le timer avec délai en ms – 10 pour réception rapide
#—– fonction de gestion du signal timeout du QTimer
def timerEvent(self): # fonction appelée lors de la survenue d’un évènement Timer – nom fonction indiférrent
#– variables de réception —
self.chaineIn=« »;
self.char=« »;
# lecture des données reçues
if self.serialPort: # seulement si le port série existe
self.timer.stop() # stoppe le timer le temps de lire les caractères et éviter « réentrée »
while (self.serialPort.inWaiting()): # tant que au moins un caractère en réception
self.char=self.serialPort.read() # on lit le caractère
if self.char==‘\n‘: # si saut de ligne, on sort du while
print(« saut ligne reçu ») # debug
break # sort du while
else: #tant que c’est pas le saut de ligne, on l’ajoute à la chaine
self.chaineIn=self.chaineIn+self.char
if len(self.chaineIn)>0: # … pour ne pas avoir d’affichage si « »
print(self.chaineIn) # affiche la chaîne
self.textEditReception.append(self.chaineIn[:-1]) # ajoute le texte au textEdit en enlevant le dernier caractère
self.timer.start() # redémarre le timer
#—- fin timerEvent
def timerEvent(self): # fonction appelée lors de la survenue d’un évènement Timer – nom fonction indiférrent
#– variables de réception —
self.chaineIn=« »;
self.char=« »;
# lecture des données reçues
if self.serialPort: # seulement si le port série existe
self.timer.stop() # stoppe le timer le temps de lire les caractères et éviter « réentrée »
while (self.serialPort.inWaiting()): # tant que au moins un caractère en réception
self.char=self.serialPort.read() # on lit le caractère
#self.chaineIn=self.chaineIn+self.char # forme minimale…
if self.char==‘\n‘: # si saut de ligne, on sort du while
print(« saut ligne reçu ») # debug
break # sort du while
else: #tant que c’est pas le saut de ligne, on l’ajoute à la chaine
self.chaineIn=self.chaineIn+self.char
if len(self.chaineIn)>0: # … pour ne pas avoir d’affichage si « »
print(self.chaineIn) # affiche la chaîne
self.textEditReception.append(self.chaineIn[:-1]) # ajoute le texte au textEdit en enlevant le dernier caractère
self.timer.start() # redémarre le timer
#—- fin timerEvent
def main(args):
a=QApplication(args) # crée l’objet application
f=QWidget() # crée le QWidget racine
c=myApp(f) # appelle la classe contenant le code de l’application
f.show() # affiche la fenêtre QWidget
r=a.exec_() # lance l’exécution de l’application
return r
if __name__==« __main__ »: # pour rendre le code exécutable
main(sys.argv) # appelle la fonction main
Code Arduino d’exemple
- Ce code Arduino se contente d’envoyer une chaîne à intervalle régulier vers le PC.
Serial.begin(115200); // initialise vitesse de transmission série utiliser la même vitesse côté PC
}
void loop() {
Serial.println(« Coucou »); // envoi chaine sur port série
delay(1000); // pause 1 seconde
}
Utilisation
- Les 2 fichiers suivants sont à enregistrer dans un même répertoire, l’un en nom.py et l’autre en nomMain.py.
- Puis lancer l’application depuis Geany ou équivalent, en exécutant le fichier nomMain.py
- Sélectionner le port, le débit et clic sur le bouton : les chaînes doivent s’affficher dans la zone te texte.
Articles similaires:
- PyQt Lab’ : Série : Interface graphique de base pour initialiser la connexion au port série (sélection graphique du débit, du port utilisé)
- PyQt Lab’ : Port Série : en réception : Réception d’une valeur numérique sur le port série et affichage dans un widget LCD.
- PyQt Lab’ : Port Série : en réception : Afficher dans un QwtThermo, le widget d’affichage analogique « vu-mètre », une valeur de conversion analogique numérique (0-1023) reçue sur le port série en provenance d’Arduino.
- PyQt Lab’ : Port Série : en réception : Afficher dans un QwtDial, le widget d’affichage analogique « à aiguille », une valeur de conversion analogique numérique (0-1023) reçue sur le port série en provenance d’Arduino.
- PyQt Lab’ : Port Série : en réception : Réception d’une valeur numérique sur le port série, conversion mesure/unité et affichage dans des widgets LCD.
Articles Liés
- PyQt Lab' : Graphiques Math : Pyqtgraph + Pyserial : Afficher une courbe à partir de valeurs reçues sur le port série, avec widgets de paramétrage des axes
PyQt Lab est un outil puissant qui permet aux utilisateurs de créer des graphiques mathématiques…
- PyQt Lab' : Port Série : en envoi : Envoyer sur le port série une valeur numérique saisie à l'aide d'un clavier graphique.
PyQt Lab est un outil puissant qui permet aux utilisateurs de créer des applications graphiques…
- Javascript : Graphique Dygraphs simple
Le Javascript est un langage de programmation très populaire et puissant qui permet aux développeurs…