Partage
  • Partager sur Facebook
  • Partager sur Twitter

[C/C++]Acquisition d'une fréquence venant du port COM

Projet TPE

    18 janvier 2007 à 7:24:16

    merci,

    par contre "coder de façon abstraite", c'est pas évident quand on débute, car on ne peut pas tester son code etc...

    euh,... le code doit-il être dans plusieurs fonctions?
    mais, si j'ai bien compris une fonction qui fait son return, hop ensuite elle s'arrête...
    sauf si elle est contenue dans une "boucle" dont la condition est remplie?

    imaginons une fonction qui calcule vitesseVent = 2.5 * frequenceHertz
    et qui "return" vitesseVent
    cette variable vitesseVent pourra-t-elle etre utilisée dans une autre fonction?

    Aussi, que met-on en priorité dans la fonction main?
    • Partager sur Facebook
    • Partager sur Twitter
      18 janvier 2007 à 9:02:37

      Citation : sam_fra

      par contre "coder de façon abstraite", c'est pas évident quand on débute, car on ne peut pas tester son code etc...


      La programmation, c'est précisément l'art de manier des concepts abstraits.

      Mais c'est un concept bien connu en mathématiques ou en physique, ou on cherche à établir une formule générale avant de faire l'application numérique. En informatique c'est pareil. On raisonne sur du texte qui représente des données. La valeur exacte des données est souvent peu importante. Ce qui compte c'est ce qu'elle représente (le sens, la signification, la sémantique, the meaning).

      Si je définis :
      BLEU=1
      ROUGE=2
      VERT=3

      ou
      BLEU=111
      ROUGE=222
      VERT=333

      ca ne change rien au codage qui fait :

      couleur (BLEU)
      imprimer("hello")

      C'est ça l'abstraction. On s'attache au sens, pas à la valeur.

      Pour simplifier, une machine ne voit que des valeurs, et un humain ne raisonne qu'avec du sens. L'informatique est l'art de faire comprendre le sens à la machine. Pour cela, l'humain 'fait abstraction' de la machine et utilise son raisonnement. Les langages de programmation sont proche de l'humain, et sont conçu pour traduire du texte en code machine.

      Mais, et tant que les Cylons n'ont pas pris le pouvoir, c'est un humain qui conçoit le code de la machine. Donc même à ce niveau là, il a prévu un codage qui permet facilement de savoir de quoi on parle.

      Si je te dis (valeurs arbitraires, je ne suis pas une machine):

      34 A2 54 6E


      tu auras du mal à suivre (et moi aussi). Par contre, la machine saura quoi en faire.

      Mais si je dis

      mov, ax, 123


      même si ça te parais ésotérique au début, il est finalement simple de comprendre que ça veut dire :

      "prend la valeur 123 et met la dans le registre AX",

      ou, en pseudo code :

      AX <- 123


      pour peu qu'on connaisse les clés de ce langage. Encore une fois, c'est ça l'abstraction. (Ce langage s'appelle l'assembleur, et il est propre à chaque processeur).

      Citation : Pas de titre

      euh,... le code doit-il être dans plusieurs fonctions?
      mais, si j'ai bien compris une fonction qui fait son return, hop ensuite elle s'arrête...


      Je t'arrête tout de suite. Pour coder en C, il faut apprendre le C. Ca ne se fait pas en 5 minutes, et le C est un langage bourré de pièges. Il y a un tutoriel sur ce site.
      • Partager sur Facebook
      • Partager sur Twitter
      Music only !
        18 janvier 2007 à 12:46:12

        Personnellement, je ferai le programme en plusieurs fonctions.

        Le main.c se chargerait d'appeler les fonctions d'acquisition et de traitement avant éventuellement la fonction d'affichage, et ensuite de faire la boucle.

        Le seul problème qui réside là dedans selon moi, c'est pour traiter l'acquisition: comme l'a soulevé -ed-, on ne peut pas monopoliser le CPU pour compter les impulsions qui arrivent du signal.

        Voila comment moi je ferais, au niveau de la structure du programme, je n'ai pas assez de connaissances pour dire exactement comment je ferais pour acquérir le signal.

        Donc voila, si ça peut t'aider, tant mieux.
        • Partager sur Facebook
        • Partager sur Twitter
          18 janvier 2007 à 12:53:45

          Citation : Magloan

          Le seul problème qui réside là dedans selon moi, c'est pour traiter l'acquisition: comme l'a soulevé -ed-, on ne peut pas monopoliser le CPU pour compter les impulsions qui arrivent du signal.


          Une boucle avec une suspension de 1 seconde (Windows : Sleep(1000)), par exemple. Le comptage donne des Hertz...

          SAM : Tu devrais déjà au moins pouvoir au moins écrire l'algorithme du programme.

          Nan. Voir plus loin...
          • Partager sur Facebook
          • Partager sur Twitter
          Music only !
            18 janvier 2007 à 13:23:46

            Justement -ed-, si j'ai bien compris, la fonction sleep "endore" l'execution du prgm pour le temps programmé, comment dans ce cas serait il possible de faire compter les impulsions du signal?

            Si tu peux m'éclairer là dessus.
            Merci
            • Partager sur Facebook
            • Partager sur Twitter
              18 janvier 2007 à 15:28:00

              Citation : Magloan

              Justement -ed-, si j'ai bien compris, la fonction sleep "endore" l'execution du prgm pour le temps programmé, comment dans ce cas serait il possible de faire compter les impulsions du signal?

              Si tu peux m'éclairer là dessus.


              Oui, j'ai réfléchi à ça pendant ma sieste. C'est vrai qu'on doit traiter le signal (ça me parait tellement illogique de faire ça dans un PC, que je n'ai pas fait attention).

              Il faut donc faire un échantillonnage de l'état à une cadence rapide. Pour ça, on fait une boucle avec une suspension minimale (Sleep(1), par exemple) qui va lire l'état du contact. A chaque fois que l'état lu est différent de l'état précédent, (par exemple 0 vers 1) on incrémente le compteur.

              Ca nécessite un petit algorithme avec une variable d'état (logique séquentielle). Pour bien concevoir ce genre d'algorithme, un graphe etat/transition peut aider. (C'est l'occasion d'apprendre quelque chose hé hé).

              On commence par définir les évènements :

              C'est pas dur :
              • L'état lu est zéro
              • L'état lu est un

              Ensuite, on définit les états. C'est là qu'il faut un peu réfléchir...

              Y'en a un qui est facile, c'est l'état initial. (Ben oui, faut bien démarrer...)

              - initial

              ensuite, on va dire que au démarrage, on lit l'état du port. Si il vaut 0, on va attendre qu'il passe à 1.
              Si il vaut 1, on va attendre qu'il passe à 0. On a donc 3 états :
              • initial
              • attendre 0
              • attendre 1

              Maintenant les transitions (comment on passe d'un état à un autre et qu'est-ce qu'on fait) :

              Le schéma formel d'une transition est :

              DE état initial A état final PAR evenement FAIRE action

              En voici la liste :
              • DE initial A attendre 1 PAR état lu zéro FAIRE compteur à zéro, noter l'heure
              • DE initial A attendre 0 PAR état lu un FAIRE compteur à zéro, noter l'heure
              • DE attendre 1 A attendre 0 PAR état lu zéro FAIRE rien
              • DE attendre 0 A attendre 1 PAR état lu un FAIRE
                • incrémenter le compteur
                • lire l'heure
                • si elle est supérieure de une seconde à l'heure précédente
                  • noter la nouvelle heure
                  • évaluer la fréquence
                  • calculer la vitesse
                  • afficher la vitesse
                  • compteur à zéro




              Image utilisateur

              Affaire classée.

              Un peu de théorie sur les machines à états (FSM)

              http://mapage.noos.fr/emdel/fsm_um.htm#theorie
              • Partager sur Facebook
              • Partager sur Twitter
              Music only !
                18 janvier 2007 à 16:18:18

                ok

                ça me rappelle les cours sur les CPLD et le VHDL, en fin de compte, c'est pareil.

                Et avec ça, on utilise pas toutes les ressources CPU.
                Bon, il n'y a plus qu'a coder le programme en conséquence.

                Bon courage a toi Sam_fra
                • Partager sur Facebook
                • Partager sur Twitter
                  18 janvier 2007 à 18:13:19

                  Merci, j'arrive bien à comprendre tout ça

                          |    ETAT_0     |     ETAT_1    |
                    ------|---------------|---------------|
                    INIT  | WAIT_1 / ACT_1| WAIT_0 / ACT_1|
                    ------|---------------|---------------|
                    WAIT_0|               | WAIT_1 / ACT_2|
                    ------|---------------|---------------|
                    WAIT_1| WAIT_0 /      |               |
                    ------|---------------|---------------|


                  Avec ACT_1: mettre compteur à 0, noter l'heure
                  ACT_2:

                  Citation : -ed-

                  # incrémenter le compteur
                  # lire l'heure
                  # si elle est supérieure de une seconde à l'heure précédente

                  * noter la nouvelle heure
                  * évaluer la fréquence
                  * calculer la vitesse
                  * afficher la vitesse
                  * compteur à zéro




                  Par contre, au niveau du code C,
                  Je peux faire la méthode du Switch-case comme expliqué dans le lien, avec mes propores evenements/etats/ etc comme repertorié dans le tableau ci dessus,
                  mais, comment ensuite définir chaque action...
                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 janvier 2007 à 18:50:36

                    Citation : sam_fra

                    Merci, j'arrive bien à comprendre tout ça


                            |    ETAT_0     |     ETAT_1    |
                      ------|---------------|---------------|
                      INIT  | WAIT_1 / ACT_1| WAIT_0 / ACT_1|
                      ------|---------------|---------------|
                      WAIT_0|               | WAIT_1 / ACT_2|
                      ------|---------------|---------------|
                      WAIT_1| WAIT_0 /      |               |
                      ------|---------------|---------------|



                    Woaw ! Je suis impressionné. En général, quand le parle de FSM, on prend pour un martien...

                    Citation : Pas de titre

                    Avec ACT_1: mettre compteur à 0, noter l'heure
                    ACT_2:

                    Citation : -ed-

                    # incrémenter le compteur
                    # lire l'heure
                    # si elle est supérieure de une seconde à l'heure précédente

                    * noter la nouvelle heure
                    * évaluer la fréquence
                    * calculer la vitesse
                    * afficher la vitesse
                    * compteur à zéro


                    Parfait.

                    Citation : Pas de titre


                    Par contre, au niveau du code C,
                    Je peux faire la méthode du Switch-case comme expliqué dans le lien, avec mes propores evenements/etats/ etc comme repertorié dans le tableau ci dessus,


                    Tout à fait. C'est même recommandé, car étant débutant en C, je ne te vois pas utiliser d'autres méthodes plus, disons avancées, ça paraitrait chelou...

                    Citation : Pas de titre


                    mais, comment ensuite définir chaque action...


                    Tu fais une fonction par action que tu appelles dans les bonnes branches du switch-case. On règlera les problèmes des paramètres lors de l'implémentation (pas de globales, beark!)

                    Il faut un niveau C de base. Rien de bien méchant.

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Music only !
                      18 janvier 2007 à 18:58:54

                      Citation : ed


                      Woaw ! Je suis impressionné. En général, quand le parle de FSM, on prend pour un martien...



                      Du moment que c'est pas de l'ironie tout va bien :p


                      Bon je fait mon "switch-case",
                      j'essaie de faire les actions dans des fonctions,
                      si j'ai un probleme je sais ou m'adresse ;)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        18 janvier 2007 à 19:05:35

                        Citation : sam_fra

                        Citation : ed


                        Woaw ! Je suis impressionné. En général, quand le parle de FSM, on prend pour un martien...



                        Du moment que c'est pas de l'ironie tout va bien :p


                        Non, c'est pas du tout ironique. Très rares sont les gens qui comprennent les FSM du premier coup...
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Music only !
                          18 janvier 2007 à 19:43:09

                          Mmh,

                          je coince,
                          j'ssaie de comprendre le code là, mais par exemple
                          switch (etat_courant)

                          Je ne comprend pas: "etat_courant" correspond à quoi?
                          pareil

                          switch (evenement)
                          à quoi correspond "evenement"?

                          (j'ai laissé tel quel dans le bout de code:)
                          {
                           
                             switch (etat_courant)
                             {
                             case INIT:

                                switch (evenement)
                                {
                                case ETAT_0:
                                   /* changement d'etat */
                                   etat_courant = WAIT_1;

                                   /* action */
                                   action (ACT_1);
                                   break;

                                case ETAT_1:
                                  /* changement d'etat */
                                   etat_courant = WAIT_0;

                                   /* action */
                                   action (ACT_1);
                                   break;
                                }
                                break;

                             case WAIT_0:

                                switch (evenement)
                                {
                                case ETAT_0:
                                   /* changement d'etat */

                                   /* action */
                                   break;

                                case ETAT_1:
                                   /* changement d'etat */
                                    etat_courant = WAIT_1;
                                   
                                   /* action */
                                   action (ACT_2);
                                   break;
                                }
                                break;

                             case WAIT_1:

                                switch (evenement)
                                {
                                case ETAT_0:
                                   /* changement d'etat */
                                    etat_courant = WAIT_0;
                                   
                                   /* action */
                                   break;

                                case ETAT_1:
                                   /* changement d'etat */

                                   /* action */
                                   
                                   break;
                                }
                                break;
                             }
                           
                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 janvier 2007 à 23:18:57

                            Citation : sam_fra


                            je coince,
                            j'ssaie de comprendre le code là, mais par exemple

                            switch (etat_courant)


                            Je ne comprend pas: "etat_courant" correspond à quoi?


                            C'est l'état de la machine. Au démarrage, c'est INIT (ce que j'avais appelé 'INITIAL'). Il faut donc donner la valeur INIT à cette variable avant de démarrer la boucle. En suite, en fonction de l'évènement, l'état va évoluer.

                            Citation : Pas de titre


                            pareil


                            switch (evenement)

                            à quoi correspond "evenement"?


                            C'est ce qui va faire évoluer l'état. Ici, c'est le résultat de la lecture de l'état du port : 0 ou 1 qui est évalué à chaque tour de boucle. (Ce que tu as appelé ETAT_0 et ETAT_1).

                            Oui, c'est un peu confusant qu'un évènement s'appele ETAT...

                            En principe, je met le préfixe EVT_ aux évènements et STS_ aux états.

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Music only !
                              20 janvier 2007 à 19:21:48

                              Bon maintenant, il me faut une fonction qui fera ACT_1 et qui sera appelée quand besoin est, pareil pour ACT_2

                              commençons par la plus simple, c'est à dire ACT_1 qui doit:
                              _mettre le compteur à 0
                              _noter l'heure

                              ->Pour mettre le compteur à 0 rien de plus facile, je choisis un nom de variable pour le compteur, et je fais = 0 (mais cette variable devra être réutilisable dans la fonction corespondant à ACT_2 , il faut donc une variable "static", mais -ed- à l'air de vouloir dire non?)
                              ->Pour noter l'heure, je fais #include <time.h> en haut du fichier,
                              puis, je n'ai pas bien compris par exemple ici , car il y a la notion de pointeur,
                              et apres avoir relu le cours de mateo, j'ai pas compris a 100%

                              Citation : ...

                              time_t time(time_t *t);

                              Hein?
                              et dans le cours de mateo SDL est utilisé pour les timers donc bon...


                              car après dans la fonction ACT_2 je devrai comparer le temps actuel au temps noté dans la fonction ACT_1
                              donc le temps est une partie essentielle du programme

                              • Partager sur Facebook
                              • Partager sur Twitter
                                20 janvier 2007 à 19:39:05

                                Citation : sam_fra


                                commençons par la plus simple, c'est à dire ACT_1 qui doit:
                                _mettre le compteur à 0
                                _noter l'heure

                                ->Pour mettre le compteur à 0 rien de plus facile, je choisis un nom de variable pour le compteur, et je fais = 0 (mais cette variable devra être réutilisable dans la fonction corespondant à ACT_2 , il faut donc une variable "static", mais -ed- à l'air de vouloir dire non?)


                                Comme tu débutes en C, fait comme tu le sens. On te montreras comment le faire d'une façon plus 'professionnelle' après.

                                Citation : Pas de titre


                                ->Pour noter l'heure, je fais #include <time.h> en haut du fichier,


                                Puis tu lis l'heure courante que tu stockes dans un time_t qui est fait pour ça :
                                  time_t heure = time(NULL);

                                Citation : Pas de titre


                                car après dans la fonction ACT_2 je devrai comparer le temps actuel au temps noté dans la fonction ACT_1
                                donc le temps est une partie essentielle du programme


                                Pour faire un fréquencemètre (F = 1/T), y'a des chances !

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Music only !
                                  20 janvier 2007 à 20:01:28


                                  void ACT_1()                        //Fonction de l'action 1
                                  {
                                      static int compteur = 0;        //Met le compeur à 0
                                      time_t old = time(NULL);        //note le temps actuel
                                  }


                                  j'ai mis time_t "old"
                                  pour pouvoir ensuite comparer un time_t "now"
                                  faut il aussi mettre static devant time_t ?
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    20 janvier 2007 à 20:20:07

                                    Citation : sam_fra


                                    void ACT_1()                        //Fonction de l'action 1
                                    {
                                        static int compteur = 0;        //Met le compeur à 0
                                        time_t old = time(NULL);        //note le temps actuel
                                    }



                                    j'ai mis time_t "old"
                                    pour pouvoir ensuite comparer un time_t "now"
                                    faut il aussi mettre static devant time_t ?


                                    Bonne question. Tu as besoin de données persistantes. La méthode officielle, c'est de les placer dans une structure (Accelerated C lesson inside) :

                                    struct data
                                    {
                                        int compteur;
                                        time_t old;
                                    };

                                    de définir une instance dans le main() :
                                    int main (void)
                                    {
                                       struct data data;

                                    de passer l'adresse de la structure aux fonctions :

                                       act_0 (&data);
                                    ...
                                       act_1 (&data);

                                    de définir les fonctions avec un paramètre pointeur sur la structure :
                                       act_0 (struct data *p_data)

                                    et enfin d'accéder correctement aux données avec -> :

                                    // Fonction // Oui, on sait ce qu'est une fonction
                                    // de l'action 1 // Ben oui, c'est écrit...
                                    // Encore une action de la campagne contre les commentaires inutiles
                                    void act_1(struct data *p_data)
                                    {
                                        p_data->compteur = 0;        //Met le compteur à 0 // sans blague ?
                                        p_data->old = time(NULL);    //note le temps actuel // OK
                                    }

                                    Je t'ai offert un cours de C accéléré parce que tu ne m'as pas l'air d'être un abruti... Ca ne te dispense pas de poser des questions...
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Music only !
                                      20 janvier 2007 à 21:57:04

                                      ok merci pour tout ce petit cour

                                      mmh les commentaires, j'exagère un peu car il faut que j'explique a mon coequipier encore moins avancé que moi en C, et que j'explique simplement à des examinateurs qui ne connaissent pas forcément bien le C (genre prof de mécanique, ...)
                                      et ça ne coute RIEN :p

                                      Citation : ed




                                      act_0 (&data);
                                      ...
                                      act_1 (&data);



                                      juste une chose ça se met ou ça?
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        23 janvier 2007 à 18:28:30

                                        struct data                        //Structure pour variables
                                        {
                                            int compteur;
                                            time_t old;
                                            time_t now;
                                            int differenceTemps;;
                                            int vitesse;
                                        };



                                        void act_1(struct data *p_data)
                                        {
                                            p_data->compteur = 0;        //Met le compteur à 0
                                            p_data->old = time(NULL);    //note le temps actuel
                                        }

                                        void act_2(struct data *p_data)
                                        {
                                            p_data->compteur ++;        //J'incrémente le compteur
                                            p_data->now = time(NULL);    //note le temps actuel
                                            p_data->differenceTemps = p_data->now - p_data->old;  // difference entre temps actuel temps enregsistré avant
                                            if (p_data->differenceTemps >= 1000) // si difference de 1000 ms ou plus alors
                                        {
                                          p_data->old = time(NULL)// note heure actuelle
                                          p_data->vitesse = p_data->compteur * 2.5;
                                          printf("Il y a %ld Km/h de vent!", p_data->vitesse);    //afficher vitesse
                                          p_data->compteur = 0// met compteur à 0
                                          p_data->vitesse = 0;
                                          p_data->differenceTemps = 0;
                                        }
                                        }


                                        J'ai fait ça...

                                        par contre,

                                        int main (void)
                                        {
                                           struct data data;


                                        A quoi sert de mettre void dans les parametres de la fonction main?
                                        j'ai fait ça perso:

                                        int main(void)                   //, int argc, char *argv[] : viré

                                        {
                                            {
                                            struct data data;
                                            act_1 (&data);
                                            act_2 (&data);
                                            };
                                           
                                            etat_courant = INIT;
                                        ...................
                                        .......
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          23 janvier 2007 à 18:38:44

                                          Citation : sam_fra

                                          J'ai fait ça...


                                          Pas mal. Manque un '\n' à la fin du printf().

                                          EDIT : Il y a un peu trop de monde dans la structure On n'y met que ce qui est persistant. Ce qui est calculé, on s'en tape. Ca peut être local. Pour la vitesse, utilise un type double et affiche le avec "%f" (ou "%.2f").

                                          Tu devrais t'en tirer avec :
                                          /* Structure pour variables persistantes */
                                          struct data
                                          {
                                              int compteur;
                                              time_t old;
                                          };

                                          Citation : Pas de titre


                                          par contre,


                                          int main (void)
                                          {
                                             struct data data;



                                          A quoi sert de mettre void dans les parametres de la fonction main?


                                          Pour dire qu'il n'y a pas de paramètres.

                                          Citation : Pas de titre


                                          j'ai fait ça perso:


                                          int main(void)                   //, int argc, char *argv[] : viré

                                          {
                                              {
                                              struct data data;
                                              act_1 (&data);
                                              act_2 (&data);
                                              };
                                             
                                              etat_courant = INIT;
                                          ...................
                                          .......


                                          Non (ou alors c'est extrêmement partiel). act_1() et act2() doivent être appelées par la machine à état qu'on avait définie précédemment. C'est un tout...

                                          Mais la façon d'appeler les fonctions est correcte.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Music only !
                                            23 janvier 2007 à 18:47:12

                                            ok donc il vaut mieux que à chaque fois qu'il y a ça:
                                            /* action */
                                                     action (ACT_1);


                                            je remplace par


                                            /* action */
                                                     action (act_1(&data));
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              23 janvier 2007 à 19:30:37

                                              Citation : sam_fra

                                              ok donc il vaut mieux que à chaque fois qu'il y a ça:

                                              /* action */
                                                       action (ACT_1);



                                              je remplace par



                                              /* action */
                                                       action (act_1(&data));

                                              Hum, par
                                                       /* action */
                                                       act_1(&data);

                                              Tout simplement. Tu es sûr d'avoir compris le code ? Ne fait rien que tu ne maitrises pas. Si il faut réexpliquer, c'est toujours possible.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Music only !
                                                23 janvier 2007 à 19:49:57

                                                non j'ai bien compris c'est pas ça je pensais qu'il existait dans switch une commande action() qui declenchait ce qu'on aurait mis (...)

                                                si tu me dis que si je met
                                                   /* action */
                                                         act_1(&data);


                                                la fonction act_1 sera déclenchée au moment ou la condition switch-case sera remplie

                                                tout va bien ;)


                                                par contre maintenant il faut definir
                                                les evenements
                                                c'est la partie "lecture du port //"
                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                [C/C++]Acquisition d'une fréquence venant du port COM

                                                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                • Editeur
                                                • Markdown