Cours:SaeRobotique : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(changement d'état d'un capteur)
(changement d'état d'un capteur)
Ligne 246 : Ligne 246 :
 
</source>
 
</source>
 
|}
 
|}
 +
 +
===filtrer un capteur tor===
 +
 +
<source lang=cpp>
 +
 +
bool rawValue=readCapteur();
 +
static bool value=false;
 +
 +
const uint8_t filterValue=12;
 +
static uint8_t nbTrue=0;
 +
static uint8_t nbFalse=0;
 +
 +
if ( rawValue  )
 +
{
 +
  if ( nbTrue>= filterValue)
 +
  {
 +
    value=true;
 +
    nbFalse=0;
 +
  }
 +
  else nbTrue++;
 +
}
 +
if ( !rawValue )
 +
{
 +
  if ( nbFalse>= filterValue)
 +
  {
 +
    value=false;
 +
    nbTrue=0;
 +
  }
 +
  else nbFalse++;
 +
}
 +
</source>
  
 
===Optimiser l'exécution d'une fonction===
 
===Optimiser l'exécution d'une fonction===

Version du 5 juin 2025 à 19:40

Corrections enseignants


Cours:SaeRobotiqueSuiviLigne


Cours:SaeRobotiqueTennis


Ressources communes

structure du programme

Vous pourrez utiliser la structure de programme suivante :

enum state {etapeInit,etapeChercheBalle,etapeDeplacementVersBalle};

state etapeSuivante=etapeInit;
state etapeActive=etapeInit;


int main()
{
  while(1)
  {
    // lecture des capteurs en début de boucle
    switch (etapeActive)
    {
      case etapeInit:

            // si ... etapeSuivante=
            break;
      case etapeChercheBalle:

            // si ... etapeSuivante=
            break;
      case etapeDeplacementVersBalle:

            // si ... etapeSuivante=
            break;
    }

    // on modifie l'étape active pour la prochaine boucle
    etapeActive=etapeSuivante;
  }
}

Programmation : comment faire

Exécuter une action une seule fois :

while(1)
{
   static bool dejaFait=false;
   if (dejaFait==false)
   {
      executerMonAction();
      dejaFait=true;
   }
}

Répéter une action régulièrement

void initFonctionsTempsArduino()
{
  sei();
  // marche pour 328p et 2560 et autres ...
  // à adapter suivant le µc
  // cf https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring.c
  TCCR0A=(1<<WGM01)|(1<<WGM00);
  TCCR0B=(1<<CS01)|(1<<CS00);
  TIMSK0=(1<<TOIE0);
}

int main()
{
  initFonctionsTempsArduino();
  while(1)
  {
    static uint32_t triggerTime=millis();
    uint32_t currentTime=millis();
    if (currentTime>=triggerTime)
    {
       faireMonAction();
       triggerTime += 500; // prochaine exécution dans 500ms
    }
  }
}
void initFonctionsTempsArduino()
{
  sei();
  // marche pour 328p et 2560 et autres ...
  // à adapter suivant le µc
  // cf https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring.c
  TCCR0A=(1<<WGM01)|(1<<WGM00);
  TCCR0B=(1<<CS01)|(1<<CS00);
  TIMSK0=(1<<TOIE0);
}

int main()
{
  initFonctionsTempsArduino();
  while(1)
  {
    static uint32_t triggerTime=0;
    uint32_t currentTime=millis();

    switch (etapeActive)
    {
      case etapeX:
            if ( qqch)
            {
               etapeSuivante=etapeY;
               triggerTime=currentTime;
            }
            break;
      case etapeY:
            if ( currentTime >= (triggerTime + duree ) )
            {
               etapeSuivante=etapeZ;
            }
            break;
      case etapeZ:
            ...
            break;
    }
    etapeActive=etapeSuivante;
  }
}

Affichage provisoire pour deboggage

#define debug   // mode debug
//ou
#undef debug // mode sans debug

int main()
{
  ...
  while(1)
  {
    #ifdef debug
       Serial.println("juste si debug");
    #endif
  }
}
#define DEBUG   //If you comment this line, the DEBUG_PRINT & DEBUG_PRINTLN lines are defined as blank.
#ifdef DEBUG    //Macros are usually in all capital letters.
   #define DEBUG_PRINT(...)    Serial.print(__VA_ARGS__)     //DEBUG_PRINT is a macro, debug print
   #define DEBUG_PRINTLN(...)  Serial.println(__VA_ARGS__)   //DEBUG_PRINTLN is a macro, debug print with new line
#else
   #define DEBUG_PRINT(...)     //now defines a blank line
   #define DEBUG_PRINTLN(...)   //now defines a blank line
#endif
int main()
{
  while(1)
  {
    DEBUG_PRINTLN("juste si debug");
  }
}


changement d'état d'un capteur

au front montant d'un capteur 1x si le capteur est actif suffisamment longtemps
bool valeurActuelle=valeurInit;
bool valeurPrecedente=valeurInit;

...
int main()
{
   ...
   while(1)
   {
      valeurPrecedente=valeurActuelle;
      valeurActuelle=lireValeurCapteur();
      if ( (valeurPrecedente==false) and (valeurActuelle==true) )
      {
         // action, par ex:
         nombreFrontMontant++;
      }
   }
}
bool valeurActuelle=valeurInit;
int8_t dureeActif=0;
bool isFront=true;

...
int main()
{
   ...
   while(1)
   {
      valeurActuelle=lireValeurCapteur();
      if (valeurActuelle==true)
      {
         if (dureeActif>=20)
         {
            // faire l'action, par ex
            if (isFront==true)
            {
                isFront=false;
                nombreFrontMontant++;
            }
         }
         else dureeActif++;
      }
      else
      {
         dureeActif=0;
         isFront=true;
      }
   }
}

filtrer un capteur tor

bool rawValue=readCapteur();
static bool value=false;

const uint8_t filterValue=12;
static uint8_t nbTrue=0;
static uint8_t nbFalse=0;

if ( rawValue  )
{
   if ( nbTrue>= filterValue)
   {
     value=true;
     nbFalse=0;
   }
   else nbTrue++;
}
if ( !rawValue )
{
   if ( nbFalse>= filterValue)
   {
     value=false;
     nbTrue=0;
   }
   else nbFalse++;
}

Optimiser l'exécution d'une fonction

inline void setVitesse(int16_t vmG, int16_t vmD) __attribute__((always_inline));

void setVitesse(int16_t vmG, int16_t vmD)
{
   // code de la fonction
   ...
}

Diagramme d'état

Pour aller plus loin dans la programmation sous forme de machine à état fini, vous utiliserez comme base le programme suivant :

Media:TestFiniteStateMachine.zip

Composants Kicad

  • Résistances :
    • symbole R
    • boitier suivant la valeur : 1206(CMS)/Axial DIN0309 (traversant)
  • Condensateur
    • symbole C
    • boitier suivant la valeur 1206(CMS)
  • VNH7070
    • télécharger et décompresser le fichier Media:VNH7070BASTR.zip
    • ajouter la librairie en suivante la page : https://www.snapeda.com/about/import/#KiCad6
    • attention : pour l'ajout de la librairie de l'empreinte, indique comme "pseudo nom" VNH7070BASTR
    • modèle 3d
      • ajouter le fichier VNH7070BASTR.step
      • faire une rotation sur X de 90°
  • Arduino Nano
    • symbole Arduino_Nano_v2.x
    • modèle 3d
      • télécharger et décompresser : Media:Arduino_nano.STEP.zip
      • dans les propriétés de la carte (éditeur de pcb), onglet modèle 3d
        • ajouter le fichier téléchargé
        • rotation X 90
        • rotation Z -90
        • décalage Z 11mm
      • ajouter 2 barrettes M/F
      • ${KICAD9_3DMODEL_DIR}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x15_P2.54mm_Vertical.step
      • décaler le 2ème en X de 15,24mm
  • bornier à vis : Screw_Terminal_01x02
  • MPU-9250
  • convertisseur de niveau gt1167 A modifier, pas le bon écartement !!
    • utiliser la librairie : Media:BOB-12009.zip
    • modèle 3d :
      • BOB-12009.step
        • rotation 90/0/0
        • translation 0/0/9
      • ajouter 2 barrettes M/F : ${KICAD9_3DMODEL_DIR}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x06_P2.54mm_Vertical.step
        • rotation 0/0/0
        • translation 5.08/6.35/0 et -5.08/6.35/0