In [1]:
%pylab inline
import serial  # nécessite l'installation du module pyserial
from time import time
Populating the interactive namespace from numpy and matplotlib

Récupération des données par le port série

Exécuter la première cellule et la dernière (fonctions support).

La fonction lectureSerie permet de récupérer dans un tableau numpy de flottants et dans un fichier texte des données transmises sur le port série.

Les données sont lues ligne par ligne sur le port série. Chaque ligne doit comporter des entiers ou flottants, transmis sous forme de chaînes de caractères, séparées uniquement par un caractère espace.

2 opérations à réaliser :

  1. récupérer le nom du port série connecter à la carte Arduino ("COM5" par exemple) et utiliser la fonction initPortSerie pour configurer la connection. Cette fonction ne peut être exécutée plusieur fois.
  2. utiliser la fonction lectureSerie pour lire les données et, de façon optionnelle, créer un fichier texte.

Un fichier texte contenant les données est créé uniquement si un nom de fichier est transmis. Les données peuvent facilement être récupérées avec np.loadtxt.

Il est possible de définir la durée de communication (15s par défaut). Par défaut, les 5 premières lignes sont affichées. La définition est :

def lectureSerie(ser, duree=15, affiche=5, fichier=None):

Ci-dessous un exemple d'utilisation à adapter.

In [ ]:
# INITIALISATION du port série (à n'éxécuter qu'une seule fois)
ser = initPortSerie("COM5",115200)
In [ ]:
# lecture des données sur le port série pendant 10s et créaction d'un fichier data.txt
data=lectureSerie(ser, 10, fichier="data.txt") # données récupérées dans la variable data 
In [2]:
data = np.loadtxt("data.txt")
t = np.linspace(0, (len(data)-1) * 0.1, len(data))
vG, vD, vitG, vitD = data[:,0], data[:,1], data[:,2], data[:,3]
plt.plot(t,vG, label="vG")
plt.plot(t,vG, label="vD")
plt.plot(t,vitG, label="vitG")
plt.plot(t,vitD, label="vitD")
plt.grid()
plt.legend()
Out[2]:
<matplotlib.legend.Legend at 0x11a1a9be0>
In [9]:
plt.figure(figsize=(10,3))
plt.subplot(121)
plt.plot(t,vG, label="vG")
plt.plot(t,vG, label="vD")
plt.plot(t,vitG, label="vitG")
plt.plot(t,vitD, label="vitD")
plt.grid()
plt.legend()
plt.xlim(0, 1)
plt.ylim(0,1000)

plt.subplot(122)
plt.plot(t,vG, label="vG")
plt.plot(t,vG, label="vD")
plt.plot(t,vitG, label="vitG")
plt.plot(t,vitD, label="vitD")
plt.grid()
plt.legend()
plt.xlim(3.25, 4.5)
plt.ylim(0,1000)
Out[9]:
(0, 1000)

Fonctions support pour récupérer des données par le port série

Les fonctions ci-dessous permettent de récupérer les informations envoyées par le microcontroleur sur le port série avec la fonction Serial.print et Serial.println.

La lecture est réalisée ligne par ligne et se termine à la lecture d'une ligne comprenant l'unique mot : fin. La lecture s'arrête aussi au bout d'un temps de prédéfini (15s par défaut).

Par défaut, le débit doit être le plus important possible : 115200 bauds

Le nom du port est affiché en bas à gauche des fenêtre de l'environnement Arduino.

La fonction la plus importante est lectureSerie.

In [1]:
def initPortSerie(port,baud=9600):
    """Initialise le port série port et retourne un objet de type serial.Serial"""
    ser=serial.Serial();
    ser.port = port
    ser.baudrate = baud # doit être identique au débit du programme arduino
    print("Configurer le port série de l'Arduino avec : Serial.begin(",baud,");\n")
    return ser

def ouverturePortSerie(ser):
    """Ouvre en lecture le port ser, objet de type serial.Serial."""
    ser.open()                              # Ouverture du port série
    print("port série ouvert :",ser.port)
    ser.flushInput() ; ser.flushOutput()    # Vider les buffers d'entree et de sortie

def fermeturePortSerie(ser):
    """Ferme le port ser, objet de type serial.Serial."""
    ser.close()                                 # Fermeture du port série
    ser.close()
    print("port série fermé :",ser.port)

def traitement(ligne,nbligne=-1):
    """Traitement par défaut des lignes lues sur le port série.
    Cette fonction affiche chaque ligne lue ainsi que son numéro."""
    print(nbligne,"-->",ligne)
    
def lecture(ser,f=traitement,duree=15):
    """Lit, ligne par ligne, les données sur le port ser (objet de type serial.Serial).
    La lecture s'arrete lorsqu'une ligne est constituée de l'unique mot 'fin',
    ou au bout d'un temps de 15 s par défaut (duree).
    Chaque ligne lue avec son numéro est transmise à la fonction f.
    Par défaut la fonction f est la fonction de nom 'traitement' réalisant l'affichage 
    de la ligne."""
    ouverturePortSerie(ser) # ouverture
    fin=False
    tdebut=time()
    nbligne=0
    while (not fin) and (time()-tdebut)<duree:
        # lecture des lignes
        lignes=[]
        while ser.inWaiting():        # on remplit le buffer avec les données en attente sur le port série
            try :
                lignes.append(ser.readline().decode("utf8").strip())
                if lignes[-1]=="fin": fin=True
            except :
                print("il y a une donnee incorrecte")
                fin=True
        # traitement des lignes lues
        for l in lignes:
            if l!="fin":
                try:
                    f(l,nbligne)
                except:
                    fermeturePortSerie(ser)
                    raise
                nbligne=nbligne+1
    fermeturePortSerie(ser)
        
def lectureSerie(ser, duree=15, affiche=5, fichier=None):
    """Lit sur le port série, pendant la durée indiquée, les données et les converties 
    en tableau de flottant.
    Les données doivent être séparées par le caractère espace.
    Séparateur décimal : . (le point).
    Affiche les affiche premières lignes lues.
    Les donnes peuves être enregistrée dans un fichier texte avec l'espace comme séparateur."""
    data=[]
    if fichier is not None:
        fic = open(fichier,'w')
    def recup(l,n):
        if n==0 and affiche>0: print(str(affiche)+" premières lignes récupérées :")
        if n<affiche: print(l)
        
        A=l.split(" ")
        try:
            data.append(np.array([float(val) for val in A]))
        except ValueError:
            if fichier is not None: fic.close()
            raise ValueError("La ligne "+l+" ne peut être convertie en liste de flottants.")
            
        if fichier is not None:
            fic.write(l + "\n")
        
    lecture(ser, recup, duree)
    if fichier is not None: fic.close()
    return np.array(data)