Pages: [1]   Go Down
Author Topic: Generateur de fréquences  (Read 4637 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Voici un générateur de fréquence de 30hz à 8Mhz qui se pilote par deux boutons poussoir et un potentiomètre de 1k il peut être piloté par la liaison série, et dispose d'un afficheur deux lignes.

En espérant que sa peut aider pour un projet.
Code:
#include <LiquidCrystal.h>
int PRESCALER=0;
int PRESC=0;
int PCPResk;
int plus=0;
int moin=0;
int plusa=0;
int moina=0;
float Frekpc=0;
unsigned long Frek=0;
unsigned long FREQ=0;
unsigned long FOC=0;
LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(11, OUTPUT); //sortie fréquence
  pinMode(9, OUTPUT);  //bouton poussoir
  pinMode(8, OUTPUT); //bouton poussoir
 
  //configuration timer
  //mise à zéro des registres
  TCCR2B = 0;
  TCCR2A = 0;
 
  TCCR2A = ( 1<<WGM21/*ctc mode*/ | 1<<COM2A0 /*toggle mode*/  );
  TCCR2B = (  1<<CS20   |  1<<CS22 |  1<<CS21 /* prescaler */);
  //valeur a compter dans tcnt2

 
  //autorisation d'interruption
   ASSR &= ~(1 << AS2);        // horloge interne Timer/Counter2
   Serial.println("pour passer en mode commande pc");
   Serial.println("définir une fréquence en hz et finir par un .");

}
 
 /***génération de fréquence par potentiomètre***/

void loop()
{
  TCCR2A = ( 1<<WGM21/*ctc mode*/ | 1<<COM2A0 /*toggle mode*/  );
  int OCR2 = analogRead(A0);  //lecture du potentiomètre
  OCR2=OCR2/4;                //résultat sur 1024 /4 pour 256
  OCR2A=OCR2;
 
  plus = digitalRead(8);    //lecture du bouton poussoir

  if(plus !=plusa ){      //si changement d'état
 
    if(plus == HIGH ){   
       
      PRESCALER++;        //sélection du prescaler suivant
    }

    plusa = plus;        //mise à zéro du changement d'état

  }

  if(PRESCALER > 6 ){        //maximum à ne pas dépasser
  PRESCALER = 6 ;
}

  moin = digitalRead(9);    //lecture du bouton poussoir
 
  if(moin !=moina ){        //si changement d'état
     
      if(moin == HIGH ){  //et si passage a un
       
      PRESCALER--;          //sélection du prescaler précédant
     
       }
       
     moina = moin;      //mise à zéro du changement d'état
  }
 
 
if(PRESCALER < 0 ){        //minimum à ne pas dépasser
  PRESCALER = 0 ;
}

  switch (PRESCALER) //sélection du prescaler
  {
  case 0:
  TCCR2B = (  1<<CS20   |  1<<CS22 |  1<<CS21 );
  PRESC = 1024;            //valeur du prescaler
  break;
 
  case 1:
  TCCR2B = (   1<<CS22 |  1<<CS21 );
  PRESC = 256;            //valeur du prescaler
  break;
 
  case 2:
  TCCR2B = (  1<<CS20   |  1<<CS22  );
  PRESC = 128;              //valeur du prescaler
  break;
 
  case 3:
  TCCR2B = ( 1<<CS22  );
  PRESC = 64;              //valeur du prescaler
  break;
 
  case 4:
  TCCR2B = (  1<<CS20   |  1<<CS21  );
  PRESC = 32;              //valeur du prescaler
  break;
 
  case 5:
  TCCR2B = (  1<<CS21  );
  PRESC = 8;              //valeur du prescaler
  break;
 
  case 6:
  TCCR2B = (  1<<CS20  );
  PRESC = 1;          //valeur du prescaler
  break;
   
  }
 /***foc= fcryst/(2*prescaler*(1+ocr)***/
  OCR2=OCR2+1;      //préparation au calcul de fréquence ci dessus
 
  FOC=long(OCR2)*long(PRESC)*2;    //changement de type de variable et multiplication

  FREQ=16000000/FOC;      //division de la fréquence du cristal

  aff();             //affichage sur l'écran lcd

  delay(2);                        //petit délai pour la mesure analogique par sécurité
   
   if (Serial.available() > 0) {
     PCC(); 
  }
}
 
 /***affichage lcd***/

void aff(){
  lcd.print("frequence");
  lcd.setCursor(0, 1);
  lcd.print(FREQ);
  lcd.print("hz            ");
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
/***sélection de fréquence par liaison série***/
void PCC(){
  int FIN= 0;
  int j =8;
  int calc = 0;
  int tab;
  int Tab;
  int X;
  int selection = 0;
  int bp2=0;
  unsigned long U=1;
  do{
  Frek = 0;     
  Serial.println("définir une fréquence et finir par un .");
  byte tableau[11] = {};        //tableau ou je vais mettre les valeurs
     
 do
     {        //remplissage du tableau
                 
             if (Serial.available() > 0) { //si des données entrantes sont présentes

               tableau[j]= Serial.read();  //remplissage du tableau
               calc++;                      //incrémentation du nombre de case utilisées
                                     
                       if (tableau[j]== '.') {                //sortie si on reçois le point
                                             j=0;
                                             }
                                           
                                           j--;
                                           }
                 
              }while(j>0);
             
              do{                                 
             
              Tab=calc-1;      //ordre de passage
              tab = Tab-1;      //nombre de passage
             
              while(tab>0) {
                            U=U*10;          //mise à niveau des centaines dizaines unités
                            tab--;
                            }
             
           
                 j=8;          //on commence à l'emplacement 7 du tableau ou se trouve la première donnée (et non pas 0)
                              //création de la valeur
                             
              do                {

                                Frek = Frek+(tableau[j]-48)*U;  //calcul de la fréquence, le -48 car il garde la désignation ascii
                                U=U/10;                          //toujours les centaines dizaines unités
                                j--;
                                Tab--;
                                }while(Tab>0);
                 Serial.println(Frek);
             
              }while(FIN>0);   
             
          //configuration timer
            //mise à zéros des registres
            TCCR2B = 0;
            TCCR2A = 0;
           
           
            if(Frek > 0 && Frek <= 400){
              selection=1;
            }
            else if (Frek > 400 && Frek <= 1500){
              selection=2;
            }
            else if (Frek > 1500 && Frek <= 3000){
              selection=3;
            }
            else if (Frek > 3000 && Frek <= 6000){
              selection=4;
            }
            else if (Frek > 6000 && Frek <= 13000){
              selection=5;
            }
            else if (Frek > 13000 && Frek <= 50000){
              selection=6;
            }
            else if (Frek > 50000 && Frek <= 8000000){
              selection=7;
            }
 switch (selection) { //foc= fcryst/(2*prescaler*(1+ocr)     calcul a appliquer
                //1+0cr = fcryst/(foc*presc)
                //ocr+1
                //ocr-1=(foc*presc*2)/fcryst

              case (1):
              //première plage de sélection
                                  TCCR2B = ( 1<<CS22 | 1<<CS21 | 1<<CS20 /* prescaler  111 1024*/);
                                  PCPResk=1024;
                                  PCCPR();
                                  break;

              case (2):         
                                 
                                 TCCR2B = ( 1<<CS22 | 1<<CS21 /* prescaler  110 256*/);
                                 PCPResk=256;
                                 PCCPR();
                                  break;
              case (3):         
                                 
                                 TCCR2B = ( 1<<CS22 | 1<<CS20 /* prescaler  101 128*/);
                                 PCPResk=128;
                                 PCCPR();
                                  break;
              case (4):         
                                 
                                 TCCR2B = ( 1<<CS22  /* prescaler  100 64*/);
                                 PCPResk=64;
                                 PCCPR();
                                  break;
              case (5):         
                                 
                                 TCCR2B = ( 1<<CS21 | 1<<CS20 /* prescaler  011 32*/);
                                 PCPResk=32;
                                 PCCPR();
                                  break;   
              case (6):         
                                 
                                 TCCR2B = ( 1<<CS21 /* prescaler  010 8*/);
                                 PCPResk=8;
                                 PCCPR();
                                  break;
              case (7):         
                                 
                                 TCCR2B = ( 1<<CS20 /* prescaler  001 1*/);
                                 PCPResk=1;
                                 PCCPR();
                                  break;                           
            }
           
 Serial.println("pour sortir du mode commande pc");           
 Serial.println("envoyer un . en appuyant sur les 2"); 
 Serial.println("bouton poussoir ou"); 
 plus = digitalRead(8);    //lecture du bouton poussoir
 moin = digitalRead(9);    //lecture du bouton poussoir

    if(plus == HIGH && moin == HIGH ){    //si les deux sont haut retour au mode manuel
     bp2 = 1;
    }   
  }while(bp2 != 1);
 
}
 

 /***calcul de l'ocr***/       

/***********calcul de l'ocr*************/       

void PCCPR(){
  int OCR2;
  TCCR2A = ( 1<<WGM21/*ctc mode*/ | 1<<COM2A0 /*toggle mode*/  );
  Frekpc = (Frek*PCPResk*2);
  Frekpc = 16000000/Frekpc;                               
  Frekpc = --Frekpc;
  OCR2A=Frekpc;                              //calcul de l'ocr
 
  OCR2=OCR2A;
  OCR2=OCR2+1;                              //préparation au calcul de frequence
  FOC=long(OCR2)*long(PCPResk)*2;    //changement de type de variable et multiplication
  FREQ=16000000/FOC; 
  aff();                                           //afichage sur l'ecran lcd
 
  PCC();                         //retour à  la detection
 
}

avec un petit schéma


* LCD_bb.png (58.53 KB, 621x1012 - viewed 174 times.)
« Last Edit: May 09, 2012, 02:38:28 am by zelange » Logged

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 23
Posts: 2054
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci de partager.

N'oublie pas que pour les gros sources, tu peux attacher directement le fichier (en bas de la zone de saisie du texte, "Advanced...")
Logged

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

83 - var
Offline Offline
God Member
*****
Karma: 4
Posts: 769
ARDUINO Powa !
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci de partage c'est utile ça je viens de voir un petit topic qui réclame sa justement ! smiley

Skizo !
Logged

Un tien vaux mieux que deux tu l'auras !

Offline Offline
Faraday Member
**
Karma: 19
Posts: 4180
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Voici un générateur de fréquence de 30hz à 8Mhz qui se pilote par deux boutons poussoir et un potentiomètre de 1k il peut être piloté par la liaison série, et dispose d'un afficheur deux lignes.

En espérant que sa peut aider pour un projet.

bonsoir
interessant
je l'ai testé rapidement sur uno avec le serial (pas de lcd ,pas de potentiometre et pas de poussoir)
verif sur fréquencemètre
sauf erreur de ma part, voilà ce que cela rend pour moi
500000 = ok 0.5Mhz
1000000 =0k 1Mhz
2000000 =ok 2Mhz
3000000 = Nok 4Mhz
4000000 = Ok 4Mhz
5000000 , 6000000,7000000 Nok = 8Mhz
8000000 = Ok 8Mhz


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oui c'est vraie je l'utilise sur un uno et j'ai se problème mais il viens justement du calcul qui permet de rentré une fréquence :
 foc= fcryst/(2*prescaler*(1+ocr)
 1+0cr = fcryst/(foc*presc)
 ocr+1
 ocr-1=(foc*presc*2)/fcryst
en fait on obtient un chiffre à <,> mais le registre ocr ne peut pas le prendre en compte du coup il arrondie et sur les grosse fréquence c'est flagrant.
Aprés on touche au fonctionnement des registres de timer, le prescaler lui décide de l'horloge interne et donc si tu met un prescaler de un
tu obtient 8MHZ. Ton ocr lui est le nombre d’impulsion que doit compter le timer,

donc si tu compte qu'une impulsion =>8MHZ
-deux impulsions on tombe à 4 MHZ immédiatement il n'y auras pas d’intermédiaire.

mais si quelqu'un à une idée je suis preneur  smiley-kitty
« Last Edit: May 03, 2012, 01:14:03 am by zelange » Logged

Offline Offline
Faraday Member
**
Karma: 19
Posts: 4180
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oui c'est vraie je l'utilise sur un uno et j'ai se problème mais il viens justement du calcul qui permet de rentré une fréquence :
 foc= fcryst/(2*prescaler*(1+ocr)
 1+0cr = fcryst/(foc*presc)
 ocr+1
 ocr-1=(foc*presc*2)/fcryst
en fait on obtient un chiffre à <,> mais le registre ocr ne peut pas le prendre en compte du coup il arrondie et sur les grosse fréquence c'est flagrant.
Aprés on touche au fonctionnement des registres de timer, le prescaler lui décide de l'horloge interne et donc si tu met un prescaler de un
tu obtient 8MHZ. Ton ocr lui est le nombre d’impulsion que doit compter le timer,

donc si tu compte qu'une impulsion =>8MHZ
-deux impulsions on tombe à 4 MHZ immédiatement il n'y auras pas d’intermédiaire.

mais si quelqu'un à une idée je suis preneur  smiley-kitty


bonjour
c'est donc ce que l'on appelle un generateur de frequence discrete.
Il me semble aussi avoir vu des "aberrations" intermédiaires entre 2 valeurs OK, je regarderais ça plus tard.
ce qui serait intéressant dans ton soft, ce serait de determiner la F° la plus proche de celle demandée et d'afficher le résultat par la fonction inverse.
ça n’enlève rien à l'utilité de ta réalisation : lorsque l'on connait les limitations, il est plus simple d'integrer ensuite avec.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

je vais plancher dessus, à noter que sa n'arrive que sur la commande usb la commande par potentiomètre et boutons poussoir est plus précise et ne prend pas le calcul de fréquence à l'envers.
Logged

France
Offline Offline
Faraday Member
**
Karma: 23
Posts: 3019
There is an Arduino for that
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
à noter que sa n'arrive que sur la commande usb la commande par potentiomètre et boutons poussoir est plus précise
Je ne vois pas pourquoi. Le problème viens de l'architecture des timers avec les prescalers. Il n'y a pas de pas possible entre 4MHz et 8MHz et ce quelque soit le mode d'entrée de la consigne. En fait plus tu approches de la fréquence de base de la chaine de comptage plus le pas est grossier.
Pour pouvoir faire "toutes les fréquences" (toutes à prendre avec certaines réserves) il faut soit partir d'une fréquence très élevée (le principe de la synthèse digitale de fréquence DDS) soit utiliser une PLL.

Cela dit, ça n'enlève rien à ton montage. Quand on connait ses limitations on peut l'utiliser sans problème.
« Last Edit: May 04, 2012, 07:10:37 am by fdufnews » Logged

Offline Offline
Faraday Member
**
Karma: 19
Posts: 4180
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

je vais plancher dessus, à noter que sa n'arrive que sur la commande usb la commande par potentiomètre et boutons poussoir est plus précise et ne prend pas le calcul de fréquence à l'envers.
bonjour
je n'ai pas regardé le code, mais intuitivement
la F° est generée par action sur les registres de l'arduino  (scaler/prescaler, ...) , que l'action soit issue des BP et/ou d'une valeur ana, et/ou initialisée par le serial , c'est equivalent , tu dois donc toujours pouvoir "recalculer" la F° genérée en fonction de l'ecriture des registres ?

edit : je viens de voir que fdufnews et moi convergeons presque synchrone à l'identique  smiley-mr-green
« Last Edit: May 04, 2012, 07:15:37 am by Artouste » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Se que je voulais dire c'est qu'il n'affiche pas 5mhz si on le règle entre les deux, il affiche la fréquence à partir de l'ocr et du prescaler tandis que par usb on peut demander 5mhz, et il affichera 5mhz même si il ne peut pas et qu'il est soit à 8 soit à 4...

J'ai mise à jour le programme, plus particulièrement la fonction PCCPR l'écran lcd affichera la bonne fréquence maintenant.
« Last Edit: May 09, 2012, 02:40:30 am by zelange » Logged

KARUKERA 971
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ca marche super ....  smiley

Je l'ai adapté pour l'utiliser avec un LCD Serial de Lextronic (avec interface Comfile ELCD pas compatible avec la librairie LiquidCrystal) sans problème.




« Last Edit: May 13, 2012, 05:28:21 pm by PhilippeFromGpe » Logged

42 est la réponse


Décompresse en Hook2 et monster1100

Pages: [1]   Go Up
Jump to: