Aide projet Cadenas, simulation accéléromètre

Bonjour, je suis actuellement en Terminale SI, même avec le confinement nous devons finaliser notre projet de fin d’année. Je travaille sur un cadenas connecté et plus particulièrement sur la partie logicielle. J’ai pour le moment un programme qui lorsque le cadenas se ferme lance l’accéléromètre et si le vélo bouge le cadenas sonne ( J’ai beaucoup résumé je vais mettre le programme ). Mais lors du premier passage devant mes professeurs il m’a été demandé de faire une simulation pour montrer quelque chose de concret. Avec un vélo et le cadenas contenant l’accéléromètre sur le vélo pour que je puisse simuler par exemple lorsque le vélo bouge et que le cadenas est fermé cela sonne. Cela implique aussi des calculs pour savoir à partir de quel angle le cadenas va sonner. J’ai fais quelques recherches mais je ne trouve pas de logiciel de simulation qui puisse faire ceci. Si vous en connaissez ou avez des solution “bis” cela m’aiderait énormément je bloque un peu. Je met aussi en pièce jointe mon code actuel arduino pour le cadenas. L’accéléromètre utilisé est le : Grove 3 axis digital accelerometer (± 1.5g) MMA7660FC
Merci d’avance !

moteur_ferm__avec_condition_ou.ino (1.82 KB)

Je ne comprend pas bien - s’ils veulent voir quelque chose en vrai, pourquoi prendre un simulateur ? Vous n’avez pas les composants sous la main ?

Ils voudraient des simulations avec des calculs comme c'est un projet multi disciplinaire. Et avec le confinement il nous est impossible de faire un cadenas matériel pour la fin de l'année. Sinon oui j'aurais fais ça c'est le plus simple et là je bloque un peu dessus.

Y’a pas bcp de calculs à faire... si le vélo est penché à l’arrêt quand vous fermez le cadenas (= fermez un interrupteur) vous notez les accélérations mesurées à ce moment là, le vélo étant immobile vous n’avez que la gravité et le capteur sur le vélo n’étant pas purement orienté vous aurez une composante de G sur les différents axes.

Dès que ces vecteurs s’éloignent un tantinet de leur position vous savez qu’il se passe quelque chose et vous sonnez. C’est pas super important de savoir si le vélo est redressé ou mis à l’envers ... l’important dans votre dispositif c’est que Quelqu’un est en train de le déplacer..

En simulation vous pouvez mettre trois potentiomètres pour simuler les 3 axes par exemple

Faut pas non plus que le vélo sonne au moindre choc.

A l'immobilité tu as un vecteur G0 qui est la pesanteur, décomposée sur les 3 axes dont probablement aucun n'est vertical. Régulièrement ensuite tu mesures le nouveau vecteur G et tu calcules l'écart par (G-G0)^2 c-à-d la différence des vecteurs au carré. Tu compares cet écart à un seuil, fixé expérimentalement. Si > seuil, ça sonne.

Attention, si tu fais ça, ton prof va te demander pourquoi tu fais comme ça, et faudra répondre....

[Edit] Pour éviter de sonner au moindre choc, il faudrait que l'écart soit constaté pendant ... un certain temps.

J-M-L: Y’a pas bcp de calculs à faire... si le vélo est penché à l’arrêt quand vous fermez le cadenas (= fermez un interrupteur) vous notez les accélérations mesurées à ce moment là, le vélo étant immobile vous n’avez que la gravité et le capteur sur le vélo n’étant pas purement orienté vous aurez une composante de G sur les différents axes.

Dès que ces vecteurs s’éloignent un tantinet de leur position vous savez qu’il se passe quelque chose et vous sonnez. C’est pas super important de savoir si le vélo est redressé ou mis à l’envers ... l’important dans votre dispositif c’est que Quelqu’un est en train de le déplacer..

En simulation vous pouvez mettre trois potentiomètres pour simuler les 3 axes par exemple

Oui, mais justement nos professeurs voudraient des valeurs d'angles pour lesquelles le vélo pourraient sonner ou alors une translation. C'est pour ca que je parlais de simulation et je n'ai pas chez moi le matériel pour faire les test sans simulateur

biggil: Faut pas non plus que le vélo sonne au moindre choc.

A l'immobilité tu as un vecteur G0 qui est la pesanteur, décomposée sur les 3 axes dont probablement aucun n'est vertical. Régulièrement ensuite tu mesures le nouveau vecteur G et tu calcules l'écart par (G-G0)^2 c-à-d la différence des vecteurs au carré. Tu compares cet écart à un seuil, fixé expérimentalement. Si > seuil, ça sonne.

Attention, si tu fais ça, ton prof va te demander pourquoi tu fais comme ça, et faudra répondre....

[Edit] Pour éviter de sonner au moindre choc, il faudrait que l'écart soit constaté pendant ... un certain temps.

J'avais déjà fais une différence des valeurs absolue des accélérations initiale et de celle prise toutes les secondes dans le programme que j'ai mis en pièce jointe. Justement pour éviter qu'il sonne au moindre choc, je ne sais pas si c'est pareil.

Il n’y a pas de MPU je pense dans tinkerCad donc il faut passer par autre chose, de potentiomètres comme dit avant pourraient faire l’affaire. Il faudra expliquer qu’ils représentent la projection de G sur les 3 axes en fonction de l’installation physique du capteur sur le vélo et la position du vélo a une instant t

En disant par exemple que l’axe X c’est le grand axe du vélo (la barre supérieure du cadre) l’axe Y celui du guidon (orthogonal au cadre) et Z l’axe vertical, au repos si le vélo est bien droit x et y doivent être quasi nuls et z doit valoir G (l’accélération gravitationnelle). Comme vous ne serez pas droit, c’est la somme des 3 vecteurs sur x,y et z qui vous donne G. A partir des projections sur ces axes on peut déterminer si le vélo penche et de quel angle autour de X et autour de Y

C’est l’attitude, les fameux Lacet, Tangage et Roulis

Et si j'ai bien compris la variation de valeur des potentiomètres seraient la variation de valeur des accélérations ? Y aurait il alors des calculs possible pour un angle par exemple ? ( J'avoue être vraiment novice dans tout ce qui est arduino, potentiomètre et autre et ne pas connaitre trop leur fonctionnement)

Un peu de contexte pour vous aider à expliquer votre approche:

Votre accéléromètre est un MMA7660FC qui mesure des accélérations jusqu'à ±1.5g sur chacun des 3 axes X,Y et Z. Il offre aussi d'ailleurs un mode de "Shake Detection" (on secoue et on peut préciser les axes d'intérêt) et de "Tap Detection" on tapote dessus.

il n'est pas super précis et offre 6-bit seulement par axe, donc 64 valeurs pour représenter jusqu'à ±1.5G (donc une amplitude de 3G)

Un G est une accélération de 9,80665 ms−2 donc chaque bit va représenter (3*9,80665)/64= 0,46ms−2 ou une autre façon de le voir c'est 64/3 = ~21 LSB par G que vous allez retrouver dans la spec.

Pour votre simulation, vous auriez 3 potentiomètres qui devront générer ces valeurs entre 0 et 63 (le 64 valeurs possibles) - mais si vous faites la lecture de vos potentiomètres avec analogRead() vous avez une valeur entre 0 et 1023. Vous appeleriez alors la fonction map() pour convertir cette valeur vers une autre valeur qui serait plus en lien avec ce que l' accéléromètre retournerait (pour être cohérent) donc entre 0 et 63.

const byte xAxisPotPin = A0;
const byte yAxisPotPin = A1;
const byte zAxisPotPin = A2;

... plus loin dans le code

int8_t xReg = map(analogRead(xAxisPotPin), 0, 1024, 0, 64); // on aura une valeur entre 0 et 63 soit 6 bits
int8_t yReg = map(analogRead(yAxisPotPin), 0, 1024, 0, 64); // on aura une valeur entre 0 et 63 soit 6 bits
int8_t zReg = map(analogRead(zAxisPotPin), 0, 1024, 0, 64); // on aura une valeur entre 0 et 63 soit 6 bits

Voilà vous avez votre MPU simulé...

Si on veut aller un peu plus loin pour avoir un code qui pourrait ensuite utiliser la bibliothèque associée à votre composant, on pourrait faire une fausse bibliothèque qui ressemblerait à la vraie.

Le code source de la vraie bibliothèque est disponible -> Accelerometer_MMA7660 et vous avez deux fichiers importants, MMA7660.cpp et MMA7660.h

Dans le .h on voit que la bibliothèque offre les fonctions suivantes:

    void init();
    void init(uint8_t interrupts);
    void setMode(uint8_t mode);
    void setSampleRate(uint8_t rate);

    // get the signed value of x,y,z register
    bool getXYZ(int8_t* x, int8_t* y, int8_t* z);

    // calculate the acceleration from the signed value of x,y,z register
    bool getAcceleration(float* ax, float* ay, float* az);

    // lookup the acceleration from the lookup table from this chip's datasheet
    bool getAcceleration(MMA7660_ACC_DATA* data);

    // get all the register value
    bool getAllData(MMA7660_DATA* data);

On va essayer de refaire une bibliothèque qui offre un peu la même interface de façon à simuler le MPU mais on va conserver que celles que vous utiliseriez dans le vrai monde pour votre projet, soit l'appel de l'initialisation de la bibliothèque

void init();

et ensuite la lecture des accélérations

bool getAcceleration(float* ax, float* ay, float* az);

Il nous faut donc une classe qui a ces deux fonctions uniquement (et en prime on peut intégrer à la fonction init des valeurs par défaut qui seraient les pins de vos potentiomètres A0,A1 et A2).

Si on simule avec les potentiomètres l'obtention d'un nombre entre -32 et +31 on aurait le fonctionnement à l'identique de leur fonction getXYZ() donc il nous suffit d'écrire

bool getXYZ(int8_t* x, int8_t* y, int8_t* z) {
  *x = map(analogRead(xAxisPotPin), 0, 1024, -32, 32); // résultat entre -32 pour 0 et +32 pour 1024 qui n'est pas possible donc +31 sur la plage linéaire juste avant 1023
  *y = map(analogRead(yAxisPotPin), 0, 1024, -32, 32);
  *z = map(analogRead(zAxisPotPin), 0, 1024, -32, 32);
  return true;
}

et ensuite on peut conserver le code d'origine de la librairie pour getAcceleration()

bool getAcceleration(float* ax, float* ay, float* az) {
  int8_t x, y, z;
  if (!getXYZ(&x, &y, &z)) return false;
  *ax = x / 21.00;
  *ay = y / 21.00;
  *az = z / 21.00;
  return true;
}

mais comme on a vu que le 21 venait de 64/3 on peut mettre cette valeur à la place de 21.00 pour être un peu plus précis.

voilà en mettant tout cela ensemble, vous pouvez créer un fichier .hpp de définition de notre nouvelle bibliothèque (pour simplifier et en avoir qu'un)

FakeMMA7660.hpp

/*
    MMA7760.hpp
    FAKE Library for accelerometer_MMA7760 simulated with 3 potentiometers
    Copyright (c) 2020 J-M-L
    Author        :   J-M-L
    Create Time   :   April 2020
    Change Log    :

    The MIT License (MIT)
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/


#ifndef __FAKEMMC7660_H__
#define __FAKEMMC7660_H__

#include <Arduino.h>

class FAKEMMA7660 {
  private:
    byte xAxisPotPin;
    byte yAxisPotPin;
    byte zAxisPotPin;

  public:
    void init(byte xPotPin = A0, byte yPotPin = A1, byte zPotPin = A2 ); // valeurs par défaut

    // get the signed value of x,y,z register
    bool getXYZ(int8_t* x, int8_t* y, int8_t* z);

    // calculate the acceleration from the signed value of x,y,z register
    bool getAcceleration(float* ax, float* ay, float* az);
};

void FAKEMMA7660::init(byte xPotPin, byte yPotPin, byte zPotPin) {
  xAxisPotPin = xPotPin;
  yAxisPotPin = yPotPin;
  zAxisPotPin = zPotPin;
  pinMode(xAxisPotPin, INPUT);
  pinMode(yAxisPotPin, INPUT);
  pinMode(zAxisPotPin, INPUT);
}

/*Function: Get the contents of the registers in the MMA7660*/
/*          so as to calculate the acceleration.            */
bool FAKEMMA7660::getXYZ(int8_t* x, int8_t* y, int8_t* z) {
  *x = map(analogRead(xAxisPotPin), 0, 1024, -32, 32); // résultat entre -32 pour 0 et +32 pour 1024 qui n'est pas possible donc +31 sur la plage linéaire juste avant 1023
  *y = map(analogRead(yAxisPotPin), 0, 1024, -32, 32);
  *z = map(analogRead(zAxisPotPin), 0, 1024, -32, 32);
  return true;
}

bool FAKEMMA7660::getAcceleration(float* ax, float* ay, float* az) {
  int8_t x, y, z;
  if (!getXYZ(&x, &y, &z)) return false;
  *ax = x * 3.0 / 64.0; // (on divise par ~21 --> 64/3 pour être précis ce qui revient à multiplier par 3/64)
  *ay = y * 3.0 / 64.0; // idem
  *az = z * 3.0 / 64.0; // idem
  return true;
}

#endif

ensuite votre code pour l'utiliser va ressembler vraiment à ce que vous auriez fait en vrai, mais au lieu d'instancier un MMA7660 on va instancier un FAKEMMA7660

Voici un petit .ino de test

#include "FakeMMA7660.hpp"

FAKEMMA7660 mpu;

void setup() {
  Serial.begin(115200);
  mpu.init(); // pins par défaut A0, A1, A2
}

void loop()
{
  float accX, accY, accZ;
  if (mpu.getAcceleration(&accX, &accY, &accZ)) {
    Serial.print(F("Accélération:"));
    Serial.print(accX);
    Serial.write('\t'); // tabulation à l'affichage
    Serial.print(accY);
    Serial.write('\t'); // tabulation à l'affichage
    Serial.println(accZ);
  }
}

il faut mettre le fichier FakeMMA7660.hpp dans le répertoire du sketch pour qu'il soit pris en compte. ou intégrer son code au début du .ino

Voilà avec ce petit code vous pouvez utiliser tinkerCad et en bougeant les potentiomètres votre sketch recevra des accélérations sur les axes.

Quand vous voudrez passer au vrai code, au lieu de

#include "FakeMMA7660.hpp"

FAKEMMA7660 mpu;

il suffira de faire

#include <MMA7660.h>

MMA7660 mpu;

et le tour sera joué :slight_smile:

En espérant que cela vous aide à démarrer, bonne journée

Vous pouvez maintenant faire du code pour calculer roulis, tangage et lacet qui sont les angles que vos profs veulent voir et dire si le vélo tangue (on lève la roue avant par exemple pour le sortir de son rangement) de tant de degrés alors alerte, ou si le roulis change de tant de degrés (on a relevé le vélo qui était penché sur sa béquille) alors alerte.

Pour comprendre les entrées analogique lisez le tuto d'eskimon associé et il y a des tonnes d'information en ligne sur ce qu'est un potentiomètre si vous n'avez pas vu ça en classe.

Merci beaucoup pour toutes ces infos ça va vachement m'aider pour simuler l'accéléromètre. Je testerai ça sur tinkercad je pense que c'est possible. Si j'ai quelques petites questions je reviendrais vers vous. Merci pour tout et bonne journée !

Dernière petite question auriez vous un lien pour expliquer comment fonctionne le calcul des angles et comment faire ? J'ai réussis à utiliser votre librairie et à me faire un code pour bien que ce soit cohérent avec le cadenas merci beaucoup pour cela. Il ne me reste plus que pour les angles si vous avez des pistes pour que je puisse commencer ce serait génial .

Vous avez fait un peu de trigonométrie en classe ? Le cercle trigo, les sinus, cosinus, et fonctions inverses arcsinus, arccosinus etc ça vous parle ?

trigo.png

---> Savez vous calculer l'angle avec l'axe des abscisses (X) en fonction des coordonnées (x,y) de ce vecteur ?

Là c'est en 2D, ben en 3D c'est pareil sauf que le vecteur Accélération est projeté sur 3 axes au lieu de 2.

trigo.png

D'accord, donc avec les coordonnés en x et y que me donne le programme ( de +32 à -32 si je ne me trompe pas) je peux calculer l'angle effectivement merci. Mais si le vecteur a une composante en z cela devient plus compliqué non ? Ou même autre qu'en z, s'il a une troisième composante, pour en déduire la valeurs de chacun de ses cotés. Est ce que ce serait possible avec le produit scalaire ? Si on détermine un vecteur permettant de former l'angle recherché. C'est peut être plus compliqué, je vais essayer de me pencher sur la trigo en 3d et voir pour faire un programme qui calculerait tout si j'y arrive.

c’est pareil en 3D, vous prenez simplement les composantes sur les plans deux à deux

faites une recherche sur “angle entre deux vecteurs en 3D” et vous aurez plein d’infos

le programme ne va pas donner de de +32 à -31 mais comme on passe par la fonction qui donne l’accélération on a une accélération en m.s-2

Un peu de math ne fait aucun mal, j'aime bien même, mais... pourquoi calculer des angles ici ?

Il suffit que le vecteur G-> soit instable pendant au moins 3 secondes (pour filtrer les chocs, glissements, repositionnements) pour lancer l'alarme. Instable = chaque mesure s'écarte de la précedente de plus du seuil fixé. ça suffit, non ?

@biggil oui mais on a posé la question déjà si vous lisez la discussion c’est une demande des profs pour qu’il y ait une peu plus de boulot je suppose

Bonjour, après avoir suivis vos conseils j'ai réussis à faire un programme simulant l'accéléromètre et les alarmes si il bouge. Après pas mal de temps j'ai aussi fais sur géogébra des vecteurs me permettant par rapport aux valeurs de l'accéléromètre de calculer l'angle. Mais j'ai une question, j'ai remarqué que l'accéléro n'affiche quasiment jamais des valeurs à + ou - 1.5g qui sont les valeurs maximales ou minimales. Ce qui fait que par exemple le simulateur pour des valeurs de 1.5g sur x, 1.5g sur Y et 0g sur Z me donne un angle de 45°. Hors lorsque je vérifie expérimentalement on tourne autour des 0.7g en x et y. Sauriez vous comment je peux régler ce problème ? Depuis l'accéléromètre ou bien le simulateur avec les calculs d'angle Merci d'avance

Ce qui fait que par exemple le simulateur pour des valeurs de 1.5g sur x, 1.5g sur Y et 0g sur Z me donne un angle de 45°

ça ne veut rien dire... de quel angle parlez vous ?

les accélérations que vous donnez voudraient dire que votre mobile a une poussée verticale de 1G qui est compensée par l'attraction terrestre (d'où 0G sur Z) et vous accélérez à 1.5 G en X et Y. donc oui dans le plan Z=0 l'angle entre l'axe des X et votre vecteur de déplacement est de 45°, c'est normal.