Rigolinux :

screen.png.jpg

Rigolinux est un logiciel libre (créé par La Boite à Physique !) permettant de piloter les oscilloscopes de la marque Rigol, disposant d'une liaison série RS232. Il fonctionne sous Linux.

Ce logiciel est dédié à l'enseignement : toute l'ergonomie a été orientée dans le but d'une vidéoprojection du logiciel au tableau :

  •  format 1024x768 (résolution de base d'un grand nombre de vidéoprojecteurs)
  •  possibilité de modifier les couleurs des courbes et du fond ainsi que l'épaisseur des courbes (en vidéoprojection on choisira une courbe plus épaisse pour la rendre bien visible du fond de la classe)
  •  possibilité d'afficher ou pas les réglages de sensibilités de l'oscilloscope (Pratique lors de la découverte de l'oscilloscope :
    •  au bureau connecter le GBF sur l'osilloscope Rigol et projeter Rigolinux.
    • relier également le GBF à la ligne sèche de la salle de TP : tous les élèves disposent alors du même signal que le professeur.
    • en ayant masqué les réglages, demander au élèves de régler leur oscilloscope pour retrouver un affichage similaire

Ci-dessous Rigolinux (V1_03) en situation réelle : l'oscilloscope sur le bureau est relié au portable, lui même relié au vidéoprojecteur :

1_en_situation.JPG
 

 

Ci-dessous, une vidéo (version 1_3 du logiciel) avec commentaires qui détaille tous les réglages de base.

Cette vidéo est réalisée avec les logiciels suivants :

Le logiciel n'est pas terminé, mais suffisamment fonctionnel pour pouvoir être proposé sur ce site.

Les fonctions non disponibles à ce jour (Mars 2018) :

  • les fonctions mathématiques (en particulier la FFT)
  • le mode Roll

A venir :

  • sauvegarde de l'écran au format image

Le matériel nécessaire :

Le port série du PC comme celui du Rigol est de type mâle SUBD9 :

 

DSCN0991.resized.JPG        DSCN0994.resized.JPG

Il faut donc un câble série SUBD9 femelle-femelle.

Le protocole choisi par Rigol impose un câblage dit « droit » (fil à fil entre les deux connecteurs SUBD9)

Mais, on trouve généralement des câbles série :

  • femelle-femelle mais avec un câblage croisé
  • mâle-femelle avec un câblage droit ….

L'un comme l'autre ne suffisent pas. On achètera :

  • un câble série mâle-femelle
  • un adaptateur femelle-femelle :

DSCN0996.resized.JPG

 

Si on souhaite travailler avec un PC portable (généralement démuni de port série), il faut se procurer un câble adaptateur USB-série (Prolific par exemple)

 

DSCN0999.resized.JPG  DSCN0998.resized.JPG

 

Pour réaliser la commnication série entre le logiciel et l'oscilloscope :

  •    s'assurer que l'on appartient au groupe autorisé à utiliser les ports série du PC (voir l'onglet "Port série et Linux" sur la page dédiée à l'alimentation ELC AL991S)
  •   câbler comme indiqué ci-dessus,
  •  régler la vitesse de communication de l'oscilloscope sur 38400 bauds (menu Utility -> Param.E/S)
  •   si l'oscilloscope est correctement détecté, le nom du modèle s'affiche au dessus de l'écran (Cf vidéo de démo ci dessus : ici c'est un DS1062CD qui est utilisé)

(Logiciel libre sous licence GPL. Copyright 2014)

Pour contacter l'auteur : vlemieux@laboiteaphysique.fr

#!/usr/bin/python
#-*- coding: iso-8859-15 -*-

# Copyright 2014 Vincent LE MIEUX

# Contact : vlemieux@laboiteaphysique.fr

# La version la plus récente de ce programme se trouve
# sur le site de l'auteur : www.laboiteaphysique.fr

# Ce programme est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant
# les termes de la GNU General Public License telle que publiée par la Free Software Foundation ;
# soit la version 3 de la licence, soit (à votre gré) toute version ultérieure.

# Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ;
# sans même la garantie tacite de QUALITÉ MARCHANDE ou d'ADÉQUATION à UN BUT PARTICULIER.
# Consultez la GNU General Public License pour plus de détails.

# Vous devez avoir reçu une copie de la GNU General Public License en même temps que ce programme ;
# si ce n'est pas le cas, consultez <http://www.gnu.org/licenses>.

from __future__ import division
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject
import os, sys, re
import serial
import string
import cairo
from time import sleep
import glob
import math


class RIGOLINUX:
    
    
    def __init__(self):
        
        self.builder = Gtk.Builder()
        self.builder.add_from_file("rigolinux.glade")

        #recuperation des widgets utilises par le programme :
        self.lb_idn = self.builder.get_object("lb_idn")
        self.btOuvrir = self.builder.get_object("btOuvrir")
        self.btFermer = self.builder.get_object("btFermer")
        self.btQuitter = self.builder.get_object("btQuitter")
        self.btRafraichir = self.builder.get_object("btRafraichir")
        self.comboPort = self.builder.get_object("comboPort")
        self.comboBauds = self.builder.get_object("comboBauds")
        self.bt_Manuel = self.builder.get_object("bt_Manuel")
        self.bt_Auto = self.builder.get_object("bt_Auto")
        self.tgb_RunStop = self.builder.get_object("tgb_RunStop")
        self.tgb_manuel = self.builder.get_object("tgb_manuel")
        self.bt_acq1 = self.builder.get_object("bt_acq1")
        self.zone_ecran = self.builder.get_object("zone_ecran")
        self.zone_ecran.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
        
        self.bt_aff_ch1 = self.builder.get_object("bt_aff_ch1")
        self.bt_aff_ch2 = self.builder.get_object("bt_aff_ch2")
        self.bt_aff_bdt = self.builder.get_object("bt_aff_bdt")
        self.lb_CH1 = self.builder.get_object("lb_CH1")
        self.sw_ch1 = self.builder.get_object("sw_ch1")
        self.bt_plus_ch1 = self.builder.get_object("bt_plus_ch1")
        self.bt_moins_ch1 = self.builder.get_object("bt_moins_ch1")
        self.scaleCH1 = self.builder.get_object("scaleCH1")
        self.combo_couplage1 = self.builder.get_object("combo_couplage1")
        self.lb_CH2 = self.builder.get_object("lb_CH2")
        self.sw_ch2 = self.builder.get_object("sw_ch2")
        self.bt_plus_ch2 = self.builder.get_object("bt_plus_ch2")
        self.bt_moins_ch2 = self.builder.get_object("bt_moins_ch2")
        self.scaleCH2 = self.builder.get_object("scaleCH2")
        self.combo_couplage2 = self.builder.get_object("combo_couplage2")
        self.lb_BdT = self.builder.get_object("lb_BdT")
        self.bt_plus_BdT = self.builder.get_object("bt_plus_BdT")
        self.bt_moins_BdT = self.builder.get_object("bt_moins_BdT")
        self.scaleBdT= self.builder.get_object("scaleBdT")
        self.lb_decalage_horizontal = self.builder.get_object("lb_decalage_horizontal")
        self.sw_math = self.builder.get_object("sw_math")
        self.comboBdT = self.builder.get_object("comboBdT")
        self.lb_niveau_trigger = self.builder.get_object("lb_niveau_trigger")
        self.cb_afficher = self.builder.get_object("cb_afficher")
        self.colorbutton_fond = self.builder.get_object("colorbutton_fond")
        self.colorbutton1 = self.builder.get_object("colorbutton1")
        self.colorbutton2 = self.builder.get_object("colorbutton2")
        self.colorbutton_math = self.builder.get_object("colorbutton_math")
        self.sb_ligne = self.builder.get_object("sb_ligne")
        
        
        self.comboTrigSource = self.builder.get_object("comboTrigSource")
        self.comboTrigFront = self.builder.get_object("comboTrigFront")
        self.comboBalayage = self.builder.get_object("comboBalayage")
        self.scaleTrigger = self.builder.get_object("scaleTrigger")
        self.combo_math = self.builder.get_object("combo_math")

        #Onglet Mesures :
        self.switch_aff_curseurY = self.builder.get_object("switch_aff_curseurY")
        self.colorbutton_curseurY = self.builder.get_object("colorbutton_curseurY")
        self.comboCurseurY = self.builder.get_object("comboCurseurY")
        self.scaleCAY = self.builder.get_object("scaleCAY")
        self.lb_CAY = self.builder.get_object("lb_CAY")
        self.scaleCBY = self.builder.get_object("scaleCBY")
        self.lb_CBY = self.builder.get_object("lb_CBY")
        self.lb_CdY = self.builder.get_object("lb_CdY")

        self.switch_aff_curseurX= self.builder.get_object("switch_aff_curseurX")
        self.colorbutton_curseurX = self.builder.get_object("colorbutton_curseurX")
        self.scaleCAX = self.builder.get_object("scaleCAX")
        self.lb_CAX = self.builder.get_object("lb_CAX")
        self.scaleCBX = self.builder.get_object("scaleCBX")
        self.lb_CBX = self.builder.get_object("lb_CBX")
        self.lb_CdX = self.builder.get_object("lb_CdX")
        
        self.label20 = self.builder.get_object("label20")
        self.lb_debug = self.builder.get_object("lb_debug")
        self.builder.connect_signals(self)

        window = self.builder.get_object('window')
        window.show_all()

        self.lister_ports()
        self.desactiver_widget_reglages()
        
        #initialisations :
        
        
        self.ouvert = False
        self.timer_id = None
        self.sortie =""
        self.port_serie = " "
        self.port_choisi = " "
        self.data_format = " "
        self.debit = " "
        self.parite = ""
        self.comboPort.set_active(0)  # le premier port decouvert
        self.comboBauds.set_active(2) # 38400 bauds
        
        self.lb_idn.set_text("déconnecté")
        self.data_ch1 = [0]
        
        self.Affiche_S1 = True
        self.Gnd1 = False
        self.Affiche_S2 = True
        self.Gnd2 = False
        self.Affiche_BdT = True
        
        self.Affiche_ValCY = True
        self.Affiche_ValCX = True
        
        self.data_ch2 = [0]

        self.delai = 1000
        
        self.longueur_data = 1024
        # tableau des difféentes valeurs de sensibilité à envoyer :
        self.env_cal = \
        ['0.000000001', '0.000000002', '0.000000005'\
        ,'0.00000001', '0.00000002', '0.00000005'\
        ,'0.0000001', '0.0000002', '0.0000005',\
        '0.000001', '0.000002', '0.000005',\
        '0.00001', '0.00002', '0.00005',\
        '0.0001', '0.0002', '0.0005',\
        '0.001','0.002', '0.005', \
        '0.01', '0.02', '0.05',\
        '0.1', '0.2', '0.5',\
        '1', '2', '5',\
        '10','20', '50']
        
        # tableau des difféentes valeurs de sensibilité recevables :
        self.rec_cal = \
        ['1.000e-09','2.000e-09','5.000e-09', \
        '1.000e-08','2.000e-08','5.000e-08',\
        '1.000e-07','2.000e-07','5.000e-07',\
        '1.000e-06','2.000e-06','5.000e-06',\
        '1.000e-05','2.000e-05','5.000e-05',\
        '1.000e-04','2.000e-04','5.000e-04',\
        '1.000e-03','2.000e-03','5.000e-03',\
        '1.000e-02','2.000e-02','5.000e-02',\
        '1.000e-01','2.000e-01','5.000e-01',\
        '1.000e+00','2.000e+00','5.000e+00',\
        '1.000e+01','2.000e+01','5.000e+01']

        #DS1062CD : 2 mV à 5V ; 5 ns à 50 s :
        self.index_Vmin = 19
        self.index_Vmax = 29
        self.index_Hmin = 2
        self.index_Hmax = 26 #version du logiciel limitée actuellement

        #couleurs :
        self.couleur_fond = self.colorbutton_fond.get_rgba()
        self.couleur_ch1 = self.colorbutton1.get_rgba()
        self.couleur_ch2 = self.colorbutton2.get_rgba()
        self.couleur_math = self.colorbutton_math.get_rgba()
        
        self.couleur_curseurX = self.colorbutton_curseurX.get_rgba()
        self.couleur_curseurY = self.colorbutton_curseurY.get_rgba()

        adjLigne = Gtk.Adjustment(0, 1, 5, 1, 1, 0)
        self.sb_ligne.configure(adjLigne, 1,1)
        self.sb_ligne.set_value(3)
        self.epaisseur_ligne = int(self.sb_ligne.get_value())

        self.Ch1active = True
        self.Ch2active = False
        self.ModeYT = True
        self.ModeXY = False
        self.Mathactive = False
        self.FFTactive = False

        self.CurseurYactive = False
        self.PosCursYA = 110
        self.PosCursYB = 210
        self.PosCursXA = 210
        self.PosCursXB = 410
        self.CurseurXactive = False
        self.comboCurseurY.set_active(0)
    
        # masque de recherche des valeurs numériques :
        # exemple 2.000e+01
        self.masque = re.compile('([0-9])\.([0-9]+)e\D([0-9])([0-9])')
        #masque de recherche trigger :
        self.masque_trigger = re.compile('([A-Z0-9]+)')
        self.masque_triggerFront = re.compile('([A-Z]+)')
        self.masque_triggerSweep = re.compile('([A-Z]+)')
        self.masque_trigger_niveau = re.compile('(\-*[0-9])\.([0-9]+)e\D([0-9])([0-9])')
        #masque de recherche couplages :
        self.masque_couplage = re.compile('([A-Z]+)')

    def lister_ports(self) :
        if sys.platform.startswith('linux'):    #test du système d'exploitation
            # sous Linux
            list_port =  glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyS*')
            
            # puis affichage des ports dans le combo :
        i = 0
        while i < len(list_port):
            self.comboPort.append_text(list_port[i].strip('/dev/'))
            i=i+1
    
    def desactiver_widget_reglages(self):
        self.btFermer.set_sensitive(False)
        self.bt_Manuel.set_sensitive(False)
        self.bt_Auto.set_sensitive(False)
        self.tgb_RunStop.set_sensitive(False)
        self.scaleCH1.set_sensitive(False)
        self.bt_plus_ch1.set_sensitive(False)
        self.sw_ch1.set_sensitive(False)
        self.bt_moins_ch1.set_sensitive(False)
        self.scaleCH2.set_sensitive(False)
        self.sw_ch2.set_sensitive(False)
        self.bt_plus_ch2.set_sensitive(False)
        self.bt_moins_ch2.set_sensitive(False)
        self.sw_math.set_sensitive(False)
        self.combo_math.set_sensitive(False)
        #self.comboBdT.set_sensitive(False)
        self.bt_plus_BdT.set_sensitive(False)
        self.bt_moins_BdT.set_sensitive(False)
        self.scaleBdT.set_sensitive(False)
        self.scaleCH1.set_sensitive(False)
        self.bt_plus_ch1.set_sensitive(False)
        self.comboTrigSource.set_sensitive(False)
        self.comboTrigFront.set_sensitive(False)
        self.scaleTrigger.set_sensitive(False)

    def activer_widget_reglages(self):
        self.btFermer.set_sensitive(True)
        self.bt_Manuel.set_sensitive(True)
        self.bt_Auto.set_sensitive(True)
        self.tgb_RunStop.set_sensitive(True)
        self.scaleCH1.set_sensitive(True)
        self.bt_plus_ch1.set_sensitive(True)
        self.sw_ch1.set_sensitive(True)
        self.bt_moins_ch1.set_sensitive(True)
        self.scaleCH2.set_sensitive(True)
        self.sw_ch2.set_sensitive(True)
        self.bt_plus_ch2.set_sensitive(True)
        self.bt_moins_ch2.set_sensitive(True)
        #self.sw_math.set_sensitive(True)
        #self.combo_math.set_sensitive(True)
        self.comboBdT.set_sensitive(True)
        self.scaleBdT.set_sensitive(True)
        self.bt_plus_BdT.set_sensitive(True)
        self.bt_moins_BdT.set_sensitive(True)
        self.scaleCH1.set_sensitive(True)
        self.bt_plus_ch1.set_sensitive(True)
        self.comboTrigSource.set_sensitive(True)
        self.comboTrigFront.set_sensitive(True)
        self.scaleTrigger.set_sensitive(True)
            
    def lire_reglages_sensibilites(self):
        try:
            #récupérer la sensibilité CH1 :
            self.port_serie.write(':CHAN1:SCAL?' + '\n')
            sleep(0.01)
            self.sensib1 = self.masque.search(self.port_serie.readline()).group(0)    
            
            if self.Affiche_S1 == True :
                if float(self.sensib1) < 1 :
                    self.lb_CH1.set_text(str(int(1000*float(self.sensib1))) + " mV/div")
                else:
                    self.lb_CH1.set_text(str(int(float(self.sensib1))) + " V/div")
            else:
                self.lb_CH1.set_text("")
            #recuperation de l'indice (dans le tableau) du calibre de la voie 1
            self.index1 = self.rec_cal.index(self.sensib1)
            
            #récupérer la sensibilité CH2 :    
            self.port_serie.write(':CHAN2:SCAL?' + '\n')
            sleep(0.01)
            self.sensib2 = self.masque.search(self.port_serie.readline()).group(0)        
            if self.Affiche_S2 == True :
                if float(self.sensib2) < 1 :
                    self.lb_CH2.set_text(str(int(1000*float(self.sensib2))) + " mV/div")
                else:
                    self.lb_CH2.set_text(str(int(float(self.sensib2))) + " V/div")
            else:
                self.lb_CH2.set_text("")
            self.index2 = self.rec_cal.index(self.sensib2)    
                    
            #récupérer la sensibilité horizontale :        
            self.port_serie.write(':TIM:SCAL?' + '\n')
            sleep(0.01)
            self.BdT = self.masque.search(self.port_serie.readline()).group(0)        
            if self.Affiche_BdT == True :
                if float(self.BdT) < 1E-6 :            
                    self.lb_BdT.set_text(str(int(1E9*float(self.BdT))) + " ns/div")
                elif float(self.BdT) < 1E-3 :
                    self.lb_BdT.set_text(str(int(1E6*float(self.BdT))) + " " + u"\u03BC" + "s/div")
                elif float(self.BdT) < 1 :
                    self.lb_BdT.set_text(str(int(1E3*float(self.BdT))) + " ms/div")
                else:
                    self.lb_BdT.set_text(str(int(float(self.BdT))) + " s/div")
            else:
                self.lb_BdT.set_text("")
            self.indexH = self.rec_cal.index(self.BdT)
            self.lb_debug.set_text('')
        except :
            self.lb_debug.set_text('erreur de lecture')    
    
    def lire_couplages(self):
        #récupérer le mode de couplage sur chacune des voies :
        try:
            self.port_serie.write(':CHANnel1:COUPling?' + '\n')
            sleep(0.01)    
            self.Couplage1_Oscillo = self.masque_couplage.search(self.port_serie.readline()).group(0)
            
            if self.Couplage1_Oscillo == 'DC' :
                self.combo_couplage1.set_active(0)
            elif self.Couplage1_Oscillo == 'AC' :
                self.combo_couplage1.set_active(1)    
            elif self.Couplage1_Oscillo == 'GND' :
                self.combo_couplage1.set_active(2)
                self.Gnd1 = True    
            else :
                self.combo_couplage1.set_active(0)
                self.port_serie.write(':CHANnel1:COUPling DC' + '\n' )
            
            self.port_serie.write(':CHANnel2:COUPling?' + '\n')
            sleep(0.01)    
            self.Couplage2_Oscillo = self.masque_couplage.search(self.port_serie.readline()).group(0)
            
            if self.Couplage2_Oscillo == 'DC' :
                self.combo_couplage2.set_active(0)
            elif self.Couplage2_Oscillo == 'AC' :
                self.combo_couplage2.set_active(1)    
            elif self.Couplage2_Oscillo == 'GND' :
                self.combo_couplage2.set_active(2)    
                self.Gnd2 = True
            else :
                self.combo_couplage2.set_active(0)
                self.port_serie.write(':CHANnel2:COUPling DC' + '\n' )
        except :
            self.lb_debug.set_text('erreur de lecture')
        
    def lire_reglages_trigger(self):    
        
    #récupérer les réglages trigger :
        try:    
            # source du trigger :
            self.port_serie.write(':TRIG:EDGE:SOUR?' + '\n')
            sleep(0.01)
            self.TrigSourceOscillo = self.masque_trigger.search(self.port_serie.readline()).group(0)
            
            if self.TrigSourceOscillo == 'CH1' :
                self.comboTrigSource.set_active(0)
            elif self.TrigSourceOscillo == 'CH2' :
                self.comboTrigSource.set_active(1)    
            elif self.TrigSourceOscillo == 'EXT' :
                self.comboTrigSource.set_active(2)    
            else :
                self.comboTrigSource.set_active(0)
                self.port_serie.write(':TRIG:EDGE:SOUR CH1' + '\n' )
                
            # Front du trigger :
            self.port_serie.write(':TRIGger:EDGE:SLOPe?' + '\n')
            sleep(0.01)
            
            self.TrigFrontOscillo = self.masque_triggerFront.search(self.port_serie.readline()).group(0)
            
            if self.TrigFrontOscillo == 'POSITIVE' :
                self.comboTrigFront.set_active(0)
            elif self.TrigFrontOscillo == 'NEGATIVE' :
                self.comboTrigFront.set_active(1)    
            
            else :
                self.comboTrigFront.set_active(0)
                self.port_serie.write(':TRIG:EDGE:SLOP POS' + '\n' )
            
            # niveau du trigger :
            self.port_serie.write(':TRIG:EDGE:LEV?' + '\n')
            sleep(0.01)
            self.niveau_trigger_oscillo = float(self.masque_trigger_niveau.search(self.port_serie.readline()).group(0)    )
            self.scaleTrigger.set_value(10*self.niveau_trigger_oscillo)
            self.lb_niveau_trigger.set_text(str("{:1.2f}".format(float(self.sensib1)*self.niveau_trigger_oscillo/10) + 'V'))
        
            # balayage :
            self.port_serie.write(':TRIGger:EDGE:SWEep?' + '\n')
            sleep(0.01)
            self.TrigSweep = self.masque_triggerSweep.search(self.port_serie.readline()).group(0)
            if self.TrigSweep == 'AUTO' :
                self.comboBalayage.set_active(0)
            elif self.TrigSweep == 'NORMAL' :
                self.comboBalayage.set_active(1)    
            elif self.TrigSweep == 'SINGLE' :
                self.comboBalayage.set_active(2)    
            
            else :
                self.self.comboBalayage.set_active(1)
                self.port_serie.write(':TRIGger:EDGE:SWEep NORMAL' + '\n')
            
        except :
            self.lb_debug.set_text('erreur de lecture')
        
        
    def on_colorbutton_fond_color_set(self, user_data):
        self.couleur_fond = self.colorbutton_fond.get_rgba()
        self.zone_ecran.queue_draw()
        

    def on_colorbutton_math_color_set(self, user_data):
        self.couleur_math = self.colorbutton_math.get_rgba()
        self.zone_ecran.queue_draw()

    def on_colorbutton1_color_set(self, user_data):
        self.couleur_ch1 = self.colorbutton1.get_rgba()
        self.zone_ecran.queue_draw()

    def on_colorbutton2_color_set(self, user_data):
        self.couleur_ch2 = self.colorbutton2.get_rgba()
        self.zone_ecran.queue_draw()

    def on_sb_ligne_value_changed(self, user_data):
        self.epaisseur_ligne = int(self.sb_ligne.get_value())
        self.zone_ecran.queue_draw()
            
    def on_bt_aff_ch1_toggled(self,widget):
        if widget.get_active():
            self.Affiche_S1 = False
            self.lb_CH1.set_text("")        
        else:
            self.Affiche_S1 = True
                                
    def on_bt_aff_ch2_toggled(self,widget):
        if widget.get_active():
            self.Affiche_S2 = False
            self.lb_CH2.set_text("")        
        else:
            self.Affiche_S2 = True
                        
    def on_bt_aff_bdt_toggled(self,widget):
        if widget.get_active():
            self.Affiche_BdT = False    
            self.lb_BdT.set_text("")    
        else:
            self.Affiche_BdT = True
    
    def tracer_grille(self,cr):
        self.epaisseur_ligne = int(self.sb_ligne.get_value())
        #Tracé du tour et des axes centraux :
        cr.set_line_width(2)
        cr.set_source_rgb(self.couleur_fond.red,self.couleur_fond.green,self.couleur_fond.blue)
        cr.rectangle(0, 0, 620, 580)
        cr.fill()
        cr.set_source_rgb(0,0,0)
        cr.move_to(10,10)
        cr.rel_line_to(0, 400)
        cr.rel_line_to(600,0)
        cr.rel_line_to(0,-400)
        cr.rel_line_to(-600,0)
        cr.move_to(10,210)
        cr.rel_line_to(600,0)
        cr.move_to(310,10)
        cr.rel_line_to(0,400)
        for i in range (40):
            cr.move_to(305,10*i + 10)
            cr.rel_line_to(10,0)
        for i in range (120):
            cr.move_to(10 * i + 10,205)
            cr.rel_line_to(0,10)
        cr.stroke()
        # tracé de la grille secondaire :
        cr.set_line_width(0.5)
        for i in range (12):
            cr.move_to(50 * i + 10,10)
            cr.rel_line_to(0,400)
        for i in range (8):
            cr.move_to(10,50*i + 10)
            cr.rel_line_to(600,0)
        cr.stroke()
    
    def tracer_courbes(self,cr):
        cr.set_line_width(self.epaisseur_ligne)

        if self.ModeYT == True:
            if self.Ch1active == True:
                #tracé de CH1:
            
                cr.set_source_rgb(self.couleur_ch1.red,self.couleur_ch1.green,self.couleur_ch1.blue)
                try:
                    #tracé du repère 0 de la voie 1
                    cr.move_to(0 ,210 - 5*self.scaleCH1.get_value())
                    cr.line_to(10, 210 - 5*self.scaleCH1.get_value())
                    cr.stroke()
                    #tracé du repère du trigger :
                    if self.TrigSource == 0:
                        cr.move_to(310 - 5*self.scaleBdT.get_value(), 0)
                        cr.line_to(310 - 5*self.scaleBdT.get_value(), 10)
                        cr.stroke()    
                    #tracé de la courbe CH1
                    for i in range (217,816):
                        if self.Gnd1 == False:
                            cr.move_to(i-207 ,2*self.data_ch1[i]-40)
                            cr.line_to(i-206, 2*(self.data_ch1[i+1])-40)
                            cr.stroke()
                        else:
                            cr.move_to(0 ,210 - 5*self.scaleCH1.get_value())
                            cr.line_to(610, 210 - 5*self.scaleCH1.get_value())
                            cr.stroke()
                    
                except:
                    self.lb_debug.set_text("")
                

            if self.Ch2active == True:
                #tracé de CH2:
                
                cr.set_source_rgb(self.couleur_ch2.red,self.couleur_ch2.green,self.couleur_ch2.blue)

                try:
                    cr.move_to(0 ,210 - 5*self.scaleCH2.get_value())
                    cr.line_to(10, 210 - 5*self.scaleCH2.get_value())
                    cr.stroke()
                    #tracé du repère du trigger :
                    if self.TrigSource == 1:
                        cr.move_to(310 - 5*self.scaleBdT.get_value(), 0)
                        cr.line_to(310 - 5*self.scaleBdT.get_value(), 10)
                        cr.stroke()    
                    for i in range (217,816):
                        if self.Gnd2 == False:
                            cr.move_to(i-207 ,2*self.data_ch2[i]-40)
                            cr.line_to(i-206, 2*(self.data_ch2[i+1])-40)
                            cr.stroke()
                        else:
                            cr.move_to(0 ,210 - 5*self.scaleCH2.get_value())
                            cr.line_to(610, 210 - 5*self.scaleCH2.get_value())
                            cr.stroke()
                        
                except:
                    self.lb_debug.set_text("")
            if self.FFTactive == True:
                #tracé de la FFT:
                cr.set_line_width(self.epaisseur_ligne)
                cr.set_source_rgb(self.couleur_math.red,self.couleur_math.green,self.couleur_math.blue)
                try:
                    for i in range (217,816):
                        cr.move_to(i-207 ,2*self.data_FFT[i]-40)
                        cr.line_to(i-206, 2*(self.data_FFT[i+1])-40)
                        cr.stroke()
                        
                except:
                    self.lb_debug.set_text("")

        #Mode XY             
        if self.ModeXY == True:    
            
            #tracé de la courbe XY
            cr.set_line_width(self.epaisseur_ligne)
            cr.set_source_rgb(self.couleur_ch1.red,self.couleur_ch1.green,self.couleur_ch1.blue)
            if self.Ch1active == True and self.Ch2active == True:        
                for i in range (217,816):
                    if (self.Gnd1 == False) and (self.Gnd2 == False):
                        cr.move_to(560-2*self.data_ch1[i] , 2*self.data_ch2[i] -40 )
                        cr.line_to(560-2*self.data_ch1[i+1], 2* self.data_ch2[i+1] -40)                                    
                    else:
                        self.lb_debug.set_text('Choisir un couplage <> GND')
                    cr.stroke()
                                
    def on_zone_ecran_draw(self, widget,cr):
        self.tracer_grille(cr)
        self.tracer_courbes(cr)
        self.tracer_curseurs(cr)
        
    def on_zone_ecran_button_press_event(self, widget, event):
        print "Mouse clicked... at ", event.x, ", ", event.y
        # How to draw a line starting at this point on the drawing area?        
        return True
           
    def on_sw_ch1_button_press_event(self,widget,event):
        self.Ch1active = not self.Ch1active

    def on_bt_plus_ch1_clicked(self,widget):    
        if (self.index1 < self.index_Vmax) :
            self.port_serie.write(':CHAN1:SCAL ' + self.env_cal[self.index1 +1]  + '\n' )    
            sleep(0.01)
            self.lire_reglages_sensibilites()
    
    def on_bt_moins_ch1_clicked(self,widget):
        if (self.index1 > self.index_Vmin) :
            self.port_serie.write(':CHAN1:SCAL ' + self.env_cal[self.index1 - 1]  + '\n' )    
            sleep(0.01)
            self.lire_reglages_sensibilites()
            
    def on_scaleCH1_value_changed(self,widget):
        self.decalage_CH1 = self.scaleCH1.get_value()
        self.envoi_decalage_CH1 = str(float(self.sensib1)*self.decalage_CH1/10)
            
        self.port_serie.write(':CHAN1:OFFS ' + (self.envoi_decalage_CH1) + '\n')
        sleep(0.01)
    
    def on_scaleCH1_button_press_event(self,widget,event):
        self.scaleCH1.set_value(0)
    
    def on_combo_couplage1_changed(self,widget):
        #régler couplage CH1 selon choix logiciel :
        self.Couplage1 = self.combo_couplage1.get_active()
        if self.Couplage1  == 0:
            self.Gnd1 = False
            self.port_serie.write(':CHANnel1:COUPling DC' + '\n' )
        if self.Couplage1  == 1:
            self.Gnd1 = False
            self.port_serie.write(':CHANnel1:COUPling AC' + '\n' )
        if self.Couplage1  == 2:
            self.port_serie.write(':CHANnel1:COUPling GND' + '\n' )
            self.Gnd1 = True
        
    def on_bt_plus_ch2_clicked(self,widget):    
        if (self.index2 < self.index_Vmax) :
            self.port_serie.write(':CHAN2:SCAL ' + self.env_cal[self.index2 +1]  + '\n' )    
            sleep(0.01)
            self.lire_reglages_sensibilites()
    
    def on_bt_moins_ch2_clicked(self,widget):
        if (self.index2 > self.index_Vmin) :
            self.port_serie.write(':CHAN2:SCAL ' + self.env_cal[self.index2 - 1]  + '\n' )    
            sleep(0.01)
            self.lire_reglages_sensibilites()
    
    def on_scaleCH2_value_changed(self,widget):
        self.decalage_CH2 = self.scaleCH2.get_value()
        self.envoi_decalage_CH2 = str(float(self.sensib2)*self.decalage_CH2/10)
            
        self.port_serie.write(':CHAN2:OFFS ' + (self.envoi_decalage_CH2) + '\n')
        sleep(0.01)
    
    def on_scaleCH2_button_press_event(self,widget,event):
        self.scaleCH2.set_value(0)    
    
    def on_combo_couplage2_changed(self,widget):
        #régler couplage CH2 selon choix logiciel :
        self.Couplage2 = self.combo_couplage2.get_active()
        if self.Couplage2  == 0:
            self.Gnd2 = False
            self.port_serie.write(':CHANnel2:COUPling DC' + '\n' )
        if self.Couplage2  == 1:
            self.Gnd2 = False
            self.port_serie.write(':CHANnel2:COUPling AC' + '\n' )
        if self.Couplage2  == 2:
            self.Gnd2=True
            self.port_serie.write(':CHANnel2:COUPling GND' + '\n' )
            
    def on_bt_plus_BdT_clicked(self,widget):
        
        if (self.indexH < self.index_Hmax) :
            self.port_serie.write(':TIM:SCAL ' + self.env_cal[self.indexH +1]  + '\n' )    
            sleep(0.01)
            self.lire_reglages_sensibilites()
            
    def on_bt_moins_BdT_clicked(self,widget):
        if (self.indexH > self.index_Hmin) :
            self.port_serie.write(':TIM:SCAL ' + self.env_cal[self.indexH - 1]  + '\n' )    
            sleep(0.01)
            self.lire_reglages_sensibilites()
    
    def on_scaleBdT_value_changed(self,widget):
        self.decalage_Horizontal = self.scaleBdT.get_value()
        self.envoi_decalage_Horizontal = str("{:1.8f}".format(float(self.BdT)*self.decalage_Horizontal/10))
        self.port_serie.write(':TIM:OFFS ' + (self.envoi_decalage_Horizontal) + '\n')
        sleep(0.01)
        self.lb_decalage_horizontal.set_text(str("{:1.1f}".format(float(-self.decalage_Horizontal/10)) + ' div'))
        
    def on_scaleBdT_button_press_event(self,widget,event):
        self.scaleBdT.set_value(0)    
        
    def on_comboBdT_changed(self,widget):
        self.lb_CAX.set_text('          ')
        self.lb_CAY.set_text('          ')
        self.lb_CBX.set_text('          ')
        self.lb_CBY.set_text('          ')
        self.lb_CdX.set_text('          ')
        self.lb_CdY.set_text('          ')
            
        #choisir le mode : YT ou XY
        self.FormatBdt = self.comboBdT.get_active()
        if self.FormatBdt == 0:
            self.comboCurseurY.set_sensitive(True)
            self.port_serie.write(':TIM:FORM YT' + '\n' )
            self.ModeYT = True
            self.ModeXY = False
            
        if self.FormatBdt == 1:
            self.comboCurseurY.set_active(1)
            self.comboCurseurY.set_sensitive(False)
            if self.Ch1active == False :
                self.sw_ch1.set_active(True)
                self.Ch1active = True
            if self.Ch2active == False :
                self.sw_ch2.set_active(True)
                self.Ch2active = True
            #self.port_serie.write(':TIM:FORM XY' + '\n' )
            self.ModeYT = False
            self.ModeXY = True        
                    
    def on_sw_ch2_button_press_event(self,widget,event):
        self.Ch2active = not self.Ch2active
    
    
    def on_comboTrigSource_changed(self,widget):
        #régler Trigger selon choix logiciel :
        self.TrigSource = self.comboTrigSource.get_active()
        if self.TrigSource == 0:
            self.port_serie.write(':TRIG:EDGE:SOURce CHANnel1' + '\n' )
        if self.TrigSource == 1:
            self.port_serie.write(':TRIG:EDGE:SOURce CHANnel2' + '\n' )
        if self.TrigSource == 2:
            self.port_serie.write(':TRIG:EDGE:SOURce EXT' + '\n' )
        
    def on_comboBalayage_changed(self,widget):
        # régler le type de balayge selon choix logiciel :
        self.TrigSweep = self.comboBalayage.get_active()
        if self.TrigSweep == 0 :
            self.port_serie.write(':TRIGger:EDGE:SWEep AUTO' + '\n')
        if self.TrigSweep == 1 :
            self.port_serie.write(':TRIGger:EDGE:SWEep NORMAL' + '\n')
        if self.TrigSweep == 2 :
            self.port_serie.write(':TRIGger:EDGE:SWEep SINGLE' + '\n')
        
    def on_comboTrigFront_changed(self,widget):
        self.TrigFront = self.comboTrigFront.get_active()
        if self.TrigFront == 0 :
            self.port_serie.write(':TRIGger:EDGE:SLOPe POSitive' + '\n' )
        if self.TrigFront == 1 :
            self.port_serie.write(':TRIGger:EDGE:SLOPe NEGative' + '\n' )
            
    def on_scaleTrigger_value_changed(self,widget):    
        self.niveau_trigger = self.scaleTrigger.get_value()
        self.TrigSource = self.comboTrigSource.get_active()
        if self.TrigSource == 0:
            self.envoi_trigger = str(float(self.sensib1)*self.niveau_trigger/10)
            self.lb_niveau_trigger.set_text(str("{:1.2f}".format(float(self.sensib1)*self.niveau_trigger/10) + 'V'))
        if self.TrigSource == 1:
            self.envoi_trigger = str(float(self.sensib2)*self.niveau_trigger/10)
            self.lb_niveau_trigger.set_text(str("{:1.2f}".format(float(self.sensib2)*self.niveau_trigger/10) + 'V'))
            
        self.port_serie.write(':TRIG:EDGE:LEV ' + (self.envoi_trigger) + '\n')
        sleep(0.01)
    
    def on_scaleTrigger_button_press_event(self,widget,event):
        self.scaleTrigger.set_value(0)    
        
    def acquisition(self):
        if self.timer_id is not None:
            self.port_serie.flushInput()
            
            self.lire_reglages_sensibilites()

            self.port_serie.write(':WAV:POIN:MODE NOR' + '\n' )
            sleep(0.01)
            #acquisition voie 1 :
            self.port_serie.flushInput()
            sleep(0.01)
            for i in range (self.longueur_data):
                    self.data_ch1 = [0]
                    self.data_ch2 = [0]
                    self.data_FFT = [0]
            
            if self.Ch1active == True:
                self.port_serie.write(':WAVeform:DATA? CHANnel1' + '\n')
                sleep(0.3)            
                
                lecture1 = self.port_serie.read(self.longueur_data)
                try:
                    for i in range (self.longueur_data):
                        self.data_ch1.append(ord(lecture1[i]))
                except:
                    self.lb_debug.set_text("")
                        
            #acquisition voie 2 :
            self.port_serie.flushInput()
            sleep(0.01)
            
            if self.Ch2active == True:
                self.port_serie.write(':WAVeform:DATA? CHANnel2' + '\n')
                sleep(0.1)        
                
                lecture2 = self.port_serie.read(self.longueur_data)
                try:
                    for i in range (self.longueur_data):
                        self.data_ch2.append(ord(lecture2[i]))
                except:
                    self.lb_debug.set_text("")
            
            if self.FFTactive == True:
                self.port_serie.write(':WAVeform:DATA? FFT' + '\n')
                sleep(0.3)            
                
                lectureFFT = self.port_serie.read(self.longueur_data)
                try:
                    for i in range (self.longueur_data):
                        self.data_FFT.append(ord(lectureFFT[i]))
                except:
                    self.lb_debug.set_text("")    
                
            self.zone_ecran.queue_draw()
            return True
            
        return False


    def on_btRafraichir_clicked(self,widget):
        #Rafraichir la liste des ports série disponibles
        self.comboPort.remove_all()
        self.lister_ports()

    def on_btOuvrir_clicked(self,widget):
        # recuperation des parametres choisis :
        self.port_choisi = '/dev/' + self.comboPort.get_active_text()
        debit = self.comboBauds.get_active_text()
        
        data_format = serial.EIGHTBITS
        stop = serial.STOPBITS_ONE
        parite = serial.PARITY_NONE
        try:
            # desactivation de widgets (ceux qui ne doivent pas
            # etre modifies une fois le port serie ouvert) :
            self.comboPort.set_sensitive(False)
            self.btRafraichir.set_sensitive(False)
            self.btQuitter.set_sensitive(True)


            #ouverture du port serie :
            self.port_serie = serial.Serial(
                port=self.port_choisi,
                baudrate = debit,
                bytesize = data_format,
                parity = parite,
                stopbits = stop,
                timeout=2
            )

            #activation/desactivation de widgets :
            self.btFermer.set_sensitive(True)
            self.btOuvrir.set_sensitive(False)
            self.comboBauds.set_sensitive(False)
            self.activer_widget_reglages()
            #vidage du port et tentative de contact :
            self.port_serie.flushInput()
            
            self.port_serie.write('*IDN?' + '\n')
            #petit délai avant de lire le retour :
            sleep(0.1)
            data = []
            
            n_data = 0
            n_data = self.port_serie.inWaiting()
            sleep(0.1)
            if n_data > 0 :
                chaine = ""
                for i in range (n_data) :
                    data.append(ord(self.port_serie.read(1)))
                    
                    chaine += chr(data[i])
                identite = chaine.split(',')
                self.lb_idn.set_text(identite[1])
            
            self.port_serie.write(':KEY:LOCK ENABLE' + '\n')
            sleep(0.01)
            self.port_serie.write(':STOP' + '\n')
            sleep(0.01)
            
            
            # ces deux lignes à déplacer par la suite :
            self.port_serie.write(':TIM:MODE MAIN'  + '\n')
            sleep(0.01)
            
            self.lire_reglages_sensibilites()
            self.lire_reglages_trigger()
            self.lire_couplages()
            self.comboBdT.set_active(0)    
            self.ouvert = True
                    
        except :
            self.comboPort.set_sensitive(True)
            self.btOuvrir.set_sensitive(True)
            self.btRafraichir.set_sensitive(True)
            self.ouvert = False
            #self.bt_fermer.set_sensitive(False)
            self.ouvert = False
            msg = "Erreur lors de l'ouverture du port série : ce port n'est peut-être pas valide, ou bien vous n'avez pas les droits pour accéder aux ports série"
            dialog = Gtk.MessageDialog(None, 0, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, msg)
            # Montre le dialog
            dialog.run()
            # Destruction du dialog
            dialog.destroy()

    def fermer_port(self):
        try :
            if self.ouvert == True:
                self.port_serie.write(':STOP' + '\n')
                self.port_serie.write(':KEY:LOCK DISABLE' + '\n')
                self.port_serie.close()
                self.comboPort.set_sensitive(True)
                self.comboBauds.set_sensitive(True)
                self.btOuvrir.set_sensitive(True)
                self.btRafraichir.set_sensitive(True)
                self.btFermer.set_sensitive(False)
                self.lb_idn.set_text("Etat : déconnecté ")
                self.desactiver_widget_reglages()
                self.ouvert = False
        except :
            msgFermer = "Erreur lors de la fermeture du port série !"
            dlgFermer = Gtk.MessageDialog(None, 0, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, msgFermer)
            dlgFermer.run()
            dlgFermer.destroy()
            
    def on_btFermer_clicked(self,widget):
        #fermeture du port série ouvert
        self.fermer_port()

    def on_bt_Auto_clicked(self,widget):
        
        self.port_serie.write(':AUTO' + '\n')
        self.tgb_RunStop.set_active(True)

    def on_tgb_RunStop_toggled(self,widget):

        if widget.get_active():
            self.lire_reglages_sensibilites()
            self.lire_couplages()
            self.lire_reglages_trigger()
            # met les deux entrées en coef 1 :    
            self.port_serie.write(':CHAN1:PROB 1' + '\n')
            sleep(0.01)
            self.port_serie.write(':CHAN2:PROB 1' + '\n')
            sleep(0.01)
            # mode YT :
            self.port_serie.write(':TIM:FORM YT' + '\n' )
            sleep(0.01)
            #mode Run :
            self.port_serie.write(':RUN' + '\n')
            sleep(0.01)
            
            self.timer_id = GObject.timeout_add(self.delai, self.acquisition)
            self.btFermer.set_sensitive(False)
            self.btQuitter.set_sensitive(False)
        else:
            self.timer_id = None
            self.port_serie.write(':STOP' + '\n')
            self.btFermer.set_sensitive(True)
            self.btQuitter.set_sensitive(True)
            
    def on_bt_Manuel_clicked(self,widget):

          self.port_serie.write(':KEY:LOCK DISABLE' + '\n')

# Onglet Mesures :
    # curseurs horizontaux :
    def on_switch_aff_curseurY_button_press_event(self,widget,event):
        self.CurseurYactive = not self.CurseurYactive
        
    def on_colorbutton_curseurY_color_set(self, user_data):
        self.couleur_curseurY = self.colorbutton_curseurY.get_rgba()
        self.zone_ecran.queue_draw()
    
    def on_tgb_Affiche_ValCY_toggled(self,widget):
        if widget.get_active():
            self.Affiche_ValCY = False
            self.lb_CAY.set_text("")
            self.lb_CBY.set_text("")
            self.lb_CdY.set_text("")        
        else:
            self.Affiche_ValCY = True
        
    def on_scaleCAY_value_changed(self,widget):
        self.PosCursYA = self.scaleCAY.get_value()
        
    
    def on_scaleCBY_value_changed(self,widget):
        self.PosCursYB = self.scaleCBY.get_value()
                    
    # curseurs verticaux    
    def on_switch_aff_curseurX_button_press_event(self,widget,event):
        self.CurseurXactive = not self.CurseurXactive
        
    def on_colorbutton_curseurX_color_set(self, user_data):
        self.couleur_curseurX = self.colorbutton_curseurX.get_rgba()
        self.zone_ecran.queue_draw()
        
    def on_tgb_Affiche_ValCX_toggled(self,widget):
        if widget.get_active():
            self.Affiche_ValCX = False
            self.lb_CAX.set_text("")
            self.lb_CBX.set_text("")
            self.lb_CdX.set_text("")        
        else:
            self.Affiche_ValCX = True
            
    def on_scaleCAX_value_changed(self,widget):
        self.PosCursXA = self.scaleCAX.get_value()
    
    def on_scaleCBX_value_changed(self,widget):
        self.PosCursXB = self.scaleCBX.get_value()    
                
    def tracer_curseurs(self,cr):
        if self.CurseurYactive == True:
            #tracé des curseurs horizontaux :
            cr.set_dash([12,12])
            cr.set_source_rgb(self.couleur_curseurY.red,self.couleur_curseurY.green,self.couleur_curseurY.blue)
            cr.move_to(10 ,self.PosCursYA)
            cr.line_to(610, self.PosCursYA)
            cr.move_to(10 ,self.PosCursYB)
            cr.line_to(610, self.PosCursYB)    
            cr.stroke()
            #affichage des valeurs des curseurs horizontaux :
            if self.Affiche_ValCY == True:
                if self.ModeYT == True:
                    self.ChoixVoie = self.comboCurseurY.get_active()
                    if self.ChoixVoie  == 0:
                        self.sensib = self.sensib1
                    if self.ChoixVoie  == 1:
                        self.sensib = self.sensib2
                if self.ModeXY == True:
                    self.sensib = self.sensib2
            
                self.ValCA = float(self.sensib)*((210 - 5*self.scaleCH1.get_value())-self.PosCursYA)
                self.ValCB = float(self.sensib)*((210 - 5*self.scaleCH1.get_value())-self.PosCursYB)
                if float(self.sensib) < 1 :
                    self.lb_CAY.set_text(str(int(20*self.ValCA)) + " mV")
                    self.lb_CBY.set_text(str(int(20*self.ValCB)) + " mV")
                    self.lb_CdY.set_text(str(int(20*(self.ValCA - self.ValCB))) + " mV")
                else:
                    self.lb_CAY.set_text(str("{:1.2f}".format(0.02*self.ValCA) + " V"))
                    self.lb_CBY.set_text(str("{:1.2f}".format(0.02*self.ValCB) + " V"))
                    self.lb_CdY.set_text(str("{:1.2f}".format(0.02*(self.ValCA - self.ValCB))) + " V")
    
        if self.CurseurXactive == True:        
            #tracé des curseurs verticaux :
            cr.set_dash([12,12])
            cr.set_source_rgb(self.couleur_curseurX.red,self.couleur_curseurX.green,self.couleur_curseurX.blue)
            cr.move_to(self.PosCursXA,10)
            cr.line_to(self.PosCursXA,410)
            cr.move_to(self.PosCursXB,10)
            cr.line_to(self.PosCursXB,410)    
            cr.stroke()
            
            #affichage des valeurs des curseurs verticaux :
            if self.Affiche_ValCX == True:
                if self.ModeYT == True:
                    self.ValCA = float(self.BdT)*(self.PosCursXA - (310 - 5*self.scaleBdT.get_value()))
                    self.ValCB = float(self.BdT)*(self.PosCursXB - (310 - 5*self.scaleBdT.get_value()))
                    if float(self.BdT) < 1E-6 :    
                        self.lb_CAX.set_text(str("{:1.2f}".format(2E7*self.ValCA) + " ns"))
                        self.lb_CBX.set_text(str("{:1.2f}".format(2E7*self.ValCB) + " ns"))
                        self.lb_CdX.set_text(str("{:1.2f}".format(2E7*(self.ValCB - self.ValCA ))) + " ns")
                    elif float(self.BdT) < 1E-3 :
                        self.lb_CAX.set_text(str("{:1.2f}".format(2E4*self.ValCA)) + " " + u"\u03BC" +  "s")
                        self.lb_CBX.set_text(str("{:1.2f}".format(2E4*self.ValCB))  + " " + u"\u03BC" +  "s")
                        self.lb_CdX.set_text(str("{:1.2f}".format(2E4*(self.ValCB - self.ValCA)))  + " " + u"\u03BC" +  "s")
                    elif float(self.BdT) < 1 :
                        self.lb_CAX.set_text(str("{:1.2f}".format(20*self.ValCA) + " ms"))
                        self.lb_CBX.set_text(str("{:1.2f}".format(20*self.ValCB) + " ms"))
                        self.lb_CdX.set_text(str("{:1.2f}".format(20*(self.ValCB - self.ValCA))) + " ms")
                    else:
                        self.lb_CAX.set_text(str("{:1.2f}".format(0.02*self.ValCA) + " s"))
                        self.lb_CBX.set_text(str("{:1.2f}".format(0.02*self.ValCB) + " s"))
                        self.lb_CdX.set_text(str("{:1.2f}".format(0.02*(self.ValCB - self.ValCA))) + " s")
                
                if self.ModeXY == True:
                    self.sensib = self.sensib1
            
                    self.ValCA = float(self.sensib)*(self.PosCursXA - (310 - 5*self.scaleCH1.get_value()))
                    self.ValCB = float(self.sensib)*(self.PosCursXB - (310 - 5*self.scaleCH1.get_value()))
                    if float(self.sensib) < 1 :
                        self.lb_CAX.set_text(str(int(20*self.ValCA)) + " mV")
                        self.lb_CBX.set_text(str(int(20*self.ValCB)) + " mV")
                        self.lb_CdX.set_text(str(int(20*(self.ValCA - self.ValCB))) + " mV")
                    else:
                        self.lb_CAX.set_text(str("{:1.2f}".format(0.02*self.ValCA) + " V"))
                        self.lb_CBX.set_text(str("{:1.2f}".format(0.02*self.ValCB) + " V"))
                        self.lb_CdX.set_text(str("{:1.2f}".format(0.02*(self.ValCB - self.ValCA))) + " V")
                    
        self.zone_ecran.queue_draw()

    def on_btQuitter_clicked(self,widget):
        self.fermer_port()
        sleep(0.1)
        Gtk.main_quit()

    def destroy(window, self):
        Gtk.main_quit()

def main():

    app = RIGOLINUX()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())

 

 download_manager.png Le programme à télécharger : Rigolinux V1.4

Ce programme s'appuie sur des modules Python  :

  • python-serial 
  • python-gi-cairo,

à installer avec le gestionnaire de paquets (par exemple Synaptic sur une distribution Debian).

Historique :

Rigolinux V1_31 : Correction d'un bug sur le trigger

Rigolinux_V1_3 : Possibilité de travailler en mode X-Y. L'onglet Mesures s'adapte à ce mode.(11 Juillet 2014)

Rigolinux V1_1 : L'onglet "Aide" (dans lequel il n'y avait aucune aide !) a été remplacé par un onglet
"Mesures" dans lequel on peut, à l'aide de curseurs verticaux ou horizontaux faire des
 mesures absolues et relatives. (Date de publication : 26 Juin 2014)

Rigolinux V1_05 :
-en mode Run, les entrées CH1 et CH2 sont mises systématiquement au coefficient 1
-les modes de couplage (DC,AC et Gnd) sont utilisables

Rigolinux V1_04 :
- ajouts de repères sur le bord de l'écran (0V des voies 1 et 2 et position temporelle du Trigger)
- la position temporelle du Trigger est maintenant réglable
- Le repère du Trigger prend la couleur de la voie de déclenchement.
- Les réglages de décalage (voies 1 et 2, horizontal et niveau du trigger peuvent être remis à 0 par un double-clic) (8 Mai 2014)