Cours:Oscillogbf

De troyesGEII
Révision datée du 26 mars 2025 à 12:52 par Bjacquot (discussion | contributions) (liens)
Aller à : navigation, rechercher

Voici un principe pour réaliser une interface graphique en python avec la librairie Qt pour dialoguer avec différents équipements (oscilloscope/gbf/...)


python et Qt

Mise en place avec QtCreator

  • créer un nouveau projet :
    • Application (Qt for Python) Window UI
    • pas d'importance pour PySide2 ou PySide6, on va remplacer après
    • choisir la version Python 3.x.x sans Virtual Environnement
  • ouvrir le fichier widget.py
  • remplacer par :
import sys
# communication avec le matériel de mesure
import pyvisa
# modules QT que l'on souhaite utiliser
# à compléter en fonction des besoins
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QApplication, QWidget, QFileDialog, QPushButton, QDial, QAbstractSlider
from PySide2.QtUiTools import QUiLoader


if __name__ == "__main__":
    # chargement du fichier form.ui
    # qui correspond à l'interface graphique
    loader = QUiLoader()
    app = QtWidgets.QApplication(sys.argv)
    window = loader.load("form.ui", None)
    window.show()

    # initialisation de la librairie pyVisa
    materiel=pyvisa.ResourceManager()
    # print(materiel.list_resources())

    # exemple pour se connecter sur un appareil par IP
    # gbf=materiel.open_resource('TCPIP::192.168.0.236::INSTR')

    sys.exit(app.exec_())

Signal/Slot avec PySide2

  • dans un 1er temps il faut créer un objet dans l'interface graphique, par exemple "monWidgetBouton" de type QPushButton
  • ensuite on connect le signal du widget sur la fonction que l'on souhaite :
    window.monWidgetBouton.clicked.connect(maFonction)
    
  • Ce qui donne :
    import sys
    # communication avec le matériel de mesure
    import pyvisa
    # modules QT que l'on souhaite utiliser
    # à compléter en fonction des besoins
    from PySide2 import QtCore, QtGui, QtWidgets
    from PySide2.QtWidgets import QApplication, QWidget, QFileDialog, QPushButton, QDial, QAbstractSlider
    from PySide2.QtUiTools import QUiLoader
    
    # fonction qui sera exécutée lors d'un clic
    def maFonction():
        print("clic !")
    
    if __name__ == "__main__":
        # chargement du fichier form.ui
        # qui correspond à l'interface graphique
        loader = QUiLoader()
        app = QtWidgets.QApplication(sys.argv)
        window = loader.load("form.ui", None)
        window.show()
    
        # associer une action à un QPushButton
        window.monWidgetBouton.clicked.connect(maFonction)
    
        # initialisation de la librairie pyVisa
        materiel=pyvisa.ResourceManager()
        # print(materiel.list_resources())
    
        # exemple pour se connecter sur un appareil par IP
        # gbf=materiel.open_resource('TCPIP::192.168.0.236::INSTR')
    
        sys.exit(app.exec_())
    

exemple pour différents widgets

  • QPushButton
    • window.monWidgetBouton.clicked.connect(maFonction)
  • QDial/QScrollBar/QSlider (hérite de QAbstractSlider)
    • window.monWidgetDial.valueChanged.connect(getValue)
      def getValue(value):
          print(f"position du slider : {value}")
      
    • window.monWidgetDial.setSliderPosition(0)
  • QLabel
    • window.monWidgetLabel.setText("message")


réaliser une action périodique

https://doc.qt.io/qtforpython-5/PySide2/QtCore/QTimer.html

from PySide2 import QtCore
from PySide2.QtCore import QTimer

def actionPeriodique():
    print("tic")

if __name__ == "__main__":
    timer = QTimer()
    timer.timeout.connect(actionPeriodique)
    timer.start(500)

créer son widget

import sys
import time
# communication avec le matériel de mesure
import pyvisa
# modules QT que l'on souhaite utiliser
# à compléter en fonction des besoins
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QApplication, QWidget, QFileDialog, QPushButton, QDial, QAbstractSlider, QLabel, QLayout
from PySide2.QtUiTools import QUiLoader
from PySide2.QtCore import Qt, QTimer, QRect, QPoint
from PySide2.QtGui import QPainter

class WidgetPerso(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

    def paintEvent(self, paintEvent):
        painter = QPainter()
        painter.begin(self)
        rect = QRect(QPoint(0, 0),QPoint(100, 100))
        painter.fillRect(rect, Qt.GlobalColor.white)
        painter.end()




if __name__ == "__main__":
    # chargement du fichier form.ui
    # qui correspond à l'interface graphique
    loader = QUiLoader()
    app = QtWidgets.QApplication(sys.argv)
    window = loader.load("form.ui", None)
    window.show()

    # on crée un nouvel objet de type WidgetPerso
    monWdiget = WidgetPerso()
    # on ajoute ce widget dans un container (Widget ou Frame)
    # !! attention, il faut définir un layout pour ce container dans QtDesigner : !!
    # ajouter un objet dans le container, changer le layout, puis supprimer l'objet
    window.zoneWidget.layout().addWidget(monWdiget)

    sys.exit(app.exec_())

dialoguer avec les appareils

initialisation

  • il faut initialiser la librairie
    materiel=pyvisa.ResourceManager()
    
  • se connecter sur un équipement
    gbf=materiel.open_resource('TCPIP::192.168.0.236::INSTR')
    
  • on peut ensuite :
    • envoyer des commandes à l'équipement :
      gbf.write(":OUTP1 ON")
      
    • demander une valeur à l'équipement :
      gbf.query("*IDN?")
      
  • Exemple :
    materiel=pyvisa.ResourceManager()
    gbf     =materiel.open_resource('TCPIP::192.168.0.236::INSTR')
    gbf2    =materiel.open_resource('USB0::6833::1603::DG8A231301537::0::INSTR')
    oscillo =materiel.open_resource('TCPIP::192.168.0.73::INSTR')
    print(gbf.query("*IDN?"))
    print(oscillo.query("*IDN?"))
    

commandes génériques

Les commandes suivantes devraient être valables pour tous les équipements :

commande paramètre description
*CLS clear : initialise la communication
*IDN? retourne l'identifiant de l'appareil
*OPC? operation complete : indique si l'opération précédente est terminée (1) ou non (0)

gbf DG822

Le fichier suivant contient l'ensemble des commandes pour le Rigol DG822 : dg822.pdf

Voici quelques commandes dont vous pourrez avoir besoin :

commande description exemple
 :OUTPx ON/1/OFF/0 activer la sortie gbf.write(":OUTP1 ON")
 :SOURx:FREQ value modifier la fréquence de la sortie gbf.write(":SOUR1:FREQ")
 :SOURx:APPL:SIN freq,amp,offset,phase générer un sinus à l'amplitude, offset, déphasage et fréquence souhaitée gbf.write(":SOUR1:APPL:SIN 100,3,2,1")
 :SOURx:APPL:PULS freq,amp,offset,phase générer un signal carré à l'amplitude, offset, déphasage et fréquence souhaitée gbf.write(":SOUR1:APPL:SIN 100,3,2,0")
 :SOURx:APPL:SQU freq,amp,offset,phase générer un signal PWM à l'amplitude, offset, déphasage et fréquence souhaitée gbf.write(":SOUR1:APPL:PULS 100,5,2.5,0")
 :SOURx:PULS:DCYC duty modifie le rapport cyclique d'un signal PWM gbf.write(":SOUR1:PULS:DCYC 45")


Exemple :

import sys
# communication avec le matériel de mesure
import pyvisa
# modules QT que l'on souhaite utiliser
# à compléter en fonction des besoins
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QApplication, QWidget, QFileDialog, QPushButton, QDial, QAbstractSlider
from PySide2.QtUiTools import QUiLoader

# fonction qui sera exécutée lors d'un clic
def maFonction():
    print("clic !")
    gbf.write(":OUTP1 ON")
    gbf.write(":SOUR1:APPL:PULS 1000,5,2.5,0")

# fonction qui sera exécutée lors de la modification du slider
def getValue(value):
    print(f"position du slider : {value}")
    gbf.write(f":SOUR1:PULS:DCYC {value}")


if __name__ == "__main__":
    # chargement du fichier form.ui
    # qui correspond à l'interface graphique
    loader = QUiLoader()
    app = QtWidgets.QApplication(sys.argv)
    window = loader.load("form.ui", None)
    window.show()

    # associer une action à un QPushButton
    window.monWidgetBouton.clicked.connect(maFonction)

    # associer une action à un QDial (hérite de QAbstractSlider)
    window.monWidgetDial.valueChanged.connect(getValue)

    # initialisation de la librairie pyVisa
    materiel=pyvisa.ResourceManager()
    # print(materiel.list_resources())

    # exemple pour se connecter sur un appareil par IP
    gbf    =materiel.open_resource('TCPIP::192.168.0.236::INSTR')
    #oscillo=materiel.open_resource('TCPIP::192.168.0.73::INSTR')
    print(gbf.query("*IDN?"))
    #print(oscillo.query("*IDN?"))

    sys.exit(app.exec_())

oscillo DS1104Z

Media:MSO_DS1000Z_ProgrammingGuide_EN.pdf

Voici quelques commandes dont vous pourrez avoir besoin :

commande description exemple
 :RUN
 :STOP
 :AUT
 :SING
run / stop / autoset / single oscillo.write(":STOP")
 :CHANnelx:DISPlay ON/1/OFF/0 enable/disable channel oscillo.write(":CHAN1:DISP ON")
 :CHANnel<n>:COUPling AC/DC/GND oscillo.write("")
 :CHANnel<n>:PROBe gain réglage du gain de la sonde (à modifier avant scale et offset) oscillo.write("")
 :CHANnel<n>:SCALe calibre de tension (à modifier avant l'offset) oscillo.write("")
 :CHANnel<n>:OFFSet oscillo.write("")
 :TIMebase[:MAIN]:SCALe base de temps en s oscillo.write(":TIMebase:MAIN:SCALe 0.001")
NORMal|SINGle oscillo.write("")
 :TRIGger:EDGe:SOURce CHANx oscillo.write("")
 :MEASure:ITEM? PDUTy,CHANnel1 oscillo.write("")
oscillo.write("")


Exemple :

oscillo.write(":CHANnel1:DISPlay ON")
oscillo.write(":CHANnel2:DISPlay OFF")
oscillo.write(":CHANnel3:DISPlay OFF")
oscillo.write(":CHANnel4:DISPlay OFF")
oscillo.write(":CHANnel1:COUPling DC")
oscillo.write(":CHANnel1:PROBe 1")
oscillo.write(":CHANnel1:SCALe 1")
oscillo.write(":CHANnel1:OFFSet -2")
oscillo.write(":TIMebase:MAIN:SCALe 0.001")
oscillo.write(":TRIGger:SWEep NORMal")
oscillo.write(":TRIGger:EDGe:SOURce CHAN1")
duty=int(float(oscillo.query(":MEASure:ITEM? PDUTy,CHANnel1"))*100)
print(duty)

multimètre DM3058

A creuser


liens