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.
#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 ");
}
/***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
}
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
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/(2prescaler(1+ocr)
1+0cr = fcryst/(focpresc)
ocr+1
ocr-1=(focpresc*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.
zelange:
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/(2prescaler(1+ocr)
1+0cr = fcryst/(focpresc)
ocr+1
ocr-1=(focpresc*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
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.
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.
à 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.
zelange:
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
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.
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.
Bonjour,
je travaille actuellement sur un projet de génération de fréquences sur Arduino.Est ce que vous pourriez me dire ce que c'est la carte se trouvant avec l'Arduino?