Transformer un Raspberry Pi en multimètre réseau

Transformer un Raspberry Pi en multimètre réseau

Par , dans Mesures, le .

Les appareils de mesure qui peuvent être connectés directement sur le réseau sont en général très chers, plus de 1000 EUR. Pourtant, de nombreuses applications pourraient en profiter s'ils étaient plus abordables, comme par exemple le suivi d'une expérience commencée sur un coin de table. Nous allons donc vous montrer comment transformer très simplement un Raspberry Pi en un multi-mètre Ethernet très flexible, à l'aide d'un simple script Python. Une solution simple à base de modules USB standards, vidéo à l'appui.


Pour faire notre multi-mètre Ethernet, nous allons utiliser
- un Raspberry Pi modèle B, pour la connexion Ethernet (28 EUR)
- un écran OLED Yocto-Display, pour un affichage très lisible (70 EUR)
- une RaspBox, pour l'habillage (12 EUR)
- des capteurs Yoctopuce, par ex. un Yocto-Thermocouple (37 EUR) ou un Yocto-Volt (48 EUR)
- un petit script Python tournant sur le Raspberry Pi pour le contrôle de l'écran (gratuit)
- le logiciel VirtualHub (téléchargeable sur notre site) pour l'accès distant aux mesures (gratuit)
Le prix final dépendra des capteurs que vous utilisez, mais restera très avantageux par rapport à une solution commerciale (dans l'exemple ci-dessus, deux entrées thermocouple plus une mesure de tension avec isolation revient à moins de 200 EUR).

L'assemblage

Rien de compliqué pour cette réalisation puisqu'on utilise que des périphériques USB standards. En faisant 4 petits trous sur la plaque supérieure de la RaspBox, on fixe le Yocto-Display dessous afin qu'il soit protégé. L'écran est raccordé par un câble USB via un connecteur 1.27mm, moins encombrant qu'une fiche micro-B, qui s'adapte à tous nos modules et que nous aurons en vente sur notre shop d'ici quelques jours.

Voilà ce qu'on va réaliser
Voilà ce qu'on va réaliser



L'installation

Prenez une image Linux pour Raspberry Pi standard, et vérifiez bien que votre Raspberry Pi est à jour en exécutant "sudo raspi-config" et en sélectionnant "update". Le bug USB du Raspberry Pi n'a toujours pas été complètement fixé, il faut donc s'assurer que votre fichier /boot/cmdline.txt contienne bien l'option dwc_otg.speed=1 et redémarrer.

Téléchargez et installez ensuite le VirtualHub de Yoctopuce, qui fournira automatiquement un accès réseau à vos capteurs, pour pouvoir les interroger à distance depuis votre station de travail, et installez la librairie Yoctopuce pour Python yoctopuce via PyPi. C'est tout, il ne reste plus qu'à écrire les quelques lignes de Python pour piloter le tout.

Le code

Pour être le plus pratique possible, le code va détecter à tout moment les modules connectés afin de s'adapter automatiquement à la sonde connectée. Pour ce faire, nous allons partir de l'exemple de programmation par événement fourni dans la librairie Yoctopuce, et le généraliser un peu pour tenir à jour un dictionnaire de sondes disponibles pour l'affichage.


# List of sensors to display (discovered by Plug-and-play)
sensors = { }
currentSensor = ""

# add sensor to dictionary when plugged
def deviceArrival(m):
    global sensors, currentSensor
    for i in range(m.functionCount()):
        fctName = m.functionId(i)                     # eg. "voltage1"
        fctType = re.sub("\d+$", "", fctName)         # eg. "voltage"
        hwId = m.get_serialNumber() + "." + fctName
        yocto_mod = getattr(yoctopuce, "yocto_"+fctType.lower(), None)
        if(yocto_mod is not None):
            className = fctType[0].upper()+fctType[1:]# eg. "Voltage"
            YClass = getattr(yocto_mod, "Y"+className)# eg. YVoltage
            yFind = getattr(YClass, "Find"+className) # eg. YVoltage.FindVoltage
            fct = yFind(hwId)
            if getattr(fct, "get_unit", None) is not None:
                currentSensor = fct.get_hardwareId()
                sensors[currentSensor] = \
                    { "name" : fct.get_friendlyName(),
                      "val"  : fct.get_unit() }
                fct.registerValueCallback(sensorChanged)
    refreshDisplay()

# update display when sensor changes
def sensorChanged(fct,value):
    hwId = fct.get_hardwareId()
    if hwId in sensors: sensors[hwId]['val'] = value+" "+fct.get_unit()
    refreshDisplay()

# remove sensor from dictionary when unplugged
def deviceRemoval(m):
    deletePattern = m.get_serialNumber()+"\..*"
    deleteList = []
    for key in sensors:
        if re.match(deletePattern, key): deleteList.append(key)
    for key in deleteList:
        del sensors[key]
    refreshDisplay()
 


Le code d'affichage ne prend que quelques lignes. Comme il peut y avoir plusieurs senseurs, on garde le nom de la fonction actuellement affichée dans une variable.


# Get the display object
display = YDisplay.FirstDisplay()
if display is None:
    sys.exit("Display not connected")
display.resetAll()
dispLayer = display.get_displayLayer(1)
dispLayer.hide()

# Update the display value if needed (with double-buffering)
def refreshDisplay():
    global currentSensor
    if currentSensor not in sensors:
        currentSensor = sensors.keys()[-1]
    sensor = sensors[currentSensor]
    dispLayer.clear()
    dispLayer.selectFont("Small.yfm")
    dispLayer.drawText(0,0,YDisplayLayer.ALIGN.TOP_LEFT,sensor["name"])
    dispLayer.selectFont("Medium.yfm")
    dispLayer.drawText(127,28,YDisplayLayer.ALIGN.BOTTOM_RIGHT,sensor["val"])
    display.copyLayerContent(1,2)
 


Pour changer la fonction affichée, on utilise simplement les entrées bouton disponibles sur l'écran. Il n'est même pas indispensable d'y mettre un vrai bouton poussoir en l'occurrence: comme il s'agit d'entrées analogiques avec calibration, il suffira d'effleurer les contacts avec les doigts pour activer les entrées, selon le même principe que le Makey-Makey.


# Get the buttons objects, get an event when "pressed"
serial = display.get_module().get_serialNumber()
prevButton = YAnButton(serial+".anButton1")
nextButton = YAnButton(serial+".anButton6")
prevButton.set_userData(False)   # False = released
nextButton.set_userData(False)   # False = released
prevButton.registerValueCallback(buttonPressed);
nextButton.registerValueCallback(buttonPressed);

# Callback whenever a button value changes
def buttonPressed(fct,value):
    global currentSensor
    if(int(value) > 500):    # button is released
        fct.set_userData(False)
        return
    if(fct.get_userData()): # button was already pressed
        return
    # Button was just pressed, cycle through sensors values
    fct.set_userData(True)
    delta = (1 if fct.get_hardwareId()[-1] == '1' else -1)
    if(delta != 0):
        keys = sensors.keys()
        idx = len(keys)-1
        for i in range(len(keys)):
            if keys[i] == currentSensor:
                idx = (i+delta+len(keys)) % len(keys)
        currentSensor = keys[idx]
        refreshDisplay()
 


Pour le confort d'utilisation, on ajoute une fonction affichable supplémentaire: l'adresse IP du Raspberry Pi. Ça facilite grandement la vie pour ces machines sans écran...


# Put the Raspberry Pi itself as default sensor, to show IP address
sensors[""] = { "name" : socket.gethostname(),
                "val"  : findMyIP() }
refreshDisplay()
 


Voilà pour l'affichage en direct, vous avez maintenant un multi-mètre Ethernet. Comme nous avons mis le VirtualHub, les capteurs peuvent être interrogés à travers le réseau par la même API Yoctopuce, et ce depuis (presque) n'importe quel langage de programmation.

Et, cerise sur le gâteau, vous pouvez en quelques clicks configurer le VirtualHub pour poster automatiquement sur Cosm les valeurs mesurées. Ainsi vous pourrez suivre vos expériences sur votre Smartphone sans même écrire une ligne de code...

Les données peuvent être collectées automatiquement sur Cosm
Les données peuvent être collectées automatiquement sur Cosm



Le résultat

  

Commenter aucun commentaire
Retour au blog












Catégories
Banc d'essai
Bricolages
Divers
Electronique
Mesures
Nouveautés
Objets Connectés
Programmation
Toutes
Yoctopuce, trucs USB.