Chronométrage, RFID et voiture radio commandée

Chronométrage, RFID et voiture radio commandée

En plus de permettre de lire et d'écrire sur des tags, l'API du module Yocto-RFID-15693 permet de programmer un callback appelé à chaque fois qu'un tag entre ou sort du champ de l'antenne. Et figurez-vous que ces callbacks sont horodatés. De là à utiliser cette fonctionnalité pour construire une application de chronométrage, il n'y a qu'un pas, que l'on n'a évidement pas hésité à franchir.

On a donc ressorti notre voiture télécommandée en carton basée sur un vieux châssis HPI Micro RS4 un peu amélioré. Ce truc peut rouler bien plus vite qu'il n'est humainement possible de le contrôler sur un sol encombré d'obstacles et on aimerait savoir le meilleur temps qu'il est possible d'atteindre pour faire un tour d'étage sans percuter un pied de meuble.

L'air de rien,  là-dessous, il y a un châssis Micro-RS4 avec un moteur brushless et un accu lipo 3S
L'air de rien, là-dessous, il y a un châssis Micro-RS4 avec un moteur brushless et un accu lipo 3S


Le principe

Rapelez-vous qu'avec la technologie RFID ISO-15693, c'est le lecteur qui alimente les tags RFID par l'intermédiaire de son antenne. A puissance constante, plus une antenne est grande, plus le volume dans lequel un tag est potentiellement détectable est grand, mais moins l'énergie irradiée est "dense". Similairement, plus un tag est grand, plus il peut capter d'énergie.

L'idée, c'est donc de coller le plus gros tag RFID possible sur le toit de la voiture et de construire un portique qui maintiendra une grande antenne au-dessus du sol. Il suffira de passer dessous pour que la voiture soit détectée. On a choisi une grande antenne MaxiPCB HF RFID Antenna de Metratec, ce qui nous donne une zone de détection d'environ 30x30cm. L'antenne est connectée à un Yocto-RFID-15693 qui lui est connecté au PC de contrôle via un câble USB. Le tag, quant à lui, est une étiquette RFID auto-collante de 80x50mm.

Les différents éléments
Les différents éléments


L'antenne et le Yocto-RFID-15693 sont intégrés dans un portique en carton construit un peu à la va-vite. L'avantage d'utiliser du carton, c'est que ce n'est pas cher et que si la voiture tape dedans il y a peu de chances que cela fasse des dégâts irréparables.

Le portique terminé
Le portique terminé



Programmation

Le code est relativement simple, on commence par créer une petite classe car qui sera chargée de mémoriser l'identifiant RFID d'une voiture et de calculer le temps au tour. Cette classe ne contient qu'un constructeur et une méthode à appeler à chaque fois que la voiture passe sous le portique.

class car:
  lastSeen     = 0
  bestLapTime  = -1
  tagid        = "unknown"
  lapcount     = 0
  carsCount    = 0  # static variable
  index =0
  def __init__(self,rfidtag,timestamp):
    self.lastSeen    =  timestamp
    self.tagid       =  rfidtag
    car.carsCount    =  car.carsCount+1
    self.index       =  car.carsCount
    print("(%s) car %d - starting first lap"%(self.tagid,self.index))

  def lap(self,timestamp):
    if  (timestamp-self.lastSeen)<3 : return
    currentlaptime =  timestamp-self.lastSeen
    self.lastSeen = timestamp
    self.lapcount=self.lapcount +1
    print( "(%s) car %d - lap %d - %.2f sec  " %
       (self.tagid,self.index,self.lapcount, currentlaptime),end="")
    if (currentlaptime<=self.bestLapTime) or (self.bestLapTime<0) :
      print("best lap!")
      self.bestLapTime = currentlaptime
    else:
      print("+%.2f"%(currentlaptime-self.bestLapTime))



Notez qu'on veille à ce qu'au moins trois secondes s'écoulent entre chaque détection pour éviter que la voiture ne soit détectée plusieurs fois si la liaison RFID n'est pas très stable aux abords de l'antenne.

On code ensuite un petit callback qui sera appelé à chaque fois que le tag RFID de la voiture tag passe sous l'antenne. A chaque voiture correspond un objet car stocké dans un tableau associatif indexé par l'identifiant de son tag. Lors de l’exécution du callback, si le tag est déjà répertorié, la méthode lap() de l'objet correspondant sera appelé, sinon un nouvel objet car sera créé.

cars = {}
# called automatically each time a tag enter or leave the RFID field
def tagEvent(source,  timestamp, event, id):
  global cars
  if event!="+" : return;  # we need Tag arrival only
  if id in cars:
     # if car is known, updates its lap time
     cars.get(id).lap(timestamp)
  else:
     # otherwise creates new one
     cars[id] =   car(id,timestamp)



La partie principale du code se contente d'initialiser l'API, de retrouver le lecteur RFID et de mettre en place le callback RFID. La boucle principale ne fait rien, si ce n'est appeler YAPI.Sleep et YAPI.UpdateDeviceList de temps en temps.

print("Hello..");

# uses USB device
errmsg = YRefParam()
if YAPI.RegisterHub("usb", errmsg) != YAPI.SUCCESS:
    sys.exit("init error" + errmsg.value)

# finds the RDIF reader
reader = YRfidReader.FirstRfidReader()
if reader is None: sys.exit('no RFID reader connected')

# makes sure the reader can detect tag as fast as possible
reader.set_refreshRate(100)

# tagEvent will be automatically called each time
# a tag is detected or lost
reader.registerEventCallback(tagEvent)

# main loop, doing nothing but calling YAPI.Sleep and
# YAPI.UpdateDeviceList from time to time
n= 0
while True:
  YAPI.Sleep(10,errmsg)
  n=n+1
  if n>20 : n=0
  if (n == 0): YAPI.UpdateDeviceList(errmsg)



La seule subtilité consiste à configurer le taux de rafraîchissement au maximum. Il faut se rappeler qu'en interne, le Yocto-RFID-15693 détecte les tags en effectuant un inventaire de ceux qui se trouvent à portée d'antenne. D'où l'intérêt de faire le plus d'inventaires possible par seconde. Lorsqu'il n'y a pas de tags dans le voisinage le module peut faire environ un maximum de 75 inventaires par seconde. Avec un tag, on est à 55 par seconde, avec deux tags, on tombe à 42...

Toujours dans un souci de rapidité, il faut absolument résister à la tentation de lire ou d'écrire le tag RFID à chaque passage. Non seulement, il y a pas mal de chances pour que la voiture sorte du champ avant que la transaction ne soit terminée, mais il faut aussi savoir que pendant que le Yocto-RFID-15693 effectue une opération de lecture/écriture avec un tag, il ne fait pas d'inventaire.

Toujours pour les mêmes raisons, il faut éviter d'utiliser les fonctions ColorLedCluster et Buzzer hébergées sur Yocto-RFID-15693 car elles pourraient ralentir le module.

Amélioration

La voiture étant équipée d'une caméra FPV on a eu assez vite envie de voir nos temps au tour depuis la voiture. Pour ça, on a récupéré l'écran qu'on avait construit il y a quelques années. Cet écran est un ensemble de 8 dalles Neopixel de 8x8 LEDs rgb câblées en série. Elles sont contrôlées par un Yocto-Color-V2 lui-même piloté par un YoctoHub-Ethernet alimenté par PoE. Ce qui signifie qu'on peut le placer un peu où l'on veut, c'est juste une question de longueur de câble Ethernet.


  
Affichage à LEDs visible de la voiture


Et ça marche?

Ca marche furieusement bien, pendant tout le temps où on a joué avec, le portique n'a pas manqué un seul passage. Par contre le fait voir de son temps clairement affiché à chaque passage incite à rouler de plus en plus vite, ce qui ce termine généralement par un crash.

  



Limitations

Le système a quelques limitations. Non seulement la meilleure précision que l'on puisse espérer est de l'ordre de 0.02 secondes, ce qui est probablement un peu limite pour de la compétition, mais cette précision peut potentiellement être affectée par la dérive de l'horloge du Yocto-RFID-15693, en particulier si le module vient d'être branché. Si vous voulez chasser les millisecondes, attendez quelques minutes après avoir branché le Yocto-RFID-15693, le temps que le PC de contrôle synchronise la vitesse d'horloge du module.

Le code de chronométrage est prévu pour fonctionner avec un nombre arbitraire de voitures, mais si le portique est largement assez large pour le passage d'une Micro-RS4 qui a, en gros, la taille d'une chaussure, il est un peu étroit pour deux voitures qui tenteraient de passer de front. Du coup, on s'est demandé si on ne pouvait pas fabriquer un portique plus large en utilisant plusieurs Yocto-RFID-15693 équipés d'antennes installées côte à cote. On a essayé et sans grosse surprise, ça ne marche pas bien du tout. La détection des tags n'est absolument pas fiable.

Conclusion

En quelques heures et quelques lignes de code, on a bricolé un système de chronométrage largement assez performant pour mesurer le temps au tour d'une voiture télécommandée se déplaçant à plusieurs mètres par seconde. Maintenant, la question vraiment tentante, c'est de savoir si ça marche aussi avec un mini-quadcoptère. :-)

Pour finir, si êtes intéressés par le code source du système, vous pouvez télécharger le code Python complet y compris la partie qui contrôle l'écran.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.