Partage
  • Partager sur Facebook
  • Partager sur Twitter

Generer Sinusoide Timer1 Arduino

Problème avec Serial.begin et frequence

    19 juillet 2018 à 16:21:27

    Bonjour à tous,

    j'ai crée un programme très simple pour générer une sinusoïde avec le Fast PWM sur la broche 9 de l'Arduino uno. j'utilise le prescaler 1 pour atteindre les 62500Hz pour la porteuse (signal PWM modulé en frequence) que je filtre par la suite avec un circuit LC. En sortie, pour un échantillon de 50 valeurs de sinus, j'obtiens une belle sinusoïde de 50Hz. deux questions :

    1 - il y a un hic ! si je ne déclare pas au Void Setup Serial. begin(115200), ou une autre vitesse, et que je ne mets pas en Void loop Serial. Print ce n'est pas une sinusoide que j'obtiens mais un signal qui ne veut rien dire. je ne comprends pas la relation !

    2 - logiquement avec une porteuse à 62500Hz et 50 echantillons de periode 16us, soit 800ms (50x16), je devrais obtenir un signal à 1.25khz et non 50hz !

    je précise que mes échantillons de 50 valeurs de sinus sont calculés dans une "boucle for" dans le setup et sont lus dans le loop avec une "boucle for" également.

    Merci de votre retour. Cordialement.

    • Partager sur Facebook
    • Partager sur Twitter
      19 juillet 2018 à 16:43:51

      Pourrais tu mettre ton code histoire que l'on puisse voir comment tu fais ta sinus et ton échantillonnage ?
      • Partager sur Facebook
      • Partager sur Twitter
        19 juillet 2018 à 22:55:27

        Bonsoir,

        merci pour ton retour rapide. voici le code en dessous de l'image de la sinusoide.

        PWM et sinus

        const int NbEch=50;
        
        int TabSin[NbEch];
        
        
        
        
        
        void setup() {
        
            //Serial.begin(250000);
        
            for(int i=0;i<NbEch;i++){
        
            TabSin[i]=(5+5*sin(2*3.14*i/NbEch))*255/10;
        
            }
        
          pinMode(9,OUTPUT);
        
          pinMode(10,OUTPUT);
        
          TCCR1A=0;
        
          TCCR1B=0;
        
          TCCR1A|=(1<<WGM10) | (1<<COM1A1)| (1<<COM1B1);// WGM10 pour Fast PWM sur Broche 9 et 10 et COM1A1 et COM1B1 pour non inverseur
        
          TCCR1B|=(1<<CS10) | (1<<WGM12);// Prescaler mis à 1 pour atteindre 62500HZ. WGM12 à 1 pour mode Fast PWM 8bits (WGM12,WGM11,WGM10 ==> 1,0,1).
        
        }
        
        
        
        void loop() {
        
          for (int i=0; i<NbEch;i++){
        
          OCR1A= TabSin[i];
        
          Serial.println(TabSin[i]);
        
          }
        
        }



        c'est surtout le serial.print que je suis obligé de rajouter pour obtenir ma sinusoide.

        bien à toi.

        • Partager sur Facebook
        • Partager sur Twitter
          20 juillet 2018 à 8:22:20

          L'arduino tourne a 16 MHz donc il est capable d'exécuter 16 millions d’instructions par secondes.

          Pour ta boucle for, on a probablement :

          • une instruction pour le ++
          • une instruction pour la comparaison
          • une instrction pour l'affectation de OCR1A
          • une instruction pour revenir au début de la boucle for

          En une seconde, ton programme a donc exécuté 4 millions de fois ces instructions donc 4 millions de changement de valeur de PWM.

          Vu qu'il y a 50 échantillons, cela va donc générer 80000 sinus complètes et donc un signal théorique de 80 kHz.

          Mais comme ton PWM n'est qu'à 62 kHz, tu n'obtiendras forcément rien de bien constructif.

          ---

          Par contre, en ce qui concerne print, il s'agit d'une fonction potentiellement bloquante quand le buffer est plein.

          Avec une vitesse de 115200, il faut 0.086ms pour afficher une caractère, ce qui ralenti considérablement ta boucle.

          Suivant qu'il y a un, deux ou trois chiffre à afficher, cela prend plus ou moins de temps, d'où le fait que ta sinus soit un peu en forme de patate.

          ---

          Il te faut mettre un delay pour avoir quelque chose de correct.

          void loop() {
           
            for (int i=0; i<NbEch;i++){
           
            OCR1A= TabSin[i];
           
            delayMicroseconds(500);
           
            }
           
          }

          Si l'on néglige le temps des autres instructions, on peut même avoir une fréquence précise en calculant le delay :

          unsigned long freq = 50;
          
          unsigned long dly = ( ( 1000000uL / freq ) / NbEch )
          
          void loop() {
           
            for (int i=0; i<NbEch;i++){
           
            OCR1A= TabSin[i];
           
            delayMicroseconds(dly);
           
            }
           
          }




          -
          Edité par lorrio 20 juillet 2018 à 10:01:00

          • Partager sur Facebook
          • Partager sur Twitter
            20 juillet 2018 à 9:32:33

            Merci Lorrio,

            tes explications m'aident beaucoup. le delay j y ai pensé comme piste en lieu et place de Serial.Print. tu me le confirmes dans ton message. 

            je vais également remplacer le tableau avec des valeurs fixes au lieu de les calculer dans la boucle for, cela devrait en principe permettre de gagner du temps.

            je vais également essayer d'augmenter la fréquence de traitement actuelle de 62.5khz en utilisant ICR pour monter au maximum de la fréquence (entre 1 et 8Mhz)

            bonne journée.

            • Partager sur Facebook
            • Partager sur Twitter
              20 juillet 2018 à 10:00:26

              Le tableau fixe ne t'apportera pas grand chose si n'est une fraction de seconde gagnée au démarrage.

              En effet, la fonction setup n'est exécutée qu'une seule fois au démarrage.

              Du coup, le processeur va perdre un peu de temps au début pour calculer les valeur et les stocker dans la mémoire TabSin.

              Puis une fois les calculs fait, il va exécuter loop en boucle sans refaire les calculs donc aucun gain de temps par rapport à un tableau pré calculé.

              • Partager sur Facebook
              • Partager sur Twitter
                20 juillet 2018 à 10:37:47

                Ok, Merci

                je fais les modifs ce soir et te tiens au courant.

                BAT

                • Partager sur Facebook
                • Partager sur Twitter

                Generer Sinusoide Timer1 Arduino

                × 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