{"id":674,"date":"2021-02-19T17:09:42","date_gmt":"2021-02-19T16:09:42","guid":{"rendered":"http:\/\/labopothier.com\/?p=674"},"modified":"2024-09-10T08:09:44","modified_gmt":"2024-09-10T06:09:44","slug":"activite-arduino-python-recuperer-les-donnees-serie-dune-balance-envoyees-par-liaison-usb","status":"publish","type":"post","link":"https:\/\/labopothier.com\/index.php\/2021\/02\/19\/activite-arduino-python-recuperer-les-donnees-serie-dune-balance-envoyees-par-liaison-usb\/","title":{"rendered":"ACTIVITE PYTHON : r\u00e9cup\u00e9rer les donn\u00e9es s\u00e9rie d&rsquo;une balance (envoy\u00e9es par liaison USB)"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/www.youtube.com\/watch?v=5dH3SdCRWFU&amp;t=224s\"><img decoding=\"async\" src=\"https:\/\/labopothier.com\/wp-content\/uploads\/2021\/03\/balance-1024x576-1.jpg\" alt=\"\" class=\"wp-image-799\"\/><\/a><\/figure>\n\n\n\n<p><strong>Objectif de cette activit\u00e9 :<\/strong> R\u00e9cup\u00e9rer dans Python les donn\u00e9es d&rsquo;une balance \u00ab\u00a0interfa\u00e7able\u00a0\u00bb ou d&rsquo;un autre type d&rsquo;appareil avec connexion USB ou s\u00e9rie.<\/p>\n\n\n\n<p><strong>Pr\u00e9-requis : <\/strong> \u00eatre familier avec le langage Python <\/p>\n\n\n\n<p>Pour l&rsquo;initiation au langage Python , je vous invite \u00e0 consulter cet article :<a href=\" https:\/\/labopothier.com\/index.php\/2020\/04\/21\/initiation-au-langage-python\"> Initiation au langage Python<\/a><\/p>\n\n\n\n<p>Nous avons au laboratoire une balance avec prise USB et prise RS232. Nous souhaitons r\u00e9cup\u00e9rer les donn\u00e9es mais le logiciel du fournisseur est un peu co\u00fbteux. Notre but est donc de voir si cette balance envoie spontan\u00e9ment des messages de type cha\u00eene de caract\u00e8res \u00e0 intervalle r\u00e9gulier. Si c&rsquo;est le cas, il pourrait \u00eatre possible de r\u00e9cup\u00e9rer ces donn\u00e9es avec le langage Python, et donc de r\u00e9aliser des acquisitions temporelles avec trac\u00e9 de graphe, exporter les donn\u00e9es au format txt,&#8230;<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-id=\"686\" src=\"https:\/\/labopothier.com\/wp-content\/uploads\/2021\/02\/IMG-1682.jpg\" alt=\"\" class=\"wp-image-686\"\/><\/figure>\n<\/figure>\n\n\n\n<p>Il a fallu param\u00e9trer pr\u00e9alablement cette balance pour activer le port USB et r\u00e9gler le d\u00e9bit \u00e0 9600 bauds.<\/p>\n\n\n\n<p>V\u00e9rifier que la biblioth\u00e8que <strong>serial <\/strong>est install\u00e9e en \u00e9crivant dans le shell (interpr\u00e9teur)<strong> import serial<\/strong>. Si un message d&rsquo;erreur appara\u00eet, installer <strong>serial <\/strong>en \u00e9crivant dans le shell :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">pip install serial<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Etape 1 : R\u00e9cup\u00e9rer les valeurs dans Python pour les stocker dans une liste<\/strong><\/h2>\n\n\n\n<p>Pour la communication avec la liaison s\u00e9rie de la carte Arduino (via le c\u00e2ble USB), il faut importer la biblioth\u00e8que <strong>serial <\/strong>en \u00e9crivant ces deux lignes :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#Importation des modules\nimport serial\nimport serial.tools.list_ports   # pour la communication avec le port s\u00e9rie<\/code><\/pre>\n\n\n\n<p>On initialise la liste pour les mesures de masses:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#initialisation des listes\nliste_masse = []<\/code><\/pre>\n\n\n\n<p>On d\u00e9finit une fonction qui permet \u00e0 la fois :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>de d\u00e9tecter <strong>automatiquement <\/strong>le port s\u00e9rie utilis\u00e9 par la carte Arduino <\/li>\n\n\n\n<li>de se <strong>connecter <\/strong>\u00e0 la carte<\/li>\n\n\n\n<li>de <strong>r\u00e9cup\u00e9rer <\/strong>les donn\u00e9es s\u00e9rie venant de la carte<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\"># Fonction pour la r\u00e9cup\u00e9ration des donn\u00e9es s\u00e9rie venant de la balance\ndef recup_port_USB() :\n    ports = list(serial.tools.list_ports.comports())\n    for p in ports:\n        if 'USB' in p.description :\n            mData = serial.Serial(p.device,9600)\n    print(mData.is_open) # Affiche et v\u00e9rifie que le port est ouvert\n    print(mData.name) # Affiche le nom du port \n    return mData\n<\/code><\/pre>\n\n\n\n<p><strong>Remarque <\/strong>: cette fonction a \u00e9t\u00e9 \u00e9crite ici de la mani\u00e8re la plus basique possible, on pourrait rajouter des lignes de code suppl\u00e9mentaires pour g\u00e9rer les exceptions (pas de balance d\u00e9tect\u00e9e, choisir entre plusieurs balances connect\u00e9es en m\u00eame temps &#8230;)<\/p>\n\n\n\n<p>Ensuite on fait appel \u00e0 cette fonction pour r\u00e9cup\u00e9rer les donn\u00e9es :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">Data = recup_port_USB()<\/code><\/pre>\n\n\n\n<p>Pour lire une ligne de donn\u00e9es, il faut utiliser la m\u00e9thode <strong>.readline()<\/strong> pour r\u00e9cup\u00e9rer chaque ligne sous forme de cha\u00eene de caract\u00e8res.<\/p>\n\n\n\n<p>La m\u00e9thode<strong> .strip()<\/strong> permettra de supprimer les caract\u00e8res d&rsquo;espacement et de tabulation en d\u00e9but et fin de cha\u00eene. <\/p>\n\n\n\n<p>On utilisera aussi la m\u00e9thode <strong>.split()<\/strong> pour s\u00e9parer les diff\u00e9rentes informations de la ligne pour les stocker dans une liste.<\/p>\n\n\n\n<p>On essaie pour l&rsquo;instant d&rsquo;afficher une seule ligne (en utilisant <strong>.readline()<\/strong>) et la liste correspondante (avec les m\u00e9thodes <strong>.strip()<\/strong> et <strong>.split()<\/strong>) :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">line1 = Data.readline() \nprint (line1)\ndonnee=line1.strip().split()\nprint (donnee)<\/code><\/pre>\n\n\n\n<p>Le r\u00e9sultat se pr\u00e9sente de la fa\u00e7on suivante :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">b'ST,GS-       16.2 g \\r\\n'\n[b'ST,GS-', b'16.2', b'g']<\/code><\/pre>\n\n\n\n<p>La premi\u00e8re ligne est la cha\u00eene de caract\u00e8res r\u00e9cup\u00e9r\u00e9e, et la deuxi\u00e8me ligne est la liste que nous avons cr\u00e9\u00e9e avec les diff\u00e9rents \u00e9l\u00e9ments de cette cha\u00eene. L&rsquo;information qui nous int\u00e9resse (valeur de la masse) est donc le 2\u00e8me \u00e9l\u00e9ment de la liste &#8230; donc d&rsquo;indice 1 &#8230; et oui rappelez-vous : l&rsquo;indice du  premier \u00e9l\u00e9ment d&rsquo;une liste est <strong>0<\/strong> !<\/p>\n\n\n\n<p><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong><em>Mais que veulent dire tous ces b devant les chaines de caract\u00e8res ?<\/em><\/strong><\/p>\n\n\n\n<p>Ces donn\u00e9es ne sont pas vraiment des cha\u00eenes de caract\u00e8res mais des donn\u00e9es de type<strong> bytes<\/strong> (s\u00e9quences d&rsquo;octet). il faudra donc les d\u00e9coder (avec la m\u00e9thode<strong> .decode()<\/strong>) et \u00e9ventuellement les convertir en <strong>float <\/strong>si on a besoin de faire des calculs.<\/p>\n<\/blockquote>\n\n\n\n<p>Nous pouvons donc demander d&rsquo;afficher une s\u00e9rie de 20 valeurs (et de les stocker dans la liste<strong> liste_masse<\/strong>) de la fa\u00e7on suivante :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\"># Essai pour une succession de 20 lignes de donn\u00e9es\nfor k in range(20) :\n    line1 = Data.readline() \n    print (line1)\n    donnee=line1.strip().split()\n    print (donnee)\n\n    \n\nData.close()   # pour arr\u00eater la lecture des donn\u00e9es s\u00e9rie<\/code><\/pre>\n\n\n\n<p>Il s&rsquo;affiche ceci dans le shell :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">b'\\r\\n'\n[]\nb'\\r\\n'\n[]\nb'ST,GS-       16.2 g \\r\\n'\n[b'ST,GS-', b'16.2', b'g']\nb'\\r\\n'\n[]\nb'\\r\\n'\n[]\nb'ST,GS-       16.2 g \\r\\n'\n[b'ST,GS-', b'16.2', b'g']\nb'\\r\\n'\n[]\nb'\\r\\n'\n[]<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong><em>On s&rsquo;aper\u00e7oit que seule une ligne sur 3 contient des informations !<\/em><\/strong> <\/p>\n\n\n\n<p>Nous allons donc ajouter une condition pour \u00e9liminer les listes vides <\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\"># Essai pour une succession de 20 lignes de donn\u00e9es\nfor k in range(20) :\n    line1 = Data.readline() \n    print (line1)\n    donnee=line1.strip().split()\n    print (donnee)\n\n    if len(donnee) !=0 : # parfois des lignes de donn\u00e9es vides peuvent \u00eatre envoy\u00e9es, il faut les \"\u00e9carter\"\n        distance = float(donnee[1].decode())  # apr\u00e8s consultation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        liste_masse.append(masse)\n        print (\"masse: \", masse, \" mm\")\n\nData.close()   # pour arr\u00eater la lecture des donn\u00e9es s\u00e9rie<\/code><\/pre>\n\n\n\n<p>Quelques lignes de code suppl\u00e9mentaires pour enregistrer ces informations dans un fichier texte de format<strong> .txt<\/strong>. Cela peut \u00eatre utile pour l&rsquo;importation de ces donn\u00e9es dans des logiciels ou tableurs (Latis pro, Regressi, Excel, Libre Office ,&#8230;). Le chemin est d\u00e9fini par d\u00e9faut dans le dossier o\u00f9 se trouve le fichier python mais il est possible de d\u00e9finir d&rsquo;autres chemins:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#Ecriture dans un fichier txt\nlines=['m\\n'] #premi\u00e8re ligne du fichier txt\nfor i in range (len (liste_masse)):\n    line = str(liste_masse[i])+'\\n'\n    lines.append(line)\n\nfichier = open('data_balance.txt', 'w').writelines(lines) #cr\u00e9ation d'un nouveau fichier texte<\/code><\/pre>\n\n\n\n<p><strong>Le code complet pour ce programme de r\u00e9cup\u00e9ration de donn\u00e9es :<\/strong><\/p>\n\n\n\n<pre title=\"R\u00e9cup\u00e9ration de donn\u00e9es s\u00e9rie d'une carte Arduino (mesure de distance avec module ultrason)\" class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#Importation des modules\nimport serial\nimport serial.tools.list_ports   # pour la communication avec le port s\u00e9rie\n\n\n\n#initialisation des listes\nliste_masse = []\n\n\n# Fonction pour la r\u00e9cup\u00e9ration des donn\u00e9es s\u00e9rie venant du port USB\ndef recup_port_usb() :\n    ports = list(serial.tools.list_ports.comports())\n    for p in ports:\n        if 'USB' in p.description :\n            mData = serial.Serial(p.device,9600)\n    print(mData.is_open) # Affiche et v\u00e9rifie que le port est ouvert\n    print(mData.name) # Affiche le nom du port \n    return mData\n\nData =recup_port_usb()\n\n# Essai pour une succession de 20 lignes de donn\u00e9es\nfor k in range(20) :\n    line1 = Data.readline() \n    print (line1)\n    donnee=line1.strip().split()\n\n    if len(donnee) !=0 :\n        masse = float(donnee[1].decode())  # apr\u00e8s consultation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        liste_masse.append(masse)\n        print (\"masse : \", masse, \" g\")\nData.close()\n\n\n\n#Ecriture dans un fichier txt\nlines=['t\\tm\\n'] #premi\u00e8re ligne du fichier txt\nfor i in range (len (liste_masse)):\n    line = str(liste_temps[i]) +'\\t'+ str(liste_masse[i])+'\\n'\n    lines.append(line)\n\nfichier = open('data_balance.txt', 'w')\nfichier.writelines(lines) #cr\u00e9ation d'un nouveau fichier texte<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Astuce  :  parfois un message d&rsquo;erreur appara\u00eet (probl\u00e8me de communication avec la carte, donn\u00e9es re\u00e7ues incompl\u00e8tes &#8230;), comment r\u00e9soudre ce probl\u00e8me ?<\/strong><\/p>\n\n\n\n<p>La plupart du temps, il suffit de red\u00e9marrer le shell (CTRL+K) et relancer ensuite le programme.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Etape 2 : Acquisition temporelle<\/strong><\/h2>\n\n\n\n<p>On peut aussi afficher ces donn\u00e9es en fonction du temps gr\u00e2ce au module <strong>time<\/strong>. <\/p>\n\n\n\n<p>Nous partons donc du m\u00eame code vu ci-dessus avec quelques compl\u00e9ments et modifications.<\/p>\n\n\n\n<p>Tout d&rsquo;abord, penser \u00e0 importer le module <strong>time <\/strong>en d\u00e9but de programme<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import time        # gestion du temps<\/code><\/pre>\n\n\n\n<p>Nous allons cr\u00e9er une liste pour la mesure du temps \u00ab\u00a0brute\u00a0\u00bb. Une autre liste va \u00eatre cr\u00e9\u00e9e pour la mesure du temps avec t=0 pour le d\u00e9but de l&rsquo;acquisition<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">\n#initialisation des listes\nliste_temps_mesure =[] # liste pour stocker le temps\"brut\"\nliste_temps=[] # liste pour stocker les valeurs de temps en partant de t=0\nliste_masse = []<\/code><\/pre>\n\n\n\n<p>On d\u00e9finit un temps d&rsquo;acquisition :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">t_acquisition = 5.0<\/code><\/pre>\n\n\n\n<p>On modifie la boucle pour qu&rsquo;elle s&rsquo;arr\u00eate \u00e0 la fin du temps d&rsquo;acquisition :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">Data =recup_port_usb()\n\n# Essai pour une succession de 20 lignes de donn\u00e9es\ntempsreel=0\nwhile tempsreel &lt;= t_acquisition:\n    line1 = Data.readline()\n    print (line1)\n    #on retire les caract\u00e8res d'espacement en d\u00e9but et fin de cha\u00eene\n    listeDonnees = line1.strip()\n    # on s\u00e9pare les informations re\u00e7ues s\u00e9par\u00e9es par les espaces et on stocke ces informations dans une liste pour chacune de lignes\n    listeDonnees = line1.split()\n    print (listeDonnees)\n\n    if len(listeDonnees)!= 0: # permet de nettoyer le flux de donn\u00e9es car seule une liste sur 3 contient des informations\n        masse = float(listeDonnees[1].decode()) # apr\u00e8s consultation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        tempsmes = time.time()\n        liste_temps_mesure.append(tempsmes) # temps mesur\u00e9 \"brut\" stock\u00e9 dans une liste\n        tempsreel = tempsmes - liste_temps_mesure[0] # pour faire partir le temps de 0 (cette valeur de temps sera stock\u00e9e dans une autre liste : liste_temps)\n\n        liste_masse.append(masse)\n        print(\"m = %f\"%(masse), \" g\") # affichage de la valeur de la masse\n        liste_temps.append(tempsreel)\n        print(\"temps mesur\u00e9 = %f\"%(tempsmes), \" s\") # affichage de la valeur du temps absolu\n        print(\"temps r\u00e9el= %f\"%(tempsreel), \" s\") # affichage de la valeur du temps en partant de 0\n\nData.close()<\/code><\/pre>\n\n\n\n<p><strong>Le code complet pour ce programme d&rsquo;acquisition temporelle :<\/strong><\/p>\n\n\n\n<pre title=\"Acquisition temporellede donn\u00e9es s\u00e9rie d'une carte Arduino (mesure de distance avec module ultrason)\" class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import serial\nimport serial.tools.list_ports   # pour la communication avec le port s\u00e9rie\nimport time # gestion du temps\n\n\n#initialisation des listes\nliste_temps_mesure =[] # liste pour stocker le temps\"brut\"\nliste_temps=[] # liste pour stocker les valeurs de temps en partant de t=0\nliste_masse = []\n\nt_acquisition = 5.0\n\n\n# Fonction pour la r\u00e9cup\u00e9ration des donn\u00e9es s\u00e9rie venant du port USB\ndef recup_port_usb() :\n    ports = list(serial.tools.list_ports.comports())\n    for p in ports:\n        if 'USB' in p.description :\n            mData = serial.Serial(p.device,9600)\n    print(mData.is_open) # Affiche et v\u00e9rifie que le port est ouvert\n    print(mData.name) # Affiche le nom du port\n    return mData\n\nData =recup_port_usb()\n\n# Essai pour une succession de 20 lignes de donn\u00e9es\ntempsreel=0\nwhile tempsreel &lt;= t_acquisition:\n    line1 = Data.readline()\n    print (line1)\n    #on retire les caract\u00e8res d'espacement en d\u00e9but et fin de cha\u00eene\n    listeDonnees = line1.strip()\n    # on s\u00e9pare les informations re\u00e7ues s\u00e9par\u00e9es par les espaces et on stocke ces informations dans une liste pour chacune de lignes\n    listeDonnees = line1.split()\n    print (listeDonnees)\n\n    if len(listeDonnees)!= 0: # permet de nettoyer le flux de donn\u00e9es car seule une liste sur 3 contient des informations\n        masse = float(listeDonnees[1].decode()) # apr\u00e8s consultation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        tempsmes = time.time()\n        liste_temps_mesure.append(tempsmes) # temps mesur\u00e9 \"brut\" stock\u00e9 dans une liste\n        tempsreel = tempsmes - liste_temps_mesure[0] # pour faire partir le temps de 0 (cette valeur de temps sera stock\u00e9e dans une autre liste : liste_temps)\n\n        liste_masse.append(masse)\n        print(\"m = %f\"%(masse), \" g\") # affichage de la valeur de la masse\n        liste_temps.append(tempsreel)\n        print(\"temps mesur\u00e9 = %f\"%(tempsmes), \" s\") # affichage de la valeur du temps absolu\n        print(\"temps r\u00e9el= %f\"%(tempsreel), \" s\") # affichage de la valeur du temps en partant de 0\n\nData.close()\n\n#Ecriture dans un fichier txt\nlines=['t\\tm\\n'] #premi\u00e8re ligne du fichier txt\nfor i in range (len (liste_masse)):\n    line = str(liste_temps[i]) +'\\t'+ str(liste_masse[i])+'\\n'\n    lines.append(line)\n\nfichier = open('data_balance.txt', 'w').writelines(lines) #cr\u00e9ation d'un nouveau fichier texte<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Etape 3 : trac\u00e9 de graphe (statique ou dynamique)<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Graphe statique (qui sera affich\u00e9 en fin d&rsquo;acquisition)<\/h3>\n\n\n\n<p>Pour tracer un graphe, il faut au pr\u00e9alable importer la biblioth\u00e8que matplotlib de la mani\u00e8re suivante :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import matplotlib.pyplot as plt  # pour le trac\u00e9 de graphe<\/code><\/pre>\n\n\n\n<p>Il suffit de taper ces quelques lignes de code pour afficher le graphe avec les valeurs stock\u00e9es dans les listes :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">\nplt.title('m=f(t)') # titre du graphique\nplt.plot(liste_temps,liste_masse, color ='r', marker = 'o') # On affiche les points de coordonn\u00e9es (I,U) avec des points rouges\nplt.xlim (min(liste_temps),max(liste_temps))  #limtes pour les axes avec les valeurs extr\u00eames de I et de U\nplt.ylim(min(liste_masse),max(liste_masse))\nplt.show()<\/code><\/pre>\n\n\n\n<p><strong>Le code complet pour le trac\u00e9 de graphe statique :<\/strong><\/p>\n\n\n\n<pre title=\"Trac\u00e9 de graphe statique (acquisition temporelle de mesures de distances avec une carte Arduino)\" class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#importation des modules\nimport serial\nimport serial.tools.list_ports # pour la communication avec le port s\u00e9rie\nimport matplotlib.pyplot as plt  # pour le trac\u00e9 de graphe\nimport time # gestion du temps\n\n\n\n#initialisation des listes\nliste_temps_mesure =[] # liste pour stocker le temps\"brut\"\nliste_temps=[] # liste pour stocker les valeurs de temps en partant de t=0\nliste_masse = []\n\nt_acquisition = 5.0\n\n\n# Fonction pour la r\u00e9cup\u00e9ration des donn\u00e9es s\u00e9rie venant du port USB\ndef recup_port_usb() :\n    ports = list(serial.tools.list_ports.comports())\n    for p in ports:\n        if 'USB' in p.description :\n            mData = serial.Serial(p.device,9600)\n    print(mData.is_open) # Affiche et v\u00e9rifie que le port est ouvert\n    print(mData.name) # Affiche le nom du port \n    return mData\n\nData =recup_port_usb()\n\n# Essai pour une succession de 20 lignes de donn\u00e9es\ntempsreel=0\nwhile tempsreel &lt;= t_acquisition:\n    line1 = Data.readline()\n    print (line1)\n    #on retire les caract\u00e8res d'espacement en d\u00e9but et fin de cha\u00eene\n    listeDonnees = line1.strip()\n    # on s\u00e9pare les informations re\u00e7ues s\u00e9par\u00e9es par les espaces et on stocke ces informations dans une liste pour chacune de lignes\n    listeDonnees = line1.split()\n    print (listeDonnees)\n\n    if len(listeDonnees)!= 0: # permet de nettoyer le flux de donn\u00e9es car seule une liste sur 3 contient des informations\n        masse = float(listeDonnees[1].decode()) # apr\u00e8s consultation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        tempsmes = time.time()\n        liste_temps_mesure.append(tempsmes) # temps mesur\u00e9 \"brut\" stock\u00e9 dans une liste\n        tempsreel = tempsmes - liste_temps_mesure[0] # pour faire partir le temps de 0 (cette valeur de temps sera stock\u00e9e dans une autre liste : liste_temps)\n\n        liste_masse.append(masse)\n        print(\"m = %f\"%(masse), \" g\") # affichage de la valeur de la masse\n        liste_temps.append(tempsreel)\n        print(\"temps mesur\u00e9 = %f\"%(tempsmes), \" s\") # affichage de la valeur du temps absolu\n        print(\"temps r\u00e9el= %f\"%(tempsreel), \" s\") # affichage de la valeur du temps en partant de 0\n\nData.close()\n\nplt.title('m=f(t)') # titre du graphique\nplt.plot(liste_temps,liste_masse, color ='r', marker = 'o') # On affiche les points de coordonn\u00e9es (I,U) avec des points rouges\nplt.xlim (min(liste_temps),max(liste_temps))  #limtes pour les axes avec les valeurs extr\u00eames de I et de U\nplt.ylim(min(liste_masse),max(liste_masse))\nplt.xlabel('temps en s')\nplt.ylabel('masse en g')\nplt.show()<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/labopothier.com\/wp-content\/uploads\/2021\/02\/Sans-titre-6.png\" alt=\"\" class=\"wp-image-679\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Trac\u00e9 de graphe en temps r\u00e9el (avec la fonction animate)<\/h3>\n\n\n\n<p>Pour tracer un graphe \u00ab\u00a0anim\u00e9\u00a0\u00bb en temps r\u00e9el, il faut importer les modules suivants :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import matplotlib.pyplot as plt  # pour le trac\u00e9 de graphe\nfrom matplotlib import animation # pour la figure anim\u00e9e<\/code><\/pre>\n\n\n\n<p>On d\u00e9finit un temps d&rsquo;acquisition et une distance maximale pour l&rsquo;\u00e9chelle du graphe :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">t_acquisition = 5.0\nMassemax= 200 #en g<\/code><\/pre>\n\n\n\n<p>Nous allons inclure les instructions de la boucle dans une fonction nomm\u00e9e<strong> animate(i)<\/strong> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#pour le graphe en temps r\u00e9el\ndef animate(i):\n    line1 = Data.readline()\n    print (line1)\n    # on retire les caract\u00e8res d'espacement en d\u00e9but et fin de cha\u00eene\n    listeDonnees = line1.strip()\n    # on s\u00e9pare les informations re\u00e7ues s\u00e9par\u00e9es par les espaces et on stocke ces informations dans une liste pour chacune de lignes\n    listeDonnees = line1.split()\n    print (listeDonnees)\n\n\n    if len(listeDonnees)!= 0 : # permet de nettoyer le flux de donn\u00e9es car seule une liste sur 3 contient des informations\n        masse = float(listeDonnees[1].decode()) # apr\u00e8s consultation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        tempsmes = time.time()\n        liste_temps_mesure.append(tempsmes) # temps mesur\u00e9 \"brut\" stock\u00e9 dans une liste\n        tempsreel = tempsmes - liste_temps_mesure[0] # pour faire partir le temps de 0 (cette valeur de temps sera stock\u00e9e dans une autre liste : liste_temps)\n\n        while tempsreel &lt;= t_acquisition:\n            liste_masse.append(masse)\n            print(\"m = %f\"%(masse), \" g\") # affichage de la valeur de la masse\n            liste_temps.append(tempsreel)\n            print(\"temps mesur\u00e9 = %f\"%(tempsmes), \" s\") # affichage de la valeur du temps absolu\n            print(\"temps r\u00e9el= %f\"%(tempsreel), \" s\") # affichage de la valeur du temps en partant de 0\n            line.set_data(liste_temps,liste_masse)\n            return line,\n\n\n\n\n<\/code><\/pre>\n\n\n\n<p>Puis on r\u00e9cup\u00e8re les donn\u00e9es et on fait afficher la figure anim\u00e9e avec <strong>animation.FuncAnimation<\/strong> :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">\n# Fonction pour la r\u00e9cup\u00e9ration des donn\u00e9es s\u00e9rie venant du port USB\ndef recup_port_USB() :\n    ports = list(serial.tools.list_ports.comports())\n    for p in ports:\n        print (p)\n        if 'USB' in p.description :\n            mData = serial.Serial(p.device,9600)\n    print(mData.is_open) # Affiche et v\u00e9rifie que le port est ouvert\n    print(mData.name) # Affiche le nom du port \n    return mData\n\n\n\n\n\n\nData =recup_port_USB() #r\u00e9cup\u00e9ration des donn\u00e9es\n\n# Cr\u00e9ation figure\nfig=plt.figure()\nline, = plt.plot([],[])\nplt.xlim(0, t_acquisition)\nplt.ylim(0,Massemax)\nplt.grid()\n\n\n#Animation\nani = animation.FuncAnimation(fig, animate, frames=200,  interval=20,repeat=False)\n\nplt.show()\nData.close() # pour arr\u00eater la lecture des donn\u00e9es s\u00e9rie<\/code><\/pre>\n\n\n\n<p><strong>Le code complet pour le trac\u00e9 de graphe  en temps r\u00e9el :<\/strong><\/p>\n\n\n\n<pre title=\"Trac\u00e9 de graphe en temps r\u00e9el (acquisition temporelle de mesures de distances avec une carte Arduino)\" class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#importation des modules\nimport serial\nimport serial.tools.list_ports # pour la communication avec le port s\u00e9rie\nimport matplotlib.pyplot as plt  # pour le trac\u00e9 de graphe\nfrom matplotlib import animation # pour la figure anim\u00e9e\nimport time # gestion du temps\n\n#initialisation des listes\n\nliste_temps_mesure =[] # liste pour stocker le temps\"brut\"\nliste_temps=[] # liste pour stocker les valeurs de temps en partant de t=0\nliste_masse = [] # liste pour stocker les valeurs de masse\n\nt_acquisition = 5.0\nMassemax= 200\n\n\n#pour le graphe en temps r\u00e9el\ndef animate(i):\n    line1 = Data.readline()\n    print (line1)\n    # on retire les caract\u00e8res d'espacement en d\u00e9but et fin de cha\u00eene\n    listeDonnees = line1.strip()\n    # on s\u00e9pare les informations re\u00e7ues s\u00e9par\u00e9es par les espaces et on stocke ces informations dans une liste pour chacune de lignes\n    listeDonnees = line1.split()\n    print (listeDonnees)\n\n\n    if len(listeDonnees)!= 0 : # permet de nettoyer le flux de donn\u00e9es car seule une liste sur 3 contient des informations\n        masse = float(listeDonnees[1].decode()) # apr\u00e8s consulation des donn\u00e9es, nous choisissons le 2\u00e8me \u00e9l\u00e9ment de listeDonnees\n        tempsmes = time.time()\n        liste_temps_mesure.append(tempsmes) # temps mesur\u00e9 \"brut\" stock\u00e9 dans une liste\n        tempsreel = tempsmes - liste_temps_mesure[0] # pour faire partir le temps de 0 (cette valeur de temps sera stock\u00e9e dans une autre liste : liste_temps)\n\n        while tempsreel &lt;= t_acquisition:\n            liste_masse.append(masse)\n            print(\"m = %f\"%(masse), \" g\") # affichage de la valeur de la masse\n            liste_temps.append(tempsreel)\n            print(\"temps mesur\u00e9 = %f\"%(tempsmes), \" s\") # affichage de la valeur du temps absolu\n            print(\"temps r\u00e9el= %f\"%(tempsreel), \" s\") # affichage de la valeur du temps en partant de 0\n            line.set_data(liste_temps,liste_masse)\n            return line,\n\n\n\n\n\n\n# Fonction pour la r\u00e9cup\u00e9ration des donn\u00e9es s\u00e9rie venant du port USB\ndef recup_port_USB() :\n    ports = list(serial.tools.list_ports.comports())\n    for p in ports:\n        print (p)\n        if 'USB' in p.description :\n            mData = serial.Serial(p.device,9600)\n    print(mData.is_open) # Affiche et v\u00e9rifie que le port est ouvert\n    print(mData.name) # Affiche le nom du port \n    return mData\n\n\n\n\n\n\nData =recup_port_USB() #r\u00e9cup\u00e9ration des donn\u00e9es\n\n# Cr\u00e9ation figure\nfig=plt.figure()\nline, = plt.plot([],[])\nplt.xlim(0, t_acquisition)\nplt.ylim(0,Massemax)\nplt.grid()\n\n\n#Animation\nani = animation.FuncAnimation(fig, animate, frames=200,  interval=20,repeat=False)\n\nplt.show()\nData.close()\nplt.close(fig)\n\n#Ecriture dans un fichier txt\nlines=['t\\tm\\n'] #premi\u00e8re ligne du fichier txt\nfor i in range (len (liste_masse)):\n    line = str(liste_temps[i]) +'\\t'+ str(liste_masse[i])+'\\n'\n    lines.append(line)\n\nfichier = open('data_balance.txt', 'w').writelines(lines) #cr\u00e9ation d'un nouveau fichier texte\n\n<\/code><\/pre>\n\n\n\n<p>Ex\u00e9cution du programme dans cette vid\u00e9o :<\/p>\n\n\n\n<figure class=\"wp-block-video aligncenter\"><video controls src=\"https:\/\/labopothier.com\/wp-content\/uploads\/2021\/02\/capture-balance-Youtube-HD.mov\"><\/video><\/figure>\n\n\n\n<p>Script Python disponible sur ce lien : <a href=\"https:\/\/github.com\/jonasforlot\/python-arduino\/blob\/main\/Donn%C3%A9es%20s%C3%A9rie%20balance\/recup_donnees_balance.py\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/jonasforlot\/python-arduino\/blob\/main\/Donn%C3%A9es%20s%C3%A9rie%20balance\/recup_donnees_balance.py<\/a><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Un grand merci \u00e0 Lionel Grillet, professeur de SI, pour son aide pr\u00e9cieuse gr\u00e2ce \u00e0 ses connaissances pointues en langage Python !<\/p>\n<\/blockquote>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Objectif de cette activit\u00e9 : R\u00e9cup\u00e9rer dans Python les donn\u00e9es d&rsquo;une balance \u00ab\u00a0interfa\u00e7able\u00a0\u00bb ou d&rsquo;un autre type d&rsquo;appareil avec connexion USB ou s\u00e9rie. Pr\u00e9-requis : \u00eatre familier avec le langage Python Pour l&rsquo;initiation au langage Python , je vous invite \u00e0 consulter cet article : Initiation au langage Python Nous avons au laboratoire une balance [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":739,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"default","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[7,8],"tags":[],"class_list":["post-674","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microcontroleurs-et-python","category-python"],"_links":{"self":[{"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/posts\/674","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/comments?post=674"}],"version-history":[{"count":23,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/posts\/674\/revisions"}],"predecessor-version":[{"id":1432,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/posts\/674\/revisions\/1432"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/media\/739"}],"wp:attachment":[{"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/media?parent=674"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/categories?post=674"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/labopothier.com\/index.php\/wp-json\/wp\/v2\/tags?post=674"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}