Guider un projecteur par des télémètres

Guider un projecteur par des télémètres

Il y a un mois, on vous a présenté dans ce blog successivement deux produits dont les tests s'étaient avérés assez réussis: un petit télémètre qui fonctionnait sur plus de 10m, et un petit projecteur motorisé commandé en DMX512. On s'est dit qu'il y avait moyen de faire un petit projet amusant en les combinant, et il n'y a rien d'un tel que ce genre d'essais pour voir si un produit tient ses promesses...



L'idée est toute simple: arrive-t-on facilement à faire un petit programme qui pilote le projecteur pour suivre quelqu'un qui se déplace dans un couloir ? Et question subsidiaire, est-ce que cela marche toujours si l'on met deux capteurs à peu de distance, pour surveiller deux couloirs à la fois, ou est-ce que les capteurs vont interférer l'un avec l'autre ?

Schéma de situation

Pour commencer, voici un petit schéma qui illustre la situation. En mettant deux télémètre au mur à la fin du couloir, on peut facilement mesurer la position d'une personne qui se déplace.


Vue d'avion     Vue de face
Schémas de situation, vue d'avion et vue de face


Avec un peu de trigonométrie, on peut trouver les deux angles (rotation et inclinaison) selon lesquels il faut orienter le projecteur motorisé pour viser la personne.

Matériel

Ce projet requiert un projecteur motorisé DMX512, un Yocto-RS485-V2 pour communiquer avec ce projecteur, deux télémètres, et les interfaces Yoctopuce correspondantes. Puisque lors de notre précédent test de ces télémètres nous avions testé les deux interfaces série et I2C, nous avons décidé de continuer à les tester toutes deux. Nous avons donc utilisé un Yocto-Serial pour un couloir et un Yocto-I2C pour l'autre.

Ces trois modules d'interface sont raccordés à un YoctoHub-Ethernet, qui nous permet de piloter le tout à distance depuis un serveur central.

Matériel utilisé pour le projet
Matériel utilisé pour le projet



Logiciel

Pour ne pas compliquer cet exemple, nous avons implémenté la partie logicielle en Python.

Le code commence par se connecter au YoctoHub-Ethernet et instancier des objets pour communiquer avec les deux télémètres et l'interface de communication DMX512:

# Setup the API to use devices on remote YoctoHub-Ethernet
errmsg = YRefParam()
if YAPI.RegisterHub("192.168.1.100", errmsg) != YAPI.SUCCESS:
    sys.exit("RegisterHub error: " + errmsg.value)

# locate Yoctopuce devices
dist1 = YSensor.FindSensor("dist1")
if not dist1.isOnline():
    sys.exit("RangeFinder #1 not found")
dist2 = YSensor.FindSensor("dist2")
if not dist2.isOnline():
    sys.exit("RangeFinder #2 not found")
dmxPortOut = YSerialPort.FindSerialPort("DMX-OUT.serialPort")
if not dmxPortOut.isOnline():
    sys.exit("No Yocto-RS485-V2 with logical name DMX-OUT found")


La lecture des télémètres est faite en utilisant les callback de changement de valeur: nous avons fait une classe DetectionLane qui enregistre la position de la dernière détection annoncée par un télémètre. On en crée une instance pour chaque couloir. Une deuxième classe PanTiltHeadnous servira à faire les calculs calculs de géométrie et envoyer les messages DMX512 pour piloter la tête.

# lane 1 is 0.9m from head, length = 13m30
lane1 = DetectionLane(dist1, 900, 13300)
# lane 2 is 0.8m from head, length = 12m50
lane2 = DetectionLane(dist2, -800, 12500)
# pan tilt head is 2m70 above ground, 7m from sensors
panTiltHead = PanTiltHead(dmxPortOut, 2700, 7000)


La boucle de code principal n'a donc qu'à attendre des mesures des télémètres, et périodiquement diriger le projecteur vers le couloir sur lequel le dernier événement a été détecté:

while True:
    # Wait for 20ms before receiving rangefinder measures
    YAPI.Sleep(20, errmsg)
    # Send a DMX message (~50 Hz)
    if lane2.event is None:
        if lane1.event is None:
            panTiltHead.pointTo(None, None)
        else:
            panTiltHead.pointTo(lane1, 0)
    else:
        if lane1.event is None or abs(lane1.speed) < abs(lane2.speed):
            panTiltHead.pointTo(lane2, 0)
        else:
            panTiltHead.pointTo(lane1, 0)


Et voilà le résultat:

Pilotage automatique d'un projecteur par télémètre: ça marche!
Pilotage automatique d'un projecteur par télémètre: ça marche!


Si vous êtes intéressés à voir les calculs trigonométriques ou l'implémentation des classes DetectionLane et PanTiltHead, vous pouvez aller voir le code détaillé sur GitHub.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.