Real time plotting with arduino and Python.

Réalisation d'un graphique dynamique donnant les valeurs mesurées par un microcontroleur Arduino Uno sur un ordinateur pc ou mac (10.6 ici) en fonction du temps.

Ce type de graphique s'apparente aux plotteurs (real time plotting). Cela ressemble également à ce que l'on peut visualiser sur un oscilloscope.

Illustration vidéo : https://www.youtube.com/watch?v=pgBq1D94wL4

But

Pouvoir analyser et visualiser des mesures analogique ou digitale en temps réelle. Exemple: la mesure de la tension d'une pile permet de savoir où en est la réserve d'énergie disponible à tout moment. Dans un premier temps nous allons réaliser un programme de base qui va nous permetre de comprendre le fonctionnement de l'ensemble. Les applications pouront ensuite être personnalisées. Nous allons mesurer les tensions qu'il y a sur les bornes A0 et A1. Vous allez me dire qu'il n'y a rien de brancher dessus donc qu'est ce qu'on va pouvoir mesurer? Nous mesurons simplement le potentiel présent au borne A0 et A1 comme une antenne. Le potentiel varie généralement en modifiant la position de l'arduino ou en mettant sa main près des bornes et cette tension s'annule en touchant la terre ou ce qui fait office de prise équipotentiel ( radiateur, tuyau d'eau métalique, poutre métalique…). Nous allons pouvoir visualiser sur le graphe ce qui fait varier cette tension. Ce programme exige quelques notions de base de programmation en C et en python. Cela reste fort accessible.

Le matériel et logiciel utilisé

  1. Arduino Uno
  2. Logiciel : Arduino 1.0.6
  3. Macbookpro (ou autre)
  4. Logiciel : Python3
  5. Câblage : pas de cablage nécessaire sur l'arduino simplement brancher l'arduino à l'ordinateur par la fiche USB

Mode opératoire

  1. Brancher le tout,
  2. Allumer l'ordinateur,
  3. Dans le logiciel arduino, vérifier l'adresse du port série de l'arduino

Le programme Arduino

electronut.ino
// analog-plot
// Read analog values from A0 and A1 and print them to serial port.
// electronut.ino
#include "Arduino.h"
void setup()
{
    // initialize serial comms
    Serial.begin(9600); 
}
void loop()
{
    // read A0
    int val1 = analogRead(0);
    // read A1
    int val2 = analogRead(1);
    // print to serial
    Serial.print(val1);
    Serial.print(" ");
    Serial.print(val2);
    Serial.print("\n");
    // wait 
    delay(50);
}
  1. Dans le programme vérifier la vitesse de communication du port série (d'habitude, 9600 Bauds/s mais on peut aller jusqu'à 115 000 bauds/s)
  2. Lancer en Téléversant le programme arduino ci-après au microcontroleur Arduino Uno
  3. Vérifier que les 2 valeurs varient bien sur le port série en appyant sur < moniteur série> (icone loupe ou Zoom dans le coin supérieur droit). Il faut parfois attendre quelques secondes ou appuyer plusieurs fois
  4. Fermer l'écran moniteur série sinon il rentre en confit avec le programme python et l'acquisition de données est perturbée
  5. Lancer le Terminal de l'ordinateur
  6. A l'aide de l'option cd allez là où est installer le programme python ci-dessous
ldr.py
"""
ldr.py
Display analog data from Arduino using Python (matplotlib)
Author: Mahesh Venkitachalam
Website: electronut.in
"""

import sys, serial, argparse
import numpy as np
from time import sleep
from collections import deque

import matplotlib.pyplot as plt 
import matplotlib.animation as animation
    
# Plot class
class AnalogPlot:
  # Constructor
  def __init__(self, strPort, maxLen):
      # open serial port
      self.ser = serial.Serial(strPort, 9600)

      self.ax = deque([0.0]*maxLen)
      self.ay = deque([0.0]*maxLen)
      self.maxLen = maxLen

  # Add to buffer
  def addToBuf(self, buf, val):
      if len(buf) < self.maxLen:
          buf.append(val)
      else:
          buf.pop()
          buf.appendleft(val)

  # Add data
  def add(self, data):
      assert(len(data) == 2)
      self.addToBuf(self.ax, data[0])
      self.addToBuf(self.ay, data[1])

  # Update plot
  def update(self, frameNum, a0, a1):
      try:
          line = self.ser.readline()
          data = [float(val) for val in line.split()]
          # print data
          if(len(data) == 2):
              self.add(data)
              a0.set_data(range(self.maxLen), self.ax)
              a1.set_data(range(self.maxLen), self.ay)
      except KeyboardInterrupt:
          print('exiting')
      
      return a0, 

  # Clean up
  def close(self):
      # Close serial
      self.ser.flush()
      self.ser.close()    

# main() function
def main():
  # Create parser
  parser = argparse.ArgumentParser(description="LDR serial")
  # Add expected arguments
  parser.add_argument('--port', dest='port', required=True)

  # Parse args
  args = parser.parse_args()
  
  #strPort = '/dev/tty.usbserial-A7006Yqh'
  strPort = args.port

  print('reading from serial port %s...' % strPort)

  # Plot parameters
  analogPlot = AnalogPlot(strPort, 1000)

  print('plotting data...')

  # Set up animation
  fig = plt.figure()
  ax = plt.axes(xlim=(0, 1000), ylim=(0, 10230))
  a0, = ax.plot([], [])
  a1, = ax.plot([], [])
  anim = animation.FuncAnimation(fig, analogPlot.update, 
                                 fargs=(a0, a1), 
                                 interval=50)

  # Show plot
  plt.show()
  
  # Clean up
  analogPlot.close()

  print('exiting.')
  

# Call main
if __name__ == '__main__':
  main()
  1. Lancer le programme python en ligne de commande dans le terminal en spéciciant l'adresse du port série (voir 3) après les lignes –port / voir exemple :
  2. Attendre quelques secondes et la fenêtre s'ouvre avec le graphique qui s'actualise au fur et à mesure que les données arrivent.
  3. Fermer la fenêtre pour arrêter le programme.

À améliorer :

  1. Enregistrement de toutes les données
  2. Outil d'analyse des données
  3. Création de plusieurs graphiques sur le même écran
  4. Utilisation d'échelles différentes sur le même graphique