Déterminer l'inclinaison d'une pyboard en MicroPython

Un cas d'usage de l'accéléromètre intégré à la pyboard

La pyboard comporte un petit accéléromètre, ce qui permet de faire une estimation de l’inclinaison de la carte !

Principe

Comme son nom le suggère, un accéléromètre mesure une accélération. Celui intégré à la pyboard fournit une valeur d’accélération pour chacun des trois axes x, y et z, qui donnent ainsi les coordonnées d’un vecteur accélération dans un repère associé à la pyboard.

Quand la pyboard est au repos ou presque au repos, l’accélération mesurée correspond l’accélération due à la gravitation terrestre, g\vec g. Autrement dit, il s’agit des coordonnées du vecteur g\vec g dans le repère associé à la pyboard.

Pour un projet, j’ai besoin de connaître l’inclinaison de la carte par rapport à la verticale. Comme g\vec g est vertical dans le repère terrestre, l’angle entre g\vec g et l’axe z dans le repère associé à la pyboard correspond à l’angle entre la verticale et la pyboard.

Sur le schéma ci-dessous, cela se traduit par le fait que les deux angles verts sont identiques (à condition de faire attention à l’orientation).

On peut retrouver l’angle à partir des coordonnées avec un peu trigonométrie. En restreignant l’angle à [-90° ; +90°], il suffit de déterminer le sinus de l’angle pour obtenir l’angle avec sa fonction réciproque arcsin\arcsin.

L’angle recherché est alors :

θ=arcsin(xx2+z2)\theta = \arcsin \left( \frac{x}{\sqrt{x^2 + z^2}} \right)

Implémentation

L’implémentation est une simple transcripton de la formule mathématique, en récupérant les coordonnées de l’accéléromètre. J’ai hésité à faire un retour uniquement en degrés, ce qui s’est traduit par un non-choix : il y a une option pour renvoyer des radians.

import pyb

class AngleEstimator:
    def __init__(self):
        self.accel = pyb.Accel()

    def angle(self, unit='deg'):
        x = self.accel.x()
        z = self.accel.z()
        sin = x / math.sqrt(x * x + z * z)
        angle = math.asin(sin)
        if unit == 'deg':
            return angle * 180 / math.pi
        else:
            return angle

Performance

Vitesse d’exécution

La méthode angle() s’exécute en environ 275 µs, ce qui est assez rapide pour mon usage. Il y a peu à gagner sur les calculs mathématiques, la grosse majorité du temps est prise par les appels à l’accéléromètre (environ 250 µs).

Résolution/Précision

La précision est assez faible. Des techniques de filtrages peuvent être utiles pour y pallier, mais la méthode peut dépendre beaucoup de l’usage qu’on fait de la valeur d’inclinaison. Aussi, je ne m’étendrai pas dessus.

Cette faible résolution est due à la résolution de l’accéléromètre, qui est très limitée. Le composant est fait pour mesurer des positions grossières, à destination des appareils portables (par exemple pour détecter l’orientation d’un téléphone).

Pour mon besoin, ce paramètre risque d’être limitant, aussi, je devrais peut-être me tourner vers des composants dédiés à ce genre d’application (type IMU).

Offset

L’offset est un décalage propre à chaque composant et qui devrait être corrigé pour exploiter au mieux le composant. C’est faisable en logiciel ou directement dans le matériel.

L’accéléromètre est un MMA7660FC dispose de pas mal de documentation, notamment pour expliquer comment régler l’offset (Application Note AN3841). Curieusement, cette méthode n’est pas présente dans la documentation principale.


Miniature du billet : logo de MicroPython (source).

2 commentaires

La méthode angle() s’exécute en environ 275 µs, ce qui est assez rapide pour mon usage. Il y a peu à gagner sur les calculs mathématiques, la grosse majorité du temps est prise par les appels à l’accéléromètre (environ 250 µs).

Par curiosité, comment as-tu pu déterminer ces chiffres ?

J’ai instrumenté le code avec les fonctions pyb.micros() et pyb.elapsed_micros(), qui utilisent l’horloge de la carte pour mesurer le temps. Ensuite, j’ai enlevé/remis des lignes de codes pour voir leur contribution. C’est pas très précis, mais ça marche largement assez bien pour ce que je voulais voir. Aussi, c’est très répétable, donc j’ai assez confiance sur les ordres de grandeur du résultat.

La lecture des valeurs de l’accéléromètre se fait à travers le bus I2C. Intuitivement, on peut en effet penser que ça peut être lent lent par rapport à des calculs qui restent sur le microcontrôleur. Je n’ai pas creusé plus loin pour savoir exactement ce qui prend du temps dans la communication, cependant. :)

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte